Подтвердить что ты не робот

Почему переменная undefined в Javascript иногда оценивается как ложная, а иногда и бросает непроверенный ReferenceError?

Все, что я когда-либо читал, указывает, что в Javascript логическое значение переменной undefined равно False. Я использовал такой код сотни раз:

if (!elem) {
   ...
}

с намерением, что если "elem" undefined, код в блоке будет выполнен. Обычно это работает, но иногда браузер выдает ошибку, жалуясь на ссылку undefined. Это кажется таким основным, но я не могу найти ответ.

Разве есть разница между переменной, которая не была определена, и той, которая была определена, но которая имеет значение undefined? Это кажется совершенно неинтуитивным.

4b9b3361

Ответ 1

Что такое ReferenceError?

Как определено в ECMAScript 5, ReferenceError указывает, что обнаружена недопустимая ссылка. Это не говорит само по себе, поэтому позвольте копать немного глубже.

Оставив в стороне строгий режим, ReferenceError возникает, когда движку сценария дается указание получить значение ссылки, что не может решить базовое значение для:

Ссылка - это разрешенная привязка имени. Ссылка состоит из трех компоненты, базовое значение, имя ссылки и логические значения строгий контрольный флаг. Базовое значение равно либо undefined, Object, логический, строковый, номер или запись окружения (10.2.1). базовое значение undefined указывает, что ссылка не может быть разрешен привязкой. Указанное имя является строкой.

Когда мы ссылаемся на свойство, базовым значением является объект, свойство которого мы ссылаемся. Когда мы ссылаемся на переменную, базовое значение является уникальным для каждого контекста выполнения и называется записью среды. Когда мы ссылаемся на то, что не является ни значением базового объекта, ни переменной значения записи базовой среды, возникает ReferenceError.

Рассмотрим, что происходит, когда вы вводите foo в консоли, когда такая переменная не существует: вы получаете ReferenceError, потому что базовое значение не разрешимо. Однако, если вы делаете var foo; foo.bar, вы получаете TypeError вместо ReferenceError - тонкую, но очень существенную разницу. Это связано с тем, что базовое значение было успешно разрешено; однако он имел тип undefined, а undefined не имеет свойства bar.

Защита от ReferenceError

Из вышесказанного следует, что для того, чтобы поймать ReferenceError до его возникновения, вы должны убедиться, что базовое значение разрешимо. Поэтому, если вы хотите проверить, разрешено ли foo, do

if(this.foo) //...

В глобальном контексте this равен объекту window, поэтому if (window.foo) эквивалентен. В других контекстах исполнения это не имеет смысла использовать такую ​​проверку, потому что по определению это контекст выполнения, созданный вашим собственным кодом, поэтому вы должны знать, какие переменные существуют и которые нет.

Ответ 2

Проверка на undefined работает для переменных, которые не имеют значения, но если сама переменная не была объявлена, вы можете столкнуться с этими проблемными ссылками.

if (typeof elem === "undefined")

Это намного лучше, так как не возникает риск ссылочной проблемы, поскольку typeof - это не метод, а ключевое слово в JavaScript.

Ответ 3

Разве есть разница между переменной, которая не была определена, и той, которая была определена, но которая имеет значение undefined?

Да. Необъявленная переменная будет вызывать ReferenceError при использовании в выражении, что вы видите.

if (x) { // error, x is undeclared

}

По сравнению с;

var y; // alert(y === undefined); // true

if (y) { // false, but no error

}

Это кажется совершенно неинтуитивным.

Meh... что я нахожу неинтуитивным:

if (y) // error, y is undeclared

var x = {};

if (x.someUndeclaredAttribute) // no error... someUndeclaredAttribute is implictly undefined.

Ответ 4

Вот пример объяснения Jon's относительно записей среды:

var bar = function bar() {
    if (!b) { // will throw a reference error.
    }
},
foo = function foo() {
    var a = false;

    if (a) {
        var b = true;
    }

    if (!b) { // will not throw a reference error.
    }
};

Ответ 5

В строгом режиме это ошибка:

function a() {
  "use strict";
  if (!banana) alert("no banana"); // throws error
}

Всегда было лучше сделать явный тест для глобальных переменных:

if (!window['banana']) alert("no banana");

Не имеет смысла выполнять такой тест для неглобальных переменных. (То есть, тестирование, чтобы определить, определена ли переменная таким образом, достаточно проверить, не имеет ли определенная переменная правдивое значение.)

edit Я смягчу это, чтобы сказать, что редко бывает разумно проверять существование неглобальных переменных.

Ответ 6

Когда переменная объявляется и не инициализируется или используется с объявлением, ее значение равно "undefined". Браузер жалуется, когда эта переменная undefined указана. Здесь "ссылка" означает, что какой-то фрагмент кода javascript пытается посетить атрибут или его метод. Например, если "elem" равен undefined, это вызовет исключение:

elem.id = "BadElem";

Ответ 7

или вы используете try/catch:

try { x } catch(err){}

Таким образом, вы не делаете ничего в случае ошибки, но, по крайней мере, ваш script не спрыгнет с утеса...

Ответ 8

undefined= переменная существует, но в ней нет значения

ReferenceError = переменная не существует