删除不存在的字段的子字段
我只是观察到以下奇怪的行为:
删除未定义的variables
> delete a true > delete a[0] ReferenceError: a is not defined > delete a.something ReferenceError: a is not defined > delete a.something[0] ReferenceError: a is not defined
删除不存在的字段的子字段
> a = {} {} > delete a.foo true > delete a.bar.something TypeError: Cannot convert null to object > a.bar undefined
我有两个问题:
- 为什么
delete a
作品,而没有定义? - 为什么删除
a.bar.something
抛出错误Cannot convert null to object
而Cannot read property 'something' of undefined
(因为a.bar
undefined
)?
根据文档delete
操作删除对象的属性。 ,所以第一个问题的答案是a
应该是this
对象的一个属性?
当使用delete a;
在c + +应用程序,这个错误出现(和它应该这样做) error: 'a' was not declared in this scope
。
答案分成两部分。 第一个没有太多的描述,只是回答了这个问题,而后者则进入了规范的基本细节。
TL;博士
- 第一行工作,因为在非严格模式下,试图删除一个variables只是起作用。
- 第一部分中的其余示例不起作用,因为
a
没有定义 -
delete a.foo
作品,因为没有理由不应该 -
delete a.bar.something
会抛出,因为它首先试图在访问a.bar.something
之前将a.bar
变成对象。
而现在完全不同的东西
首先,我们要明确的是,自从第一次讨论一个未声明的variables以来,代码的两个部分在概念上是不同的。
我们将看看如何delete
相当多的指定 。
让我们从易于理解的部分开始:
> delete a[0] ReferenceError: a is not defined > delete a.something ReferenceError: a is not defined > delete a.something[0] ReferenceError: a is not defined
所有这些行都试图用a
没有声明的variables做一些事情。 因此,你会得到一个ReferenceError
。 到现在为止还挺好。
> delete a true
这是delete
语句的第三个条款: a
是一个“未解决的参考”,这是一个奇怪的方式说“它没有宣布”。 Spec说只是在这种情况下返回true
。
> a = {} {} > delete a.foo true
这个很直观,就像你期望的那样(可能),但是让我们继续深入吧。 delete obj.property
进入第4条:
返回在提供
GetReferencedName(ref)
和IsStrictReference(ref)
作为参数的ToObject(GetBase(ref))
上调用[[Delete]]
内部方法的结果。
韦尔普,这是很多无趣的东西。 让我们忽略[[Delete]]
部分后的所有内容,只要看看[[Delete]]
是如何指定的 。 如果我用js写的话,就是这样的:
function Delete (obj, prop) { var desc = Object.getOwnPropertyDescriptor(obj, prop); if (!desc) { return true; } if (desc.configurable) { desc.magicallyRemove(prop); return true; } throw new TypeError('trying to delete a non-configurable property, eh!?'); }
在这个例子中, a
没有一个名为foo
的属性,所以没有什么特别的事情发生。
现在变得有趣了:
> delete a.bar.something TypeError: Cannot convert null to object
这是因为我们之前忽略的一些无趣的事情:
返回在
ToObject(GetBase(ref))
上调用[[Delete]]
内部方法的结果[…]
我突出了与这个特定片段相关的部分。 在我们尝试delete
任何东西之前,spec告诉我们调用ToObject(GetBase(ref))
,其中ref = a.bar.something
。 那就这样吧!
-
GetBase
(a.bar.something) === a.bar
-
ToObject
(a.bar)
===引发TypeError
ToObject(undefined)
这解释了最终的行为。
最后一点:你显示的错误信息是误导性的,因为它表示它试图将null
转换成一个对象,它没有,因为它试图将undefined
转换成一个。 最新的chrome和firefox会抛出一个更精确的版本,但是我认为v8最近才修正了这个错误信息,所以升级到v11会显示正确的版本。
我分享实验和阅读,希望这会有所帮助!
1.为什么删除一个作品,而没有定义?
如果您尝试读取不在那里的属性,JavaScript将返回“undefined”。 这很方便,但如果你不小心,可以掩盖错误,所以要小心input错误!
来源 : http : //www.w3.org/wiki/Objects_in_JavaScript
“删除”将删除值和属性,所以只要JavaScript为a
返回一个值,delete就会像这个例子一样工作:
var a; delete a;
另外,正如你所说的, a
是this
对象的一个属性。 你可以通过testing这个代码来看到这个:
> var a = {} undefined > a {} > this.a {}
2.为什么删除a.bar.something会引发错误无法将null转换为对象而不是无法读取未定义的属性“something”?
请看这些例子:
的NodeJS:
> var a = {} undefined > typeof ab 'undefined' > typeof abc TypeError: Cannot read property 'c' of undefined at repl:1:12 at ...... > delete abc TypeError: Cannot convert null to object at repl:1:10 at ......
Chrome控制台:
> var a ={} undefined > typeof ab "undefined" > typeof abc Uncaught TypeError: Cannot read property 'c' of undefined VM335:2 > delete abc Uncaught TypeError: Cannot convert undefined or null to object
正如你所看到的,当testingtypeof
时,两者都将把ab
作为一个未定义的值来pipe理。 但是在删除的时候,chrome说可能是undefined
或null
,而NodeJS认为这是一个null
值。
NodeJS错误是否可能是错误的格式?