在 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中静态成员变量、实例变量、局部变量何时创建、何时销毁?
如何(以及何时?)在 JSF 2.0 中删除 Session 范围的 bean
为什么 Web 开发人员需要学习一个 JavaScript 框架?