Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么“无法读取未定义”的属性“x”未计算为false?_Javascript - Fatal编程技术网

Javascript 为什么“无法读取未定义”的属性“x”未计算为false?

Javascript 为什么“无法读取未定义”的属性“x”未计算为false?,javascript,Javascript,我多次遇到“无法读取未定义属性“x”的错误,我知道我可以通过执行著名的 if (foo && foo.bar) 但问题是为什么?为什么我们需要检查对象是否存在以测试其属性是否已定义?大概对每个人来说都不容易,我们可以安全地排除那些构建JavaScript引擎只测试目标属性的人,而JavaScript引擎在幕后执行“foo&&” 很多人都流下了眼泪,更多的夜晚都在不眠不休地调试这个错误,那么为什么JS引擎实现者选择这样做呢?它是ECMAScript规范的一部分吗?是嘲笑新手吗?是

我多次遇到“无法读取未定义属性“x”的错误,我知道我可以通过执行著名的

if (foo && foo.bar)
但问题是为什么?为什么我们需要检查对象是否存在以测试其属性是否已定义?大概对每个人来说都不容易,我们可以安全地排除那些构建JavaScript引擎只测试目标属性的人,而JavaScript引擎在幕后执行“foo&&”

很多人都流下了眼泪,更多的夜晚都在不眠不休地调试这个错误,那么为什么JS引擎实现者选择这样做呢?它是ECMAScript规范的一部分吗?是嘲笑新手吗?是StackOverflow的阴谋让更多的人访问他们的网站,一遍又一遍地问同样的问题吗

好的,它是ECMAScript规范的一部分:通常情况下。我在阅读正式的、穿西装、打领带的男士文件方面并不是专家,但应该是这样

这是一种语言结构,但为什么他们不能让可怜的开发人员更容易使用它呢

这个问题是关于学习更多关于JavaScript如何工作的知识,所以如果您能够深入地解释事情,那就太好了

为了问题的完整性,有一个工作示例:jsfiddle.net/vr6bgwop/

对每个人来说都不容易,我们可以安全地排除 这些家伙构建JavaScript引擎只是为了测试目标 属性,JavaScript引擎在幕后执行“foo&&” ?

当然可以。由于需要额外的测试,速度会慢得多,而且在开发人员非常清楚foo不能为null的所有情况下:

foo = { bar: (i == 50) };
if(foo.bar) {...}

开发人员的懒惰从来不是放慢语言速度的借口。在您的例子中,您正在评估两个条件:是否设置了foo,如果设置了foo,是否设置了其属性栏。如果您测试两个条件,那么您将同时写入这两个条件。

想象一下,每次需要访问z时,检查a.b.c.d..x.y.z中z的所有父项的开销

这就是为什么您必须自己明确地检查缺少的属性。在不显著增加内存/CPU使用率的情况下,无法自动检查它

这就是说,如果您要自动返回,例如,未定义,如果父项之一未设置,那么您将无法知道z是否未定义,或者它的父项之一是否未定义


那么,你如何确保它的父母被正确设置?通过手动检查每个父级。

Javascript不允许您访问与所有编程语言相同的不存在的属性。这是一个迫使您使用良好实践进行开发的功能。有很多方法可以避免if语句中的问题,例如使用null或未定义的值初始化对象:

 var foo = {
      bar: null,
      beer: undefined
 }

 if(foo.beer) { 
      // you'll never notice with an undefined error, so undefined is the value!
 }

还有,请不要合谋。

让我们看看该语言的一些半相关结构:

访问不存在的对象属性,例如var foo={};foo.a导致未定义 传递少于或多于函数预期的参数是合法的;访问未传递的参数会导致未定义 对非数字进行数学运算会产生NaN,NaN会通过计算点传播对象:a*b-c^d,你不能吗? 等等。有人可能会认为上面所有的例子都会引发错误。但他们没有,这不是为了节省CPU周期或内存,这是因为语言的工作方式,以及混乱的历史。最后一个非常非常重要

这就是语言的工作方式:对象和原语 但让我们谈谈你的例子。为什么还要抛出错误呢

与流行的观点相反,JS中并不是所有的东西都是对象:如果你感兴趣,大多数东西都可以变成对象,但有两个非常重要的原语不能,即null和undefined

让我们看一下:如果你可以说null和undefined可以转化为对象,那么访问它们的属性就没有问题了,对吧

像Ruby这样的语言可以做到这一点。在Ruby中,一切都是对象,所以你可以这样做:nil.nil?看见尝试访问不存在的属性或插槽?他们是这么叫的吗?像在任何其他对象上一样引发异常为什么它们会引发异常!?他们不能返回未定义的吗

但大多数其他语言则不然。众所周知,空值和友元是用来表示什么都不是的,而不是用熟悉这个概念的语言表示的对象。在Java和C中,NullReferenceException是著名的。在C++中,更糟的是:去引用空值会导致Sebug!想象一下

因此,考虑到语言的历史以及它同时具有对象和原语,如果不能将原语视为对象,则抛出错误是有意义的 反对

想象一下这个世界 假设你是对的:区别是愚蠢的,应该实施。你提出了一个bug报告,TC39负责指定javascript的人同意,它到处都有实现。内容,你去你最喜欢的编辑,在事情的中间写这个:

foo.bar.baz = 4
出于某种原因,系统中一个非常不相关的部分以某种模糊的方式通过foo.bar.baz会抛出奇怪的错误,比如false没有toFixed函数

wtf?这是怎么发生的?如何调试它

在经过几个小时的调试和返回调用堆栈后,你难以置信地拍了拍额头。我是个白痴,你对自己说,我怎么会忘记初始化foo.bar

这就是为什么我个人认为NaN传播是一场灾难

但你为什么这么激动? 但最后,让我们澄清一些问题:为什么这个错误会导致您花费数小时进行调试?由于这是一个例外,它清楚地向您显示了它发生的行和列,并且您显然知道这个规则,因此从错误到找到正确的点的距离几乎是瞬间的。这是你应该研究的重点,撇开语言特质不谈

旁白:它在规范中的位置 您已接近指定此行为的位置。你很幸运,我很难过。。。我已经读了很多正式的、穿西装打领带的男士调文件,知道如何找到这些

搜索,您将进入该部分。注意第一个算法的步骤7和第二个算法的步骤4:

让bv去吧


在RequireObject可强制表中,我们看到undefined和null抛出一个TypeError。

在另一个世界中,men2n1问为什么访问undefined/null上的属性会给出false而不是错误?是为了嘲笑新手吗?@Zirak:是的,而且它也没有提到哪个家长是罪魁祸首。这使得调试成为一件痛苦的事。按照stackoverflow的规则,这个问题应该以过于宽泛和主要的观点为基础来解决。这个观点是如何建立的,@MarcosPérezGude?阅读:可怜的开发者,嘲笑新手,换句话说,商业stackoverflow策略等等。这不是一个好问题,即使是这个问题也很大,里面有很多问题。几乎太宽泛了,但我认为这个问题让你们所有人都笑了,没有人认为它应该结束。我也笑了几分钟,但这并没有通过stackoverflow规则测试。谢谢你的回答,但我不是说访问属性的值。它是关于评估它的存在。如果它本身不存在,或者因为它的父项不存在,为什么第一种情况返回false,第二种情况返回错误?我知道,对if中的语句求值意味着“访问其值”,并查看将其转换为布尔值的结果。但是,如果直接子属性返回undefined->false,为什么不存在父属性的间接子属性不能返回相同的值而不抛出错误?我不是阴谋论者,但这是针对usSo的阴谋,如果财产不存在,它不能返回false。我不介意。我不知道你为什么有它。与其返回false,不如抛出一个错误。如果您管理这些错误比读取false返回值更好。如果您在不存在的属性中读取false,您将遇到更多问题。这不是什么阴谋,哈哈哈。我知道你今天早上让我笑了很多。感谢您:如果JS引擎在遇到未知标记时立即返回undefined,而不是抛出错误,那么效率可能会更高。这是一个简单的问题,因为如果b未定义,引擎将在c处停止,只返回false,而无需检查所有子代,因为如果父代未定义,没有孩子,除非是母亲在维多利亚做的。没有额外的开销。JS已经完成了所有必需的检查。它只是将结果显示为异常。考虑函数{{返回.A.B.C.D.X.Y.Z} CasChe{FIFE STATEORION Type Error {RealNUL}}抛出E;}作为C的空条件运算符的JS版本A,.B....d.……x?y??z@men1n2:但是,如果y是未定义的,那么在它之前你有一大堆检查。@RickHitchcock:我扩展了我的答案。回答得很好,将来可以用来解决类似的问题。