Что означает конструкция x = x || значит? - PullRequest
216 голосов
/ 10 мая 2010

Я отлаживаю некоторый JavaScript, и не могу объяснить, что делает ||?

function (title, msg) {
  var title = title || 'Error';
  var msg   = msg || 'Error on Request';
}

Может кто-нибудь дать мне подсказку, почему этот парень использует var title = title || 'ERROR'?Иногда я вижу это и без var декларации.

Ответы [ 11 ]

188 голосов
/ 10 мая 2010

Это означает, что аргумент title является необязательным. Поэтому, если вы вызываете метод без аргументов, он будет использовать значение по умолчанию "Error".

Это сокращение от записи:

if (!title) {
  title = "Error";
}

Этот вид укороченного трюка с логическими выражениями также распространен в Perl. С выражением:

a OR b

оценивается как true, если a или b равны true. Поэтому, если a истинно, вам вообще не нужно проверять b. Это называется логической оценкой короткого замыкания так:

var title = title || "Error";

в основном проверяет, оценивается ли title как false. Если это так, он «возвращает» "Error", в противном случае он возвращает title.

163 голосов
/ 10 января 2016

Что такое оператор двойной трубы (||)?

Оператор двойной трубы (||) - это логический оператор OR . В большинстве языков это работает следующим образом:

  • Если первое значение false, оно проверяет второе значение. Если это true, возвращается true, а если false, возвращается false.
  • Если первое значение true, оно всегда возвращает true, независимо от того, какое второе значение.

Так что в основном это работает так:

function or(x, y) {
  if (x) {
    return true;
  } else if (y) {
    return true;
  } else {
    return false;
  }
}

Если вы все еще не понимаете, посмотрите на эту таблицу:

      | true   false  
------+---------------
true  | true   true   
false | true   false  

Другими словами, это только ложь, когда оба значения ложны.

Чем он отличается в JavaScript?

JavaScript немного отличается, потому что это свободно типизированный язык . В этом случае это означает, что вы можете использовать оператор || со значениями, которые не являются логическими. Хотя это не имеет смысла, вы можете использовать этот оператор, например, с функцией и объектом:

(function(){}) || {}

Что там происходит?

Если значения не булевы, JavaScript делает неявный разговор с булевыми . Это означает, что если значение равно Falsey (например, 0, "", null, undefined (см. Также Все значения Falsey в JavaScript )), оно будет рассматриваться как false ; в противном случае он рассматривается как true.

Таким образом, приведенный выше пример должен дать true, потому что пустая функция верна. Ну, это не так. Возвращает пустую функцию. Это потому, что оператор JavaScript || не работает, как я писал в начале. Работает следующим образом:

  • Если первое значение falsey , возвращается второе значение .
  • Если первое значение истинно , возвращается первое значение .

Удивлены? На самом деле, он «совместим» с традиционным оператором ||. Это можно записать в виде следующей функции:

function or(x, y) {
  if (x) {
    return x;
  } else {
    return y;
  }
}

Если вы передаете истинное значение как x, оно возвращает x, то есть истинное значение. Так что если вы используете его позже в if предложении:

(function(x, y) {
  var eitherXorY = x || y;
  if (eitherXorY) {
    console.log("Either x or y is truthy.");
  } else {
    console.log("Neither x nor y is truthy");
  }
}(true/*, undefined*/));

вы получите "Either x or y is truthy.".

Если бы x было ложным, eitherXorY было бы y. В этом случае вы получите "Either x or y is truthy.", если y будет правдой; в противном случае вы получите "Neither x nor y is truthy".

Актуальный вопрос

Теперь, когда вы знаете, как работает оператор ||, вы, вероятно, сможете сами разобраться, что означает x = x || y. Если x является правдивым, x присваивается x, так что на самом деле ничего не происходит; в противном случае y присваивается x. Обычно используется для определения параметров по умолчанию в функциях. Тем не менее, это часто считается плохой практикой программирования , поскольку она не позволяет вам передавать значение Фолси (которое необязательно undefined или null) в качестве параметра. Рассмотрим следующий пример:

function badFunction(/* boolean */flagA) {
  flagA = flagA || true;
  console.log("flagA is set to " + (flagA ? "true" : "false"));
}

Это выглядит актуально с первого взгляда. Однако что произойдет, если вы передадите false в качестве параметра flagA (поскольку он логический, то есть может быть true или false)? Это станет true. В этом примере нет способа установить flagA в false.

Лучше было бы явно проверить, является ли flagA undefined, вот так:

function goodFunction(/* boolean */flagA) {
  flagA = typeof flagA !== "undefined" ? flagA : true;
  console.log("flagA is set to " + (flagA ? "true" : "false"));
}

Хотя оно длиннее, оно всегда работает и его легче понять.


Вы также можете использовать синтаксис ES6 для параметров функции по умолчанию , но обратите внимание, что он не работает в старых браузерах (например, IE). Если вы хотите поддерживать эти браузеры, вы должны перенести свой код с помощью Babel .

См. Также Логические операторы на MDN .

28 голосов
/ 10 мая 2010

Если заголовок не установлен, используйте «ОШИБКА» в качестве значения по умолчанию.

Более общий:

var foobar = foo || default;

читает: установите для foobar значение foo или default. Вы могли бы даже связать это много раз:

var foobar = foo || bar || something || 42;
14 голосов
/ 10 мая 2010

Объясняя это немного больше ...

Оператор || является логическим оператором or. Результат верен, если первая часть верна, и истина, если вторая часть верна, и истина, если обе части верны. Для наглядности вот оно в таблице:

 X | Y | X || Y 
---+---+--------
 F | F |   F    
---+---+--------
 F | T |   T    
---+---+--------
 T | F |   T    
---+---+--------
 T | T |   T    
---+---+--------

Теперь заметили что-то здесь? Если X равно true, результат всегда равен true. Так что, если мы знаем, что X истинно, нам вообще не нужно проверять Y. Таким образом, во многих языках реализованы оценщики «короткого замыкания» для логического or (и логического and, поступающего с другого направления). Они проверяют первый элемент и, если это правда, они вообще не проверяют второй элемент. Результат (в логическом выражении) тот же, но с точки зрения исполнения потенциально огромная разница, если второй элемент дорог для вычисления.

Так какое отношение это имеет к вашему примеру?

var title   = title || 'Error';

Давайте посмотрим на это. Элемент title передается вашей функции. В JavaScript, если вы не передаете параметр, по умолчанию используется нулевое значение. Также в JavaScript, если ваша переменная имеет нулевое значение, логические операторы считают ее ложной. Поэтому, если эта функция вызывается с заданным заголовком, это не ложное значение и, таким образом, присваивается локальной переменной. Однако, если ему не дано значение, оно является нулевым значением и, следовательно, ложным. Затем логический оператор or вычисляет второе выражение и возвращает вместо него «Ошибка». Теперь локальной переменной присвоено значение «Ошибка».

Это работает из-за реализации логических выражений в JavaScript. Он не возвращает правильное логическое значение (true или false), но вместо этого возвращает значение, которое ему было дано согласно некоторым правилам относительно того, что считается эквивалентным true, а что считается эквивалентным false. Найдите ссылку на JavaScript, чтобы узнать, что JavaScript считает истинным или ложным в логических контекстах.

7 голосов
/ 10 мая 2010

Двойная труба обозначает логическое «ИЛИ». Это не совсем тот случай, когда «параметр не установлен», поскольку строго в javascript, если у вас есть код, подобный этому:

function foo(par) {
}

Затем звонит

foo()
foo("")
foo(null)
foo(undefined)
foo(0)

не эквивалентны.

Двойная труба (||) приведёт первый аргумент к логическому значению, а если полученное логическое значение истинно - выполните присваивание, в противном случае будет назначена правильная часть.

Это имеет значение, если вы проверяете наличие неустановленных параметров.

Допустим, у нас есть функция setSalary, у которой есть один необязательный параметр. Если пользователь не указывает параметр, следует использовать значение по умолчанию, равное 10.

если вы выполните проверку следующим образом:

function setSalary(dollars) {
    salary = dollars || 10
}

Это даст неожиданный результат при вызове, как

setSalary(0) 

Он все равно установит 10, следуя описанному выше потоку.

7 голосов
/ 10 мая 2010

В основном он проверяет, является ли значение перед || оценивается как true, если да, он принимает это значение, если нет, он принимает значение после ||.

Значения, для которых будет принято значение после || (насколько я помню):

  • неопределенный
  • ложь
  • 0
  • '' (Нулевая или Нулевая строка)
4 голосов
/ 15 января 2016

Чтобы добавить некоторые объяснения ко всему сказанному до меня, приведу несколько примеров для понимания логических понятий.

var name = false || "Mohsen"; # name equals to Mohsen
var family = true || "Alizadeh" # family equals to true

Это означает, что если левая сторона оценена как истинное утверждение, она будет завершена, а левая сторона будет возвращена и присвоена переменной. в других случаях правая сторона будет возвращена и назначена.

И оператор имеют противоположную структуру, как показано ниже.

var name = false && "Mohsen" # name equals to false
var family = true && "Alizadeh" # family equals to Alizadeh
4 голосов
/ 14 января 2016

Пока ответ Cletus правильный, я чувствую, что нужно добавить больше подробностей в отношении "оценивает как ложное" в JavaScript.

var title = title || 'Error';
var msg   = msg || 'Error on Request';

Это не просто проверка, предоставлено ли title / msg, но также и то, является ли любой из них falsy . то есть одно из следующего:

  • ложь.
  • 0 (ноль)
  • "" (пустая строка)
  • нуль.
  • не определено.
  • NaN (специальное числовое значение, означающее не число!)

Так в строке

var title = title || 'Error';

Если title является правдивым (то есть не ложным, поэтому title = "titleMessage" и т. Д.), То логический оператор OR (||) нашел одно значение 'true', что означает, что он оценивается как true, поэтому он схемы и возвращает истинное значение (заголовок).

Если title - это ложь (т. Е. Один из приведенных выше списков), тогда логический оператор OR (||) нашел значение «false», и теперь ему нужно вычислить другую часть оператора, «Error», которая оценивается как истина и, следовательно, возвращается.

Также может показаться (после некоторого быстрого эксперимента с консолью firebug), если обе стороны оператора оценивают как false, он возвращает второй оператор 'falsy'.

* * +1034 т.е.
return ("" || undefined)

возвращает значение undefined, возможно, оно позволяет вам использовать поведение, о котором идет речь в этом вопросе, при попытке установить заголовок / сообщение по умолчанию в "". т.е. после запуска

var foo = undefined
foo = foo || ""

foo будет установлено в ""

4 голосов
/ 10 мая 2010

оператор двойной трубы

этот пример полезен?

var section = document.getElementById('special');
if(!section){
     section = document.getElementById('main');
}

также может быть

var section = document.getElementById('special') || document.getElementById('main');
2 голосов
/ 09 мая 2016

Цитата: «Что означает конструкция x = x || y?»

Назначение значения по умолчанию.

Это означает, что предоставляет значение по умолчанию от y до x , если x все еще ожидает своего значения, но еще не получил его или был намеренно опущен, чтобы вернуться к значению по умолчанию.

...