在 Javascript 中,何时创建新范围? (使用新功能并在“with”语句中)只有这两种情况吗?

Posted

技术标签:

【中文标题】在 Javascript 中,何时创建新范围? (使用新功能并在“with”语句中)只有这两种情况吗?【英文标题】:In Javascript, when is a new scope created? (with a new function and in a "with" statement) Are these the only 2 situations? 【发布时间】:2011-02-13 10:09:44 【问题描述】:

javascript 中,何时创建新范围?我知道的两种情况是:

    有一个新函数(更新 2012/09,我认为它需要是函数调用,而不仅仅是函数定义) 在“with”语句中

请注意,任何新块(在 if-then-else、循环或无其他原因只是开始一个块)都不会创建新范围。

除了上述两种情况之外,还有第三种情况可以创建新的作用域吗?谢谢。

【问题讨论】:

EcmaScript 5 严格模式不再支持 with 语句。 建林,习惯性地接受你的问题的答案。与其说是回答者的代表,不如说是让其他感兴趣的社区知道已经得出结论。 重新定义与调用:我相信范围是函数的属性。调用函数时,会创建一个上下文来保存函数范围内变量的值。 【参考方案1】:

是的,当评估catch 块时,存在第三种情况,即作用域链被扩充(除了Shog9 提到的let mozilla-extension):

生产 Catch : catch (标识符)块被评估为 如下:

    令 C 为已传递给此产生式的参数。

    创建一个新对象,就像使用表达式 new Object()。

    在对象 Result(2) 中创建一个属性。该物业的名称是 标识符,值是C。值,和 属性是 DontDelete 。

    将 Result(2) 添加到 作用域链的前面。

    评估块。

    作用域链的前面移除Result(2)。

    返回结果(5)。

所以基本上,创建了一个新对象,将一个名为标识符的属性传递给catch,这个新对象被添加到作用域链中,因此我们可以在catch 块中使用该标识符。

try 
  throw "error";
 catch (identifier) 
  // `identifier` accessible here..

但请记住,它只是暂时扩充当前范围,引入catch标识符,内部声明的任何变量都将简单地提升到顶部它包含函数。

【讨论】:

非常好,在阅读本文之前从未考虑过捕捉评估! 在旧版本的 Firefox 中,您实际上可以获取新创建的范围对象! function getScope() try throw function () return this; ; catch (f) return f(); 通常当一个使用this 的函数被调用而不是一个方法时,它会返回全局对象。但是实现者从字面上理解“好像通过表达式 new Object()”,并将其实现为从先前范围继承的对象。一旦你得到了一个作用域对象,你就可以沿着原型链向上走去找到其他对象。【参考方案2】:

还有let statement。请记住,let (...) with (...) 一样,不会为在 块中引入的变量创建新范围。但是,let definitions 可以创建范围为定义它们的块(任何块)的变量。

公平警告:正如 cmets 中指出的那样,虽然 let 是 JavaScript 1.7(ECMA-262/ECMAScript 的 Mozilla 方言)的一部分,但它不是 em> 是 ECMAScript 的一部分,并且可能不会很快在 Firefox 以外的浏览器中工作。另请注意,虽然with can be used as a stand-in for let statements 在 ECMAScript 的当前实现中,但为待定的 ECMA-262 第 5 版提出的“严格”模式也不允许这样做。如果您担心编写跨平台、面向未来的代码(而且您应该...)那么坚持使用功能来控制范围

【讨论】:

因为您是对的,所以很想 +1,但这可能会引起一些混乱,因为它尚未广泛实施。哦......到底是什么,你赢得了它! @Andy,没有被广泛实施,因为它是一个 Mozilla 扩展,仅在 SpiderMonkey 和 Rhino 引擎上可用,并且不是 ECMAScript 标准的一部分。 @CMS,是的。我(诚然,错误地)写了 yet 因为let 是预期的 ECMAScript 4 规范的一部分,但从未出现过,而且我的大脑倾向于认为它可能会在未来的更新中返回标准。 @Andy,是的,我也认为let 将成为ECMAScript Harmony 的一部分,下一步......【参考方案3】:

这也将引用您所在的对象:

a = 
   f: function() ... ,
   b: function()this.f()

a.b() //calls a.f

【讨论】:

这不是一个新的范围;如果是这样,您可以在 b 中执行 f() 而不使用 this。

以上是关于在 Javascript 中,何时创建新范围? (使用新功能并在“with”语句中)只有这两种情况吗?的主要内容,如果未能解决你的问题,请参考以下文章

java中静态成员变量、实例变量、局部变量何时创建、何时销毁?

何时使用 Spring 原型作用域?

如何(以及何时?)在 JSF 2.0 中删除 Session 范围的 bean

为什么 Web 开发人员需要学习一个 JavaScript 框架?

何时使用 javascript 而不是创建 aspx 页面?

如何创建 JavaScript 回调以了解图像何时加载?