删除:有人可以解释这种行为

Koo*_*Inc 4 javascript operators

比较这段代码1:

  somevar = 5;
  delete window.somevar;
  alert(typeof somevar) //=> undefined, so deleted
Run Code Online (Sandbox Code Playgroud)

这段代码:

  var somevar = 5;
  delete window.somevar;
  alert(typeof somevar) //=> number, so NOT deleted
Run Code Online (Sandbox Code Playgroud)

在这里看到它

现在在第一个块中,somevar删除,在第二个块中,它不是.唯一的区别是var在第二个块中使用关键字.两个块都在全局范围内运行.

这可以解释一下吗?

1代码不能在chrome-console或firebug中测试,也不能在jsfiddle中测试.在这些环境中,所有代码都是evalled,并且在evalled代码中delete可以处理任何结果eval(请参阅更多相关信息).在IE <9delete window[anything]中无论如何都是不允许的.

T.J*_*der 11

您所看到的是这样一个事实:全局对象(window在浏览器上)是两个不同事物的混合,除了全局执行上下文之外,它们在任何地方都是不同的.

在第一个块中,someVarwindow对象的普通属性.属性可以通过删除delete.

在第二个块中,someVar是全局执行上下文的变量上下文绑定对象的属性- 也是.您无法删除绑定对象在其作为绑定对象的角色中接收的属性(即使您可以删除以其他方式接收的属性).也就是说,你不能删除声明的变量(和其他一些以相同方式添加的东西).windowvar

(对不起,不是我的术语;它来自规范,确实有一些非常有趣的语言.)

它只是全局执行上下文,我们有这种概念的混合.其他执行上下文(例如函数调用)的变量绑定对象仍然是一个非常真实的东西(对于闭包的正常运行至关重要),但是没有直接访问它的编程方式.但是,在全局执行上下文中,它是全局对象,当然我们可以访问它.

如果我们首先查看函数,然后查看全局执行上下文,这有助于理解这一点.当你调用一个函数时,会发生以下事情:

  1. 设置this为指向调用指定的对象(this通常隐式设置值,但有明确设置的方法).
  2. 为此调用创建执行上下文.
  3. 为该执行上下文创建变量上下文.
  4. 为该变量上下文创建绑定对象.
  5. 将函数的名称(如果有)添加到绑定对象作为引用该函数的属性.
  6. 将该arguments属性添加到绑定对象,引用该函数的伪参数数组.
  7. 添加在函数定义中声明的任何命名参数作为绑定对象的属性,引用它们在参数中的条目.
  8. 添加通过var语句声明的任何变量的名称(在函数体中的任何位置)作为绑定对象的属性,最初使用该值undefined.
  9. 如果在函数中声明了命名函数,请将它们的名称添加为绑定对象的属性,并引用这些函数.
  10. 将绑定对象放在作用域链的顶部(更多下方).

...然后开始逐步执​​行函数体中的代码.var具有初始值设定项的任何语句(例如,var a = 5;而不是仅在执行点到达时将其var a;视为赋值语句(a = 5;)).

综上所述,只要将属性添加到"绑定对象",就会添加一个表示无法删除的标志.这就是var无法删除s(以及声明的函数的名称等)的原因.

通过范围链查找任何不合格的引用.因此,当您a在代码中引用时,解释器所看到的第一个位置是作用域链顶部的绑定对象.如果它有一个叫做的属性a,那就是被使用的东西; 如果没有,我们会查看范围链中的下一个链接,并在找到它时使用该属性; 等等,直到我们用完范围链上的链接.全局对象是该链的最底层链接(这就是全局变量起作用的原因).

那么全球背景有什么不同呢?嗯,实际上很少.这是序列(大致):

  1. 为此调用创建执行上下文.
  2. 为该执行上下文创建变量上下文.
  3. 为该变量上下文创建绑定对象.
  4. 设置this为指向绑定对象; 这使它成为全球对象.
  5. 根据环境的定义在该对象上设置一些默认属性(例如,在浏览器中,属性window被添加到对象中,引用自身).

...然后我们基本上接受了函数中的第8步:

  • 添加通过var语句声明的任何变量的名称(在全局范围内的任何位置)作为绑定/全局对象的属性,最初使用该值undefined.
  • 如果在全局范围内声明了命名函数,请将它们的名称添加为绑定/全局对象的属性,并引用这些函数.
  • 将绑定/全局对象放在作用域链的顶部(下面更多).

...并开始逐步执​​行代码(再次使用var初始化程序成为赋值).