gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-11-01 04:58:40 27 4
gpt4 key购买 nike

比较这段代码1:

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

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

See it in action here

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

可以解释吗?

1该代码无法在chrome-console或firebug中测试,也不能在jsfiddle中进行测试。在那些环境中,所有代码都是 evalled,而在已评估的代码中, delete可以处理 eval所产生的任何结果(请参阅 more about that)。在IE <9中,无论如何都不允许 delete window[anything]

最佳答案

您所看到的是以下事实的一个方面:全局对象(浏览器上的window)是两个不同事物的组合,除了全局执行上下文外,这两个事物在其他地方都是不同的。

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

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

(抱歉,不是我的术语;它来自the spec,它确实具有一些非常有趣的语言。)

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

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

  • 设置this指向由调用指定的对象(this的值通常是隐式设置的,但是有一些方法可以显式设置它)。
  • 为此调用创建执行上下文。
  • 为该执行上下文创建变量上下文。
  • 为该变量上下文创建一个绑定(bind)对象。
  • 将函数名称(如果有的话)添加到绑定(bind)对象中,作为引用该函数的属性。
  • arguments属性添加到绑定(bind)对象,引用该函数的参数伪数组。
  • 添加在函数定义中声明的所有命名参数作为绑定(bind)对象的属性,并引用它们在参数中的条目。
  • 将通过var语句声明的任何变量的名称(在函数主体中的任何位置)添加为绑定(bind)对象的属性,其初始值为undefined
  • 如果在函数中声明了命名函数,请引用这些函数将其名称添加为绑定(bind)对象的属性。
  • 将绑定(bind)对象放在范围链的顶部(更多内容在下面)。

  • ...然后开始逐步执​​行函数体内的代码。当执行点到达时,任何带有初始化器的 var语句(例如 var a = 5;而不是 var a;)都被视为分配语句( a = 5;)。

    在上述内容中,每当将属性“添加到绑定(bind)对象”时,都会添加一个标志,指示该属性无法删除。这就是为什么 var(以及声明的函数的名称,等等)无法删除的原因。

    通过范围链查找任何不合格的引用。因此,当您在代码中引用 a时,解释器首先看到的是绑定(bind)对象,位于范围链的顶部。如果它具有名为 a的属性,则将使用该属性。如果不是,我们查看作用域链中的下一个链接,并在找到该属性时使用该属性;以此类推,直到我们用完范围链上的链接。全局对象是该链的最底层链接(这就是全局变量起作用的原因)。

    那么全局背景有何不同?好吧,实际上很少。这是顺序(大致):
  • 为此调用创建执行上下文。
  • 为该执行上下文创建变量上下文。
  • 为该变量上下文创建一个绑定(bind)对象。
  • 设置this指向绑定(bind)对象;这使其成为全局对象。
  • 根据环境的定义在该对象上设置一些默认属性(例如,在浏览器中,window属性被添加到该对象中,是指其自身)。

  • ...然后我们基本上从函数中的第8步开始:
  • 将通过var语句(在全局范围内的任何地方)声明的任何变量的名称添加为绑定(bind)/全局对象的属性,其初始值为undefined
  • 如果在全局范围内声明了命名函数,请将它们的名称添加为绑定(bind)/全局对象的属性,并引用这些函数。
  • 将绑定(bind)/全局对象放在范围链的顶部(更多内容在下面)。

  • ...并逐步执行代码(再次将 var初始化程序变为赋值操作)。

    关于javascript - 删除:有人可以解释这种行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5989408/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com