Что означает конструкция 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 для вас.