删除:有人可以解释这种行为 [英] delete: can someone explain this behavior

查看:68
本文介绍了删除:有人可以解释这种行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比较此代码 1

Compare this code1:

  somevar = 5;
  delete window.somevar;
  alert(typeof somevar) //=> undefined, so deleted

此代码:

  var somevar = 5;
  delete window.somevar;
  alert(typeof somevar) //=> number, so NOT deleted

在此处查看此操作

现在在第一个区块中, somevar 被删除,在第二个块中没有删除。唯一的区别是在第二个块中使用 var 关键字。这两个块都在全球范围内运行。

Now in the first block, somevar is deleted, in the second block it's not. The only difference is using the var keyword in the second block. Both blocks run in the global scope.

可以解释一下吗?

1 代码无法在chrome-console或firebug中测试,也不能在jsfiddle中测试。在这些环境中,所有代码都是 evalled ,并且在evalled代码中 delete 适用于<$ c的结果$ c> eval (请参阅有关详情)。在IE<无论如何都不允许9 删除窗口[任何]

1 the code can't be tested in a chrome-console or firebug, and not in jsfiddle either. In those environments all code is evalled, and in evalled code delete works on anything that is the result of eval (see more about that). In IE < 9 delete window[anything] is not allowed anyway.

推荐答案

什么你看到的是全局对象(浏览器上的窗口)是两个不同事物的混合这一事实的一个方面,除了全局执行上下文之外,它们在任何地方都是不同的。

What you're seeing is an aspect of the fact that the global object (window, on browsers) is a conflation of two different things which are distinct everywhere except the global execution context.

在第一个区块中, someVar 窗口的正常属性对象。可以通过 delete 删除属性。

In the first block, someVar is a normal property of the window object. Properties can be removed via delete.

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

In the second block, someVar is a property of the binding object of the variable context of the global execution context — which is also window. You cannot delete properties the binding object receives in its role as the binding object (even though you can delete properties it receives in other ways). That is, you cannot delete variables declared with var (and a few other things that are added the same way).

(对不起,不是我的术语;它来自规范,其中包含一些内容确实非常有趣的语言。)

(Sorry, not my terminology; it comes from the spec, which features some very fun language indeed.)

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

It's only the global execution context where we have this conflation of concepts. The variable binding object for other execution contexts (function calls, for instance) is still a very real thing (and crucial to proper functioning of closures), but there's no programmatic way to directly access it. In the global execution context, though, it's the global object, which of course we can access.

如果我们首先查看函数,然后再查看它有助于理解这一点。在全球执行环境中。当你调用一个函数时,会发生以下情况:

It helps to understand this if we look at functions first, and then look at the global execution context. when you call a function, these things happen:


  1. 设置这个指向调用指定的对象(的值通常是隐式设置的,但有明确的方法可以设置它。)

  2. 为此调用创建执行上下文

  3. 为该执行上下文创建变量上下文

  4. 为该变量上下文创建绑定对象

  5. 将函数的名称(如果有的话)添加到绑定对象作为引用该属性的属性函数。

  6. 参数属性添加到绑定对象,引用函数参数的伪数组。

  7. 将在函数定义中声明的任何命名参数添加为绑定对象的属性,引用它们在参数中的条目。

  8. 添加任何变量的名称通过函数bo中的 var 语句(任何地方)声明dy)作为绑定对象的属性,最初的值为 undefined

  9. 如果在函数中声明了已命名的函数,请添加它们的名称作为绑定对象的属性,引用那些函数。

  10. 将绑定对象放在作用域链的顶部(更多下面)。

  1. Set this to point to the object designated by the call (the value of this is usually implicitly set, but there are ways to set it explicitly).
  2. Create an execution context for this call.
  3. Create a variable context for that execution context.
  4. Create a binding object for that variable context.
  5. Add the function's name, if it has one, to the binding object as a property referring to the function.
  6. Add the arguments property to the binding object, referring to the pseudo-array of arguments to the function.
  7. Add any named arguments declared in the function definition as properties of the binding object, referring to their entries in the arguments.
  8. Add the names of of any variables declared via var statements (anywhere in the function body) as properties of the binding object, initially with the value undefined.
  9. If there are named functions declared within the function, add their names as properties of the binding object, referring to those functions.
  10. Put the binding object at the top of the scope chain (more below).

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

...and then step-by-step execution of the code in the body of the function begins. Any var statements with initializers (e.g., var a = 5; rather than just var a; are treated as assignment statements (a = 5;) when the execution point reaches them.

在上面的内容中,每当一个属性被添加到绑定对象时,它就会添加一个标志,指示它不能被删除。这就是为什么 var s (以及声明的函数的名称等)不能删除。

Throughout the above, whenever a property is added "to the binding object", it's added with a flag indicating that it cannot be deleted. This is why vars (and the names of declared functions, etc.) can't be deleted.

通过范围链查找任何不合格的引用。因此,当您在代码中引用 a 时,解释器看起来的第一个位置是作用域链顶部的绑定对象。如果它有一个名为<$ c的属性$ c> a ,这就是使用的东西;如果没有,我们会查看范围链中的下一个链接并在我们找到它时使用该属性;依此类推,直到我们用尽链接范围链。全局对象是该链的最底层链接(这就是全局变量的原因) k)。

Any unqualified reference is looked up via the scope chain. So when you refer to a in your code, the first place the interpreter looks is the binding object at the top of the scope chain. If it has a property called a, that's what gets used; if not, we look at the next link down the scope chain and use that property if we find it; and so on until we run out of links on the scope chain. The global object is the bottommost link of that chain (which is why global variables work).

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

So what's different about the global context? Well, very little, actually. Here's the sequence (roughly):


  1. 为此调用创建执行上下文

  2. 为该执行上下文创建变量上下文

  3. 为该变量上下文创建绑定对象

  4. 设置指向绑定对象;这使得它成为全局对象。

  5. 在环境定义的对象上设置一些默认属性(在浏览器中,例如,属性 window 被添加到对象中,指自己)。

  1. Create an execution context for this call.
  2. Create a variable context for that execution context.
  3. Create a binding object for that variable context.
  4. Set this to point to the binding object; that makes it the global object.
  5. Set some default properties on that object as defined by the environment (in browsers, for instance, the property window is added to the object, referring to itself).

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

...and then we basically pick up with step 8 in the function stuff:


  • 添加通过 var 语句声明的任何变量的名称(全局范围内的)作为绑定/全局对象的属性,最初的值为 undefined

  • 如果在全局范围内声明了已命名的函数,请将它们的名称添加为绑定/全局对象的属性,并引用这些函数。

  • 将绑定/全局对象放在范围链的顶部(更多信息如下)。

  • Add the names of of any variables declared via var statements (anywhere in the global scope) as properties of the binding/global object, initially with the value undefined.
  • If there are named functions declared within the global scope, add their names as properties of the binding/global object, referring to those functions.
  • Put the binding/global object at the top of the scope chain (more below).

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

...and start step-by-step execution of the code (again with var initializers becoming assignments).

这篇关于删除:有人可以解释这种行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆