Разница между undefined и не определена в Javascript

См. http://jsfiddle.net/FDhQF/1/ для тривиального примера.

Какая разница между тем, что есть undefined и что-то не определено в Javascript? Например, попытка доступа к объекту для объекта (фактически, попытка доступа к переменной), которая не определена, вернет undefined. Но вы также можете установить что-то = undefined. Когда вы это сделаете, попытка доступа к нему все равно вернет undefined, но указатель все еще там. Пример, как указано выше, заключается в том, как итерация по объекту по-прежнему проходит через свойство, которое вы (re) объявили как undefined. Похоже, существуют два разных типа undefined. Может ли кто-нибудь пролить свет на ситуацию?

Ответ 1

Оба, получающие доступ к свойству, не определенному для объекта, и свойству, содержащему примитивное значение undefined, вернут вам undefined.

Например:

var obj = {
  a: undefined
};

obj.a; // undefined
obj.b; // undefined

Разница в том, что a является собственным свойством, а b не является:

obj.hasOwnProperty('a'); // true
obj.hasOwnProperty('b'); // false

В первом случае a является собственным свойством, даже если оно содержит undefined как его значение. Во втором случае b не является собственным свойством, доступ к obj.b будет искать свойство с именем b, все в цепочке прототипов.

Когда цепочка прототипов заканчивается (когда она достигает объекта с null [[Prototype]]), поиск свойств заканчивается и undefined явно возвращается.

Вы должны знать, что метод hasOwnProperty проверяет только, если свойство физически существует на объекте (собственные свойства), но мы также имеем унаследованные свойства, в этом случае мы можем использовать оператор in, например:

function Test () {}
Test.prototype.a = 'foo'; // instances of Test will inherit from Test.prototype

var obj = new Test(); // { a="foo",  b="bar"}
obj.b = 'bar';

obj.hasOwnProperty('a');  // false
'a' in obj;               // true
obj.a;                    // 'foo'

obj.hasOwnProperty('b');  // true

Как вы можете видеть, obj наследует от Test.prototype, а свойство a не является собственным свойством, но доступно через цепочку прототипов. Поэтому hasOwnProperty возвращает false, а оператор in возвращает true.

Вы можете видеть, как внутренние свойства решаются с помощью [[Get]] внутренней операции

Примечания:

  • Доступ к undefined в качестве идентификатора не считается безопасным в ECMAScript 3 (наиболее распространенной версии стандартного языка), поскольку вместо ключевого слова языка (например, null) это просто свойство глобального объекта, и оно доступно для записи в этой версии Spec., что означает, что если кто-то заменит его значение (например, window.undefined = 'LOL';), он сломает ваш код.

Оператор typeof, поскольку вместо него могут использоваться ссылки @strager, например:

if (typeof obj.prop == 'undefined') { /*....*/ }

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

Другим распространенным способом решения этой проблемы является объявление вашей собственной переменной undefined, доступной в области ваших функций, например, некоторые библиотеки используют следующий шаблон:

(function(undefined) {
  // code here
})();

У функции есть аргумент с именем undefined, и он выполняется немедленно, не передавая ему какое-либо значение (последняя пара или параны делают вызов).

Возможно, стоит упомянуть, что глобальное свойство undefined было, наконец, описано в ECMAScript 5 как незаписываемое (неизменяемое, перечислимый и неконфигурируемый - не удаляемый -).

  • Использование метода hasOwnProperty непосредственно из экземпляра объекта также не считается безопасным, потому что, если у какого-либо объекта есть свойство с тем же именем, оригинальный метод будет затенен. Например:

    var obj = { hasOwnProperty: function () { /* evil code :) */ } };
    

Если вы вызываете:

    obj.hasOwnProperty('prop'); 

Метод, определенный на объекте, будет выполнен (и вы не захотите этого, так как вы точно знаете, какой метод вы хотите вызывать...), потому что он сглаживает одно из Object.prototype, однако это может быть безопасно вызывается:

    Object.prototype.hasOwnProperty.call(obj, 'prop');

Ответ 2

Здесь является хорошим объяснением "undefined" . Суть заключается в том, что настройка чего-либо на "undefined" не является UN-определяющим, потому что "undefined" на самом деле является примитивным значением, которое используется, когда переменной (или свойству) не присвоено значение.