JavaScript - определяет, определено ли свойство и установлено ли оно «неопределенным» или неопределенным - PullRequest
37 голосов
/ 22 декабря 2008

Скажите, у меня есть следующий код:

function One() {}
One.prototype.x = undefined;

function Two() {}

var o = new One();
var t = new Two();

o.x и t.x будут оба равны undefined. o.hasOwnProperty('x') и t.hasOwnProperty('x') оба вернут false; То же самое касается propertyIsEnumerable. Два вопроса:

  • Есть ли способ сказать, что o.x определен и имеет значение undefined?
  • Есть ли какая-либо причина для этого? (должны ли они быть семантически эквивалентными?)

Небольшое предостережение: выполнение цикла (для propName в o) приведет к выводу 'x' в качестве одной из строк, тогда как выполнение этого в t не даст - поэтому существует разница в том, как они представлены внутри (по крайней мере, в Chrome).

Ответы [ 7 ]

66 голосов
/ 22 декабря 2008

Несколько проще, чем ваш метод, - использовать Javascript в операторе

alert('x' in o); // true
alert('x' in t); // false
8 голосов
/ 22 декабря 2008

object.hasOwnProperty (name) возвращает true только для объектов, находящихся в одном объекте, и false для всего остального, включая свойства в прототипе.

function x() {
  this.another=undefined;
};

x.prototype.something=1;
x.prototype.nothing=undefined;
y = new x;

y.hasOwnProperty("something"); //false
y.hasOwnProperty("nothing"); //false
y.hasOwnProperty("another"); //true

"someting" in y; //true
"another" in y; //true

Кроме того, единственный способ удалить свойство - использовать delete. Установка его в неопределенное значение НЕ удаляйте его.

Правильный способ сделать это - использовать в как roborg сказал.

Обновление: undefined является примитивным значением, см. Спецификация языка ECMAScript , раздел 4.3.2 и 4.3.9.

4 голосов
/ 22 декабря 2008

Ах, там один для анти-паттернов.

undefined не является ключевым словом.

Когда вы присваиваете запись var foo = undefined;, вы присваиваете ему значение символа undefined, которое вы не определили, и, следовательно, вы получите значение "undefined". Вы бы получили точно такой же результат, если бы вы присвоили его UnDeFiNeD или NotFineAtAll или _qwertyuiop

Почему это так ужасно? Помимо того, что это приводит к ложному пониманию того, что происходит, что случится, если вам случится загрузить библиотеку или нанять разработчика, который пишет var undefined = true;

1 голос
/ 22 декабря 2008

Нет. Я не думаю, что переменная, равная undefined, должна распознаваться как «определенная».

Установка его равным undefined напрямую - это просто ленивый способ его удаления - в отличие от использования ключевого слова delete. Я считаю, что это просто означает, что сборка мусора не влияет на переменную / свойство.


[ 1010 * РЕДАКТИРОВАТЬ *]

Что касается вашего комментария о hasOwnProperty и propertyIsEnumerable, то методы / свойства прототипа не являются ни собственными, ни перечисляемыми.

Object.prototype.foo = 'something';

var o = {bar: 'anything'};
o.hasOwnProperty('foo');  //=> false
o.hasOwnProperty('bar');  //=> true

Object.prototype.hasOwnProperty('foo');  //=> true
1 голос
/ 22 декабря 2008

Как то так?

function isDefined(var){
   return (typeof(window[var]) == 'undefined') ? false : true;
}

или ..

function isDefined(var){
   return (window.var === undefined) ? false : true;
}
0 голосов
/ 22 декабря 2008

Вы можете попробовать поместить часы на One.x, но это скажет вам только тогда, когда они не определены.

0 голосов
/ 22 декабря 2008

Один из способов сделать это это:

var definedProperties = [];
for (var prop in o) definedProperties.push(prop);

if (o.x === undefined && contains(prop, 'x')) {
    //x is defined, but set to undefined
}

где contains просто проверяет, является ли какой-либо элемент в массиве 'x'. Это единственный способ?

...