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

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

27
Steven 6 Авг 2010 в 03:57

2 ответа

Лучший ответ

Оба, доступ к свойству, которое не определено для объекта, и к свойству, содержащему примитивное значение 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) просто свойство глобального объекта, и оно доступно для записи в этой версии спецификации, что означает, что если кто-то заменит его значение (например, window.undefined = 'LOL';), это нарушит ваш код.

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

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

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

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

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

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

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

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

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

Если вы позвоните:

    obj.hasOwnProperty('prop'); 

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

    Object.prototype.hasOwnProperty.call(obj, 'prop');
44
CMS 28 Июл 2011 в 17:15

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

1
Strelok 6 Авг 2010 в 00:08