Что означает выражение Javascript 'a = a || function () {...} 'значит? - PullRequest
14 голосов
/ 15 августа 2011

Я не уверен, что означает эта конструкция, но я видел ее несколько раз. Пример ниже взят из другого вопроса переполнения стека. Я не уверен, как интерпретировать исходную конструкцию "или":

Object.keys = Object.keys || (function () {
  var hasOwnProperty = Object.prototype.hasOwnProperty,
      hasDontEnumBug = !{toString:null}.propertyIsEnumerable("toString"),
      DontEnums = [ 
          'toString', 'toLocaleString', 'valueOf', 'hasOwnProperty',
          'isPrototypeOf', 'propertyIsEnumerable', 'constructor'
      ],
      DontEnumsLength = DontEnums.length;
  //etc...
});

Ответы [ 4 ]

16 голосов
/ 15 августа 2011

a = a || function(){...} - это идиома, которая очень распространена в Javascript. Он опирается на две концепции, которые, хотя и не уникальны для Javascript, но, возможно, еще не знакомы с вами.

1. Оператор короткого замыкания

Короткое замыкание оператора [wikipedia] - это оптимизация компилятора, разработанная для предотвращения ненужной оценки.

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

var isTeenager = person.age >= 13 && person.age <= 19;

Теперь давайте предположим, что код выполняется, и выясняется, что человек моложе 13 лет. Первое условие будет оценено и вернет false. Поскольку программе теперь известно, что левая часть оператора && равна false, а поскольку && требует, чтобы обе стороны были true, чтобы вычислить до true, она знает, что вычисление правой сторона рук бессмысленна.

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

Тот же принцип применяется к оператору ||. Предположим, мы хотели узнать, может ли человек ездить на автобусе бесплатно, то есть, если ему более 70 лет или он инвалид.

var canRideFree = person.age >= 70 || isHandicapped(person);

Если человеку за 70, программа уже знает, что он может ездить бесплатно. На данный момент программе не важно, является ли он инвалидом или нет, и, таким образом, он не оценивает вызов функции isHandicapped. Если, с другой стороны, человек был моложе 70 лет, то canRideFree будет установлено на то, что isHandicapped вернет.

2. Истинные и ложные значения

Значения правдивости и ложности [блог случайного человека] - это логические оценки объектов. В Javascript каждый объект оценивается как «истинное» или «ложное» значение.

Выражение «falsy», если его значение равно одному из следующих:

false, null, undefined, 0, "", NaN

Все остальное правдиво.

Люди используют тот факт, что нулевая или неопределенная переменная оценивается как false. Это означает, что вы можете проверить, существует ли переменная очень легко:

if (a) { /* a exists and is not a falsy value */ }

Объединяя то, что мы знаем

Оператор || замыкает цепь и возвращает значение последнего выражения, которое он оценивает . Этот принцип сочетается с правдивостью в этом единственном утверждении:

Object.keys = Object.keys || function() {...}

Если Object.keys является правдивым, он будет оценен и назначен самому себе. В противном случае, Object.keys будет присвоено функции. Это очень распространенная идиома в Javascript для проверки, если значение уже существует, и присвоение его чему-то другому, если оно не существует.

Некоторые другие языки, такие как C #, которые не имеют правдивости, имеют нуль-объединяющий оператор [MSDN] , имеющий аналогичное назначение.

object Value = PossiblyNullValue ?? ValueIfNull;

В этом коде Value будет присвоено PossiblyNullValue, если оно не равно нулю, и в этом случае оно будет присвоено ValueIfNull.

tl; dr [wikipedia]

Если вы не удосужились прочитать что-то, что я сказал выше, все, что вам нужно знать, это то, что a = a || function() {...} в основном делает то, что делает этот код:

if (exists(Object.keys)) {
  Object.keys = Object.keys;
} else { 
  Object.keys = function() {...};
}

function exists(obj) {
  return typeof obj !== "undefined" && 
         obj !== null && 
         obj !== false &&
         obj !== 0 &&
         obj !== "" &&
         !isNaN(obj);
}
4 голосов
/ 15 августа 2011

Мне это кажется неполным, но кажется, что это шайба для Object.keys. По сути, если свойство не существует (например, в браузерах, не соответствующих стандартам), мы реализуем его сами.

Оператор or оценит второй операнд, только если первый операнд неверен. Как таковой

alert(false || "Hello, world");

Оповещение "Привет, мир". В этом случае Object.keys будет undefined, что оценивается как false.

3 голосов
/ 15 августа 2011

|| в основном означает: если Object.keys не определено, определите его с помощью выражения, стоящего за ||.

Это поведение основано на функции JavaScript, согласно которой любая неопределенная переменная оценивается как false. Если переменная true, второе выражение не нужно оценивать, если оно false, оно делает.

2 голосов
/ 15 августа 2011

Из того, что я могу сказать, этот код пытается определить функцию Object.keys, если она еще не определена (или если она ложна). Функция слева от || станет функцией Object.keys.

Причина, по которой я сказал "из того, что я могу сказать", заключается в том, что вы не опубликовали весь фрагмент кода. Обратите внимание, что код после || читает (function(){ вместо function(){. Возможно, что автор настроил функцию для самостоятельного вызова.

Если после определения функции вы видите })(), то возвращаемое значение функции сохраняется в Object.keys. Если нет, то сама функция хранится там.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...