Принудительное исключение/ошибка JavaScript при чтении свойства объекта undefined?
Я - опытный программист на С++/Java, работающий в Javascript в первый раз. Я использую Chrome в качестве браузера.
Я создал несколько классов Javascript с полями и методами. Когда я прочитал поле объекта, которое не существует (из-за опечатки с моей стороны), среда выполнения Javascript не генерирует ошибку или исключение. По-видимому, такие поля чтения "undefined". Например:
var foo = new Foo();
foo.bar = 1;
var baz = foo.Bar; // baz is now undefined
Я знаю, что я могу проверить равенство против "undefined", как указано в "Обнаружение свойства объекта undefined в JavaScript", но это кажется утомительным так как я читал из полей объектов часто в моем коде.
Есть ли способ принудительно вызывать ошибку или исключение, когда я читаю свойство undefined?
И почему возникает исключение, когда я читаю переменную undefined (в отличие от свойства объекта undefined)?
Ответы
Ответ 1
Это выглядит как классический случай попыток обучить один язык парадигмам другого - лучше ИМХО изменить свой стиль кодирования, чтобы следить за тем, как Javascript делает что-то, чем пытаться привести его в соответствие с концепциями и ожиданиями на С++.
Тем не менее, если вы хотите бросить ошибку, как вы предлагаете, вам нужно определить какую-то пользовательскую функцию getProperty
, либо на объекте, к которому вы пытаетесь получить доступ, либо в глобальной области. Реализация может выглядеть так:
function getProperty(o, prop) {
if (o.hasOwnProperty(prop)) return o[prop];
else throw new ReferenceError('The property ' + prop +
' is not defined on this object');
}
var o = {
foo: 1,
bar: false,
baz: undefined
};
getProperty(o, 'foo'); // 1
getProperty(o, 'bar'); // false
getProperty(o, 'baz'); // undefined
getProperty(o, 'foobar');
// ReferenceError: The property baz is not defined on this object
Но это уродливо, и теперь у вас есть эта настраиваемая языковая конструкция во всем вашем коде, что делает ее менее переносимой (если, например, вы хотели скопировать любую часть своего кода в другой script, вы Вам также придется копировать вашу новую функцию) и менее читабельны для других программистов. Поэтому я бы рекомендовал работать в рамках парадигмы Javascript и проверять undefined
перед тем, как получить доступ к необходимым вам свойствам (или настроить ваш код, чтобы значения false-y ожидались и не прерывали работу).
Что касается вашего второго вопроса, почему Javascript выдает ошибку для переменных undefined, но не для свойств объекта undefined, я не могу дать лучшего ответа, чем "Потому что это то, что указано в спецификации языка". Объекты возвращают undefined
для имен свойств undefined, но undefined переменные ссылаются на ошибку.
Ответ 2
Это может быть достигнуто с помощью ES6-прокси:
function disallowUndefinedProperties(obj) {
const handler = {
get(target, property) {
if (property in target) {
return target[property];
}
throw new Error(`Property '${property}' is not defined`);
}
};
return new Proxy(obj, handler);
}
// example
const obj = { key: 'value' };
const noUndefObj = disallowUndefinedProperties(obj);
console.log(noUndefObj.key);
console.log(noUndefObj.undefinedProperty); // throws exception
Ответ 3
В Firefox есть опция javascript.options.strict
(в about:config
). Если вы включите это, предупреждения будут занесены в консоль для многих распространенных ошибок, включая чтение свойства undefined, используя =
вместо ==
в if
и т.д.
(Конечно, чтобы не сказать, что такой код обязательно является неправильным.)
Ответ 4
Есть ли способ принудительно вызвать ошибку или исключение, если я прочитайте свойство undefined?
Это возможно использование прокси ES6, как было сказано в предыдущих ответах.
Я сделал небольшой модуль node "zaalit", чтобы избежать необходимости его выполнять каждый раз.
Если кто-то заинтересован:
https://www.npmjs.com/package/zealit
const zealit = require('zealit')
const ref = { foo: true, bar: undefined }
ref.foo // true
ref.bar // undefined
ref.baz // undefined
const zealed = zealit(ref)
zealed.foo // true
zealed.bar // undefined
zealed.baz // throws a ReferenceError
Ответ 5
Есть ли способ принудительно вызывать ошибку или исключение, когда я читаю свойство undefined?
Короче говоря, нет. Вы всегда можете проверить, закончилось ли вы с undefined сравнением с undefined
, как вы сказали, или попыткой доступа к атрибуту второго уровня:
s = Foo()
s.bar = 1
s['Bar'] // returns undefined.
s['Bar']['Baz'] // Throws TypeError, s.Bar is undefined.
Кроме того, undefined
терпит неудачу в условной проверке, поэтому вы можете уйти от этого как сокращение для сравнения:
if (s['Bar']) {
// Something here only if s['Bar'] is set.
}
Имейте в виду, что эта короткая рука может вызвать неожиданное поведение, если был установлен параметр [[Bar]], но был значением "Falsey", и вам было только интересно, вернулась ли она обратно undefined.