我是第一次使用Javascript工作的有经验的C ++ / Java程序员。我正在使用Chrome作为浏览器。
我用字段和方法创建了几个Javascript类。当我读取一个不存在的对象字段时(由于我的错字),Javascript运行时不会抛出错误或异常。显然这样的读取字段是“未定义的”。例如:
var foo = new Foo();
foo.bar = 1;
var baz = foo.Bar; // baz is now undefined
我知道我可以检查“Detecting an undefined object property in JavaScript”中提到的“未定义”的相等性,但这似乎很乏味,因为我经常在代码中读取对象字段。
当我读取未定义的属性时,有没有办法强制抛出错误或异常?
为什么在读取未定义的变量时抛出异常(与未定义的对象属性相反)?
答案 0 :(得分:19)
这可以使用ES6 proxies:
来实现
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
答案 1 :(得分:14)
这在我看来就像是试图将一种语言变成另一种语言的经典案例 - 更好的恕我直言,改变你的编码风格,以遵循Javascript的做法,而不是试图使其符合C ++概念和期望。
也就是说,如果您想按照建议抛出错误,则需要在您尝试访问的对象或全局范围内定义某种自定义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
但这很难看,现在你的所有代码中都有这个自定义语言结构,使其不那么便携(例如,如果你想将代码的任何部分复制到另一个脚本中,你就会必须复制你的新功能)并且对其他程序员不太清晰。所以我真的建议在Javascript范例内工作并在访问你需要的属性之前检查undefined
(或者设置你的代码以便假设错误的y值并且不要破坏它们。)
关于你的第二个问题,为什么Javascript会为未定义的变量抛出错误但不会为未定义的对象属性抛出错误,我不能给出比“因为那是语言规范中的内容”更好的答案。 Objects return undefined
for undefined property names,但undefined variable references throw an error。
答案 2 :(得分:7)
有什么方法可以强制在我发生时抛出错误或异常 读取未定义的属性?
可以使用ES6代理,如之前的回复中所述。 我已经完成了小节点模块" zealit"避免每次都要实施它。
如果有人有兴趣: 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
答案 3 :(得分:6)
Firefox有一个选项javascript.options.strict
(在about:config
中)。如果启用此功能,警告将记录到控制台,以发现许多常见错误,包括使用=
中的==
代替if
来读取未定义的属性等。
(当然,这并不是说这些代码必然是错误的。)
答案 4 :(得分:0)
当我读取未定义的属性时,有没有办法强制抛出错误或异常?
简而言之,没有。您可以随时通过与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.
}
请注意,如果设置了s ['Bar'],这个短手可能会导致意外行为,但是它是一个'Falsey'值,而你只关心它是否未定义。
答案 5 :(得分:0)
一致性方面具有强大的功能(例如Stroustrup在C ++中采用的Alexander Stepanov的STL中)。对未声明的属性与未声明的变量进行不一致处理的一个简单原因可能是对不断演变的不同语言的思想和努力的反映,另一个可能是所涉人员的能力。
它还会影响您委托给任何给定语言的应用程序的类型。例如,您希望您不会尝试编写使用javascript来运行数百万美元的邮轮发动机管理系统的关键任务软件。
(对于javascript迷来说可能不是一个流行的答案。)
答案 6 :(得分:0)
到目前为止,对此的“正确”解决方案是使用TypeScript(或其他类型检查库,例如Flow)。示例:
const a = [1,2,3];
if (a.len !== 3) console.log("a's length is not 3!");
在JavaScript上,此代码将显示“ a的长度不为3!”。原因是数组上没有这样的属性len
(请记住,您使用a.length
而不是a.len
获得数组的长度)。因此,a.len
将返回undefined
,因此该语句实质上等于:
if (undefined !== 3) console.log("a's length is not 3!");
由于undefined
确实不等于3,因此if语句的主体将运行。
但是,on TypeScript会在“编译时”(在您的编辑器上,甚至在运行代码之前)直接显示错误Property 'len' does not exist on type 'number[]'
。