2009-04-22 4 views
65

ПРИМЕЧАНИЕ. Согласно ECMAScript5.1, section 15.1.1.3, window.undefined доступен только для чтения.JavaScript: undefined! == undefined?

  • Современные браузеры реализуют это правильно. например: Safari 5.1, Firefox 7, Chrome 20 и т.д.
  • Неопределенное еще изменчива в: Chrome 14, ...

Когда я недавно интегрированный Facebook Connect с Tersus, я сначала получил сообщения об ошибках Invalid Enumeration Value и Handler already exists при попытке вызвать функции Facebook API.

Оказалось, что причиной проблемы была

object.x === undefined 

возвращение ложным, когда нет свойства «х» в «объекта».

Я работал вокруг проблемы путем замены строгого равенства с регулярным равенства двух функций Facebook:

FB.Sys.isUndefined = function(o) { return o == undefined;}; 
FB.Sys.containsKey = function(d, key) { return d[key] != undefined;}; 

Это сделали все работает для меня, но, кажется, намекают на какие-то столкновения между кодом и JavaScript Facebook, мой своя.

Что может быть причиной этого?

Подсказка: хорошо документировано, что undefined == null в то время как undefined !== null. Здесь не проблема. Вопрос в том, как мы получаем undefined !== undefined.

+5

Интересно, я просто попробовал в своей консоли. 'var a = {}; a.b === undefined // true'. Вы уверены, что ваш 'object.x === undefined' возвращает false, потому что в объекте не было поля x? –

+1

«В соответствии с разделом 15.1.1.3 ECMAScript5.1, window.undefined доступен только для чтения."- Horray, потому что в предыдущей версии кто-то мог переписать' undefined' глобально, и все сломалось бы :( – Dan

ответ

59

Оказывается, что вы можете установить window.undefined все, что вы хотите, и поэтому получить object.x !== undefined когда object.x является реальным неопределенным. В моем случае я непреднамеренно установил undefined в null.

Самый простой способ, чтобы это произошло это:

window.undefined = null; 
alert(window.xyzw === undefined); // shows false 

Конечно, это не может произойти. В моем случае ошибка была немного более тонкой и была эквивалентна следующему сценарию.

var n = window.someName; // someName expected to be set but is actually undefined 
window[n]=null; // I thought I was clearing the old value but was actually changing window.undefined to null 
alert(window.xyzw === undefined); // shows false 
+16

Ах, ха! И * это * - основная причина, по которой я против использования неопределенного свойства (в отличие от использования typeof). Поздравляем с работой над ошибкой. +1 – annakata

+2

Еще одна причина, по которой всегда нужно пространство имен ваших объектов ... var n = blah.someName; л [п] = NULL; не позволил бы вам получить эту ошибку ... – cmcculloh

+0

Это не может быть перезаписано в современных браузерах, хотя – Memke

88

Проблема в том, что неопределенный по сравнению с null использованием == дает true. Общая проверка не определено поэтому делается так:

typeof x == "undefined" 

это обеспечивает тип переменной действительно не определено.

+60

Самое большое заблуждение во многих ответах здесь заключается в том, что 'undefined' - это ключевое слово Javascript. Это не ключевое слово, а переменная, которая (в большинстве случаев) не определена, поэтому единственный раз, когда «somevar === undefined» работает, когда переменная «undefined» действительно не определена. Я видел код (jcanvas), где класс-wrapping включает в себя последний аргумент с именем «undefined» (который никогда не используется), чтобы гарантировать, что в пределах области функции будет указана неопределенная переменная с именем «undefined». Помимо особых ситуаций, таких как использование «typeof» является единственным «right». –

+1

Означает ли это, что вместо неопределенного я мог бы также использовать garglblarg до тех пор, пока он не будет определен? –

+1

@ Dercsár: Да, 'var foo; foo === undefined // true'. – pimvdb

2

A). Я никогда не получал и никогда не буду доверять никакому инструменту, который претендует на создание кода без кодирования пользователя, который удваивается, где это графический инструмент.

B). У меня никогда не было никаких проблем с Facebook Connect. Это все еще простой старый JavaScript-код, работающий в браузере, и undefined===undefined, где бы вы ни находились.

Короче говоря, вам необходимо предоставить доказательства того, что ваш object.x действительно действительно был неопределенным, а не нулевым или иным образом, потому что я считаю, что невозможно, чтобы вы описывали на самом деле так - без обид :) - Я поместил деньги на проблему, существующую в коде Терсуса.

+1

Спасибо, annakata. Ваш скептический ответ заставил меня пересмотреть вопрос и найти правильный ответ (см. Ниже). –

15

Плохая практика использования оператора равенства == вместо ===.

undefined === undefined // true 
null == undefined // true 
null === undefined // false 

object.x === undefined The должен возвратить true если x неизвестно свойство.

В главе Bad Parts of JavaScript: The Good Parts, Крокфорд пишет следующее:

If you attempt to extract a value from an object, and if the object does not have a member with that name, it returns the undefined value instead.

In addition to undefined, JavaScript has a similar value called null. They are so similar that == thinks they are equal. That confuses some programmers into thinking that they are interchangeable, leading to code like

value = myObject[name]; 
if (value == null) { 
    alert(name + ' not found.'); 
} 

It is comparing the wrong value with the wrong operator. This code works because it contains two errors that cancel each other out. That is a crazy way to program. It is better written like this:

value = myObject[name]; 
if (value === undefined) { 
    alert(name + ' not found.'); 
} 
+0

Вы когда-нибудь читали эту замечательную пьесу: http://webreflection.blogspot.ie/2010/10/javascript-coercion-demystified.html? – op1ekun

18

Я хотел бы опубликовать важную информацию о undefined, что новички не могли знать.

Посмотрите на следующий код:

/* 
    * Consider there is no code above. 
    * The browser runs these lines only. 
    */ 

    // var a; 
    // --- commented out to point that we've forgotten to declare `a` variable 

    if (a === undefined) { 
     alert('Not defined'); 
    } else { 
     alert('Defined: ' + a); 
    } 

    alert('Doing important job below'); 

Если запустить этот код, в котором переменная a НИКОГДА НЕ БЫЛА ОБЪЯВЛЕННЫХ с помощью var, вы получите сообщение об ошибке ИСКЛЮЧЕНИЕ и удивительно не вижу никаких предупреждений вообще.

Вместо того, чтобы «выполнять важную работу ниже», ваш сценарий будет НЕСООТВЕТСТВУЮТ, не выбрасывая необработанное исключение в первой строке.


Вот только пуленепробиваемым способ проверить undefined с помощью typeof ключевых слов, который был разработан как раз для этой цели:

/* 
    * Correct and safe way of checking for `undefined`: 
    */ 

    if (typeof a === 'undefined') { 
     alert(
      'The variable is not declared in this scope, \n' + 
      'or you are pointing to unexisting property, \n' + 
      'or no value has been set yet to the variable, \n' + 
      'or the value set was `undefined`. \n' + 
      '(two last cases are equivalent, don\'t worry if it blows out your mind.' 
      ); 
    } 

    /* 
    * Use `typeof` for checking things like that 
    */ 

Этот метод работает во всех возможных случаях.

Последний аргумент, чтобы использовать его в том, что undefined потенциально могут быть переписаны в более ранних версиях Javascript:

 /* @ Trollface @ */ 
     undefined = 2; 
    /* Happy debuging! */ 

Надежда Я был достаточно ясен.

+0

'function xx (a) {if (a === undefined) a = 'default'; } xx() '- это хороший способ для размещения аргументов по умолчанию в javascript. – Dan

4
var a; 

typeof a === 'undefined'; // true 
a === undefined; // true 
typeof a === typeof undefined; // true 
typeof a === typeof sdfuwehflj; // true 
+0

+1 лучший ответ !!! – coolguy

10

С - JQuery_Core_Style_Guidelines

  • Глобальные переменные:
    typeof variable === "undefined"

  • локальных переменных:
    variable === undefined

  • Свойства:
    object.prop === undefined

+1

Просто примечание - если переменная вообще не существует, то она не является локальной или глобальной. Что не так интуитивно, так это то, что мы должны проверять эти потенциально несуществующие переменные так же, как мы проверяем глобальные переменные, как показал Дэн в своем примере. – JustAMartin