删除不存在的字段的子字段

我只是观察到以下奇怪的行为:

删除未定义的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 objectCannot read property 'something' of undefined (因为a.bar undefined )?

根据文档delete操作删除对象的属性。 ,所以第一个问题的答案是a应该是this对象的一个​​属性?

当使用delete a; 在c + +应用程序,这个错误出现(和它应该这样做) error: 'a' was not declared in this scope

答案分成两部分。 第一个没有太多的描述,只是回答了这个问题,而后者则进入了规范的基本细节。

TL;博士

  1. 第一行工作,因为在非严格模式下,试图删除一个variables只是起作用。
  2. 第一部分中的其余示例不起作用,因为a没有定义
  3. delete a.foo作品,因为没有理由不应该
  4. 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; 

另外,正如你所说的, athis对象的一个​​属性。 你可以通过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说可能是undefinednull ,而NodeJS认为这是一个null值。

NodeJS错误是否可能是错误的格式?