Какова конструкция x = x || y означает?

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

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

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

Ответы

Ответ 1

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

Это сокращение для написания:

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

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

a OR b

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

var title = title || "Error";

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

Ответ 2

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

Оператор двойной трубы (||) является логическим оператором 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, потому что пустая функция - 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 был truthy; в противном случае вы получите "Neither x nor y is truthy".

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

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

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

Это выглядит актуально с первого взгляда. Однако что произойдет, если вы flagA false в flagA параметра flagA (поскольку он имеет логическое значение, т. 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.

Ответ 3

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

Более общий:

var foobar = foo || default;

Считывает: Установите foobar на foo или default. Вы могли бы даже многократно зацепить это:

var foobar = foo || bar || something || 42;

Ответ 4

Объясняя это немного подробнее...

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

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

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

Итак, что это имеет отношение к вашему примеру?

var title   = title || 'Error';

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

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

Ответ 5

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

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

  • undefined
  • ложь
  • 0
  • '' (нулевая или нулевая строка)

Ответ 6

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

function foo(par) {
}

Затем вызывает

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

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

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

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

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

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

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

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

setSalary(0) 

Он по-прежнему будет устанавливать значение 10 после описанного выше потока.

Ответ 7

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

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

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

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

var section = document.getElementById('special') || document.getElementById('main');

Ответ 8

В то время как ответ Cletus верен, я чувствую, что более подробно следует добавить в отношении "оценивает false" в JavaScript.

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

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

  • ложно.
  • 0 (ноль)
  • "" (пустая строка)
  • нуль.
  • undefined.
  • NaN (специальное значение номера означает Not-a-Number!)

Итак, в строке

var title = title || 'Error';

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

Если заголовок является ложным (т.е. один из приведенных выше списков), то логический оператор OR (||) обнаружил "ложное" значение, и теперь ему необходимо оценить другую часть оператора "Ошибка", которая оценивается как true и возвращается.

Казалось бы, после нескольких быстрых экспериментов с firebug-консолью, если обе стороны оператора оценивают значение false, он возвращает второй "фальшивый" оператор.

то есть.

return ("" || undefined)

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

var foo = undefined
foo = foo || ""

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

Ответ 9

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

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

Ответ 10

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

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

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

Ответ 11

И я должен добавить еще одну вещь: этот бит сокращений - мерзость. Он управляет оптимизацией случайного интерпретатора (не беспокоясь о второй операции, если первая является правдой) для управления назначением. Это использование не имеет ничего общего с целью оператора. Я не верю, что это никогда не будет использоваться.

Я предпочитаю тернарный оператор для инициализации, например,

var title = title?title:'Error';

Это использует однострочную условную операцию для ее правильной цели. Он по-прежнему играет неприглядные игры с правдивостью, но, что Javascript для вас.