[英]delete: can someone explain this behavior
Compare this code 1 :
比较这段代码1 :
somevar = 5;
delete window.somevar;
alert(typeof somevar) //=> undefined, so deleted
to this code: 这段代码:
var somevar = 5;
delete window.somevar;
alert(typeof somevar) //=> number, so NOT deleted
Now in the first block, somevar
is deleted, in the second block it's not. 现在在第一个块中,
somevar
被删除,在第二个块中则没有。 The only difference is using the var
keyword in the second block. 唯一的区别是在第二个块中使用
var
关键字。 Both blocks run in the global scope. 两个块都在全局范围内运行。
Can this be explained? 这可以解释一下吗?
1 the code can't be tested in a chrome-console or firebug, and not in jsfiddle either.
1代码不能在chrome-console或firebug中测试,也不能在jsfiddle中测试。 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 ). 在这些环境中,所有代码都被
evalled
,并且在evalled代码中, delete
可以处理eval
任何结果(请参阅更多信息 )。 In IE < 9 delete window[anything]
is not allowed anyway. 在IE <9中,无论如何都不允许
delete window[anything]
。
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. 您所看到的是这样一个方面:全局对象(
window
,浏览器)是两个不同事物的混合,除了全局执行上下文之外,它们在任何地方都是不同的。
In the first block, someVar
is a normal property of the window
object. 在第一个块中,
someVar
是window
对象的普通属性。 Properties can be removed via delete
. 可以通过
delete
属性。
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
. 在第二个块中,
someVar
是全局执行上下文的变量上下文的绑定对象的属性 - 也是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). 也就是说,你不能删除用
var
声明的变量(以及其他一些以相同方式添加的东西)。
(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:
当你调用一个函数时,会发生以下事情:
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). this
为指向由调用指定对象的值( this
通常是隐式设置,但有办法来设置它明确)。 arguments
property to the binding object, referring to the pseudo-array of arguments to the function. arguments
属性添加到绑定对象,引用函数参数的伪数组。 var
statements ( anywhere in the function body) as properties of the binding object, initially with the value undefined
. var
语句声明的任何变量的名称(在函数体中的任何位置 )作为绑定对象的属性,最初使用值undefined
。 ...and then step-by-step execution of the code in the body of the function begins. ...然后开始逐步执行函数体中的代码。 Any
var
statements with initializers (eg, var a = 5;
rather than just var a;
are treated as assignment statements ( a = 5;
) when the execution point reaches them. 任何带有初始值设定项的
var
语句(例如, var a = 5;
而不仅仅是var a;
当执行点到达时,它们被视为赋值语句( a = 5;
)。
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
var
s (and the names of declared functions, etc.) can't be deleted. 这就是无法删除
var
s(以及声明的函数的名称等)的原因。
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. 因此,当您在代码中引用
a
时,解释器所看到的第一个位置是作用域链顶部的绑定对象。 If it has a property called a
, that's what gets used; 如果它有一个名为
a
的属性,那就是使用它; 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):
这是序列(大致):
this
to point to the binding object; this
指向绑定对象; that makes it the global object. window
is added to the object, referring to itself). window
被添加到对象中,引用自身)。 ...and then we basically pick up with step 8 in the function stuff: ...然后我们基本上接受了函数中的第8步:
var
statements ( anywhere in the global scope) as properties of the binding/global object, initially with the value undefined
. var
语句声明的任何变量的名称(在全局范围内的任何位置 )作为绑定/全局对象的属性,最初使用值undefined
。 ...and start step-by-step execution of the code (again with var
initializers becoming assignments). ...并开始逐步执行代码(再次使用
var
初始化程序成为赋值)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.