Что означает конструкция x = x || y?
Я отлаживаю некоторый JavaScript и не могу объяснить, что это || делает?
function (title, msg) {
var title = title || 'Error';
var msg = msg || 'Error on Request';
}
может кто-нибудь дать мне подсказку, почему этот парень использует var title = title || 'ERROR'? Я иногда вижу его без var декларации, а также.
11 ответов
значит title аргумент является необязательным. Так что если вы вызываете метод без аргументов, он будет использовать значение по умолчанию "Error".
это стенография для записи:
if (!title) {
title = "Error";
}
этот вид стенографического трюка с булевыми выражениями также распространен в Perl. С выражением:
a OR b
он оценивает в true если a или b is true. Так что если a это правда, вам не нужно проверять b на всех. Это называется булева оценка короткого замыкания так:
var title = title || "Error";
в основном проверяет, является ли title значение false. Если это так, он "возвращает" "Error", в противном случае она возвращает title.
что такое оператор двойной трубы (||)?
оператор двойной трубы (||) является логическое 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
другими словами, это только false, когда оба значения false.
как это отличается в JavaScript?
JavaScript немного отличается, потому что это слабо типизированным языком. В данном случае это означает, что вы можете использовать || оператор со значениями, которые не логические. Хотя это не имеет смысла, вы можете использовать этот оператор, например, с функцией и объектом:
(function(){}) || {}
что там происходит?
если значения не являются логическими, JavaScript делает неявный разговор с boolean. Это означает, что если значение 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 был falsey, eitherXorY будет y. В этом случае вы получите "Either x or y is truthy." если y было правдой; иначе вы бы получили "Neither x nor y is truthy".
вопрос
теперь, когда вы знаете, как || оператор работает, вы, вероятно, можете сами разобраться, что делает x = x || y mean. Если x - истина, x назначена x, так что на самом деле ничего не происходит; в противном случае y назначена x. Он обычно используется для определения параметров по умолчанию в функциях. Тем не менее, это часто считается плохая практика программирования, потому что это мешает вам передать значение falsey (которое не обязательно undefined или null) в качестве параметра. Рассмотрим следующий пример:
function badFunction(/* boolean */flagA) {
flagA = flagA || true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
это выглядит правильно на первый взгляд. Однако, что произойдет, если вы пройдете false as flagA параметр (так как он логический, т. е. может быть true или false)? он стал true. в этом примере нет способа установить flagA to false.
было бы лучше явно проверьте, является ли flagA is undefined, вот так:
function goodFunction(/* boolean */flagA) {
flagA = typeof flagA !== "undefined" ? flagA : true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
хотя это дольше, это всегда работает, и это легче понять.
вы также можете использовать синтаксис ES6 для параметров функции по умолчанию, но обратите внимание, что он не работает в старых браузерах (например, IE). Если вы хотите поддерживать эти браузеры, вы должны транспилировать свой код с помощью Бабель.
см. также логические операторы на MDN.
Если заголовок не задан, используйте 'ERROR' в качестве значения по умолчанию.
более общий:
var foobar = foo || default;
читает: установите foobar в foo или default.
Вы могли бы даже приковать это много раз:
var foobar = foo || bar || something || 42;
объяснить это немного больше...
на || оператор логического-or оператора. Результат истинен, если первая часть истинна, и истинен, если вторая часть истинна, и истинен, если обе части истинны. Для ясности, вот он в таблице:
X | Y | X || Y
---+---+--------
F | F | F
---+---+--------
F | T | T
---+---+--------
T | F | T
---+---+--------
T | T | T
---+---+--------
теперь заметили что-то здесь? Если X true, то результатом всегда является истиной. Так что, если мы знаем, что X это правда, нам не нужно проверять Y на всех. Таким образом, многие языки реализуют "короткое замыкание" эвалуаторы для логических-or (и логично-and идет с другой стороны). Они проверяют первый элемент, и если это правда, они вообще не утруждают себя проверкой второго. Результат (в логических терминах) тот же, но с точки зрения выполнения потенциально существует огромная разница, если второй элемент дорог для вычисления.
так какое это имеет отношение к вашему примеру?
var title = title || 'Error';
давайте посмотрим на это. The title элемент передано вашей функции. В JavaScript, если вы не передаете параметр, он по умолчанию имеет значение null. Также в JavaScript, если ваша переменная является нулевым значением, логические операторы считают ее ложной. Поэтому, если эта функция вызывается с заданным заголовком, Это значение не является ложным и, таким образом, присваивается локальной переменной. Если, однако, ему не задано значение, это значение null и, следовательно, false. Логико-or оператор затем вычисляет второе выражение и возвращает 'Error' вместо. Итак, теперь локальной переменной присваивается значение "Error".
это работает из-за реализации логических выражений в JavaScript. Он не возвращает правильное логическое значение (true или false) но вместо этого возвращает значение, которое было дано по некоторым правилам относительно того, что считается эквивалентным true и то, что считается эквивалентным false. Найдите ссылку на JavaScript, чтобы узнать, что JavaScript считает истинным или ложным в boolean контексты.
двойная труба стоит Для логически "или". Это не совсем тот случай, когда "параметр не установлен", так как строго в javascript, если у вас есть такой код:
function foo(par) {
}
вызывает
foo()
foo("")
foo(null)
foo(undefined)
foo(0)
не эквивалентны.
Double pipe ( | | ) приведет первый аргумент к boolean, и если результирующее boolean истинно - выполните назначение, иначе оно назначит правильную часть.
это имеет значение, если вы проверяете параметр unset.
допустим, у нас есть функция setSalary, которая имеет один необязательный параметр. Если пользователь не предоставляет параметр, следует использовать значение по умолчанию 10.
если вы делаете проверку так:
function setSalary(dollars) {
salary = dollars || 10
}
это даст неожиданный результат по вызову, как
setSalary(0)
он по-прежнему будет устанавливать 10 после потока, описанного выше.
в основном он проверяет, имеет ли значение перед || значение true, если да, оно принимает это значение, если нет, оно принимает значение после ||.
значения, для которых он будет принимать значение после | | (насколько я помню):
- undefined
- false
- 0
- "(нулевая или нулевая строка)
оператор двойной трубы
этот пример полезен?
var section = document.getElementById('special');
if(!section){
section = document.getElementById('main');
}
можно
var section = document.getElementById('special') || document.getElementById('main');
пока Клетус' ответ правильно, я чувствую, что более подробно следует добавить в отношении "оценивает на false" в JavaScript.
var title = title || 'Error';
var msg = msg || 'Error on Request';
не просто проверяет, был ли предоставлен title/msg, но и если любой из них ложь. то есть одно из следующих:
- false.
- 0 (ноль)
- "" (пустая строка)
- null.
- не определено.
- NaN (специальное числовое значение, означающее Не-число!)
в строку
var title = title || 'Error';
если название истинно (т. е. не ложно, поэтому title = "titleMessage" и т. д.) тогда логический оператор OR (||) нашел одно "истинное" значение, что означает, что он оценивает значение true, поэтому он закорачивает и возвращает истинное значение (title).
Если заголовок является ложным (т. е. одним из списка выше), то логический оператор OR (||) нашел значение "false", и теперь необходимо оценить другую часть оператора, 'Error', которая оценивается как true, и, следовательно, возвращается.
также казалось бы (после некоторых быстрых экспериментов с консолью firebug), если обе стороны оператора оценивают в false, он возвращает второй оператор "falsy".
то есть
return ("" || undefined)
возвращает undefined, это, вероятно, позволит вам использовать поведение, заданное в этом вопросе, при попытке по умолчанию заголовок/сообщение "". т. е. после бег!--7-->
var foo = undefined
foo = foo || ""
foo будет установлено в ""
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
цитата: "Что означает конструкция x = x || y?"
присвоение значения по умолчанию.
Это значит предоставление значения по умолчанию от y до x, в случае, если x все еще ждет своего значения, но еще не получил его или был намеренно опущен, чтобы вернуться к умолчанию.
и я должен добавить еще одну вещь: этот бит стенографии является мерзостью. Он неправильно использует случайную оптимизацию интерпретатора (не беспокоясь о второй операции, если первая истинна) для управления назначением. Это использование не имеет ничего общего с целью оператора. Я не верю, что его вообще следует использовать.
Я предпочитаю троичный оператор для инициализации, например,
var title = title?title:'Error';
для правильной цели используется однострочная условная операция. Он все еще играет неприглядные игры с правдивостью, но это Javascript для вас.