Javascript中的块作用域、函数作用域和局部作用域

Posted

技术标签:

【中文标题】Javascript中的块作用域、函数作用域和局部作用域【英文标题】:Block scope, function scope and local scope in Javascript 【发布时间】:2015-08-22 16:21:39 【问题描述】:
    块作用域有时与函数作用域相同吗?我知道 function scope 适用于函数内的所有内容,但不知道 block scope 到底是什么。 对于 javascript,是否当前建议使用 let / const 而不是 var 以供将来维护? (来自Airbnb Style Guide)

【问题讨论】:

【参考方案1】:
    javascript 5 不使用阻塞作用域,它使用链式作用域。主要区别在于,除非您将其设为全局变量,否则您无法访问范围之外的变量。当您使用 let 声明变量时,ES 6 将具有阻塞范围。 目前建议使用 var,因为不完全支持 ES 6。

【讨论】:

ES6 有预计发布日期吗?我想知道为什么 Airbnb 这么早就建议我们使用 ES6 标准。 @ChenghuaYang:ES6 规范的预计发布日期已经有几年了,我认为有一段时间应该在 2012 年或 2013 年完成。上次我听说,是的,他们预计会是今年。但是当然,您必须等待供应商支持它,并等待人们升级他们的浏览器。至于 Airbnb,好吧,也许他们正在转换,或者他们只是在推动一个议程。 @ChenghuaYang Airbnb 团队已经在 ES6 中编写代码,但他们使用转译器(如 Traceur 或 Babel)转译为 ES5,以便他们的代码可以在当今的浏览器中使用。【参考方案2】:

块作用域有时与函数作用域相同吗?我知道函数作用域适用于函数内部的所有内容,但不知道块作用域到底是什么。

块范围是中的所有内容,例如:

function foo() 
    // function scope
    if (condition) 
        // block scope
    

在第 5 版规范中,JavaScript 没有块作用域。即将完成的下一个规范(ECMAScript 6,又名“ES6”)通过letconst 添加块范围。

对于 Javascript,目前是否建议使用let / const 代替 var 以方便日后维护?

这完全取决于您。 letconst 是您可以添加到您的腰带上的新工具。如果您不希望他们替换var,他们没有。也就是说,您经常听到“let 是新的var”。

let 声明的变量有块作用域,用var 声明的变量没有。

请注意letconst don't have great support in the wild yet。毫不奇怪,将块作用域添加到以前从未有过的引擎可能不是微不足道的。你可以使用像 Babel 这样的编译器,或者暂时继续使用var

【讨论】:

【参考方案3】:

我不确定你的问题是否真的得到了解答:

块作用域有时与函数作用域相同吗?我知道函数范围适用于函数内的所有内容,但不知道什么 正好是块作用域。

是的,块作用域有时与函数作用域相同。块作用域是一组大括号 a block scope here 内的所有内容。因此,在函数代码的顶部,块作用域将与函数作用域相同:

function test(x) 
   // this is both a block scope and a function scope
   let y = 5;
   if (x) 
       // this is a smaller block scope that is not the same as the function scope
       let z = 1;
   

对于 Javascript,目前是否推荐使用 let / const 代替 var 用于将来的维护? (来自 Airbnb 风格指南)

letconst 是最新的 ES6 规范的一部分,并且仅在最新的 Javascript 引擎中实现,有时在最新的引擎中它们仅通过特殊标志启用。它们将出现在所有较新的 JS 引擎/浏览器中,但尚未广泛部署。因此,如果您正在为广泛的 Internet 上的常规浏览器使用编写 Javascript,您还不能可靠地使用 letconst

在某些情况下,您现在可以安全地使用letconst 进行编程:

    如果您仅针对特定的 Javascript 引擎,并且您知道它支持这些功能(例如特定版本的 nodejs 或仅适用于特定浏览器的特定版本的插件)。

    如果您使用的转译器会将您的代码转换为可在所有浏览器中运行的代码。使用转译器时,您可以使用最新功能编写代码,转译器会将其“简化”,以便您的代码通过模拟新功能在旧浏览器中工作。

如果您正在为一个知道支持letconst 的环境编程,那么建议酌情使用它们。如果你在函数的顶部声明一个变量,那么letvar 会做同样的事情。

如果您在函数内声明一个较小范围内的变量,那么let 将包含在较小范围内,但var 将被提升到函数顶部并具有函数范围,无论在哪里它被声明了。


您链接到的AirBnb Style Guide 是专门为 ES6 环境编写的(请注意,他们的样式指南的 ES5 版本有一个单独的链接)。所以,这意味着他们假设了一个支持 ES6 的环境。这要么是因为他们的目标是他们知道支持 ES6 的服务器端 JS 引擎,要么是因为他们使用了一个转译器,可以将 ES6 代码转换为可以在 ES5 引擎上运行的东西。


关于转译器的说明。 在使用转译器并将所有变量声明在块作用域内切换为let 之前,有必要了解转译器生成什么样的代码以及它生成的额外代码是否对应用程序的性能有任何影响。例如,let 的块作用域是通过创建一个内联 IIFE 来模拟的,这可能会导致每个包含 let 语句的块的额外运行时开销。我并不是说这一定是一件坏事,应该阻止你使用转译器,但在决定是否使用转译器时,我建议你彻底熟悉各种 ES6 的转译代码的样子功能,让您知道它是适合您的任何工作还是仅适合某些工作。

【讨论】:

以上是关于Javascript中的块作用域、函数作用域和局部作用域的主要内容,如果未能解决你的问题,请参考以下文章

javascript中的作用域

JavaScript有关作用域和预解析

全新Java入门到架构师教程之JavaScript函数作用域和内置对象

JavaScript 作用域和作用域链

JavaScript作用域和作用域链

Javascript作用域链