1

例行声明:接下来的文字内容全部来自 Understanding ECMAScript 6,作者是Nicholas C.Zakas,也就是大名鼎鼎的Professional JavaScript for Web Developers(《JavaScript高级程序设计》)的作者。我很喜欢他的写作风格,所以在看了Understanding ECMAScript 6后试着自己写篇博客梳理一下,相当于简单地翻译和巩固一下吧。在此特别感谢Nicholas的原创,我只是一个小矮人,站在巨人的肩膀上,所以看到了原本看不到的风景。
附上英文原文链接:https://leanpub.com/understan...

1: 背景介绍
在严谨模式下面,ES6之前,在一个block里面定义一个functoin是会抛出语法错误的,例如:

"use strict";

if (true) {

    // Throws a syntax error in ES5, not so in ES6
    function doSomething() {
    // ...
    }
}

在ES6,我们引入了块级函数,接下来看一下如何使用块级函数。

2: 如何定义一个 block-level function

'use strict';
if(true){
    function a(){
        //...
    }
    console.log(typeof a);//function
}
console.log(typeof a); //undefined

在if创建的一个块级作用域里面,我们定义了一个function a,然后在这个块级作用域里面执行typeof a,得到结果function,然后在if 创建的这个块级作用域外去执行typeof a,得到结果为undifined.这说明这个function a在其被定义的块级作用域里面可见,在这个块级作用域之外不可见。

3: block-level function的作用域提升
大家都知道,平常我们除了用1: function xx(){}这种方式来定义一个function外,也可以采用function expression: 2: let xx = function(){}.在用这两种方式来定义的block-level function在作用域提升的表现方面是截然不同的: 第一种会提升,第二种不会。,举例说明:

'use strict';
if(true){
    console.log(typeof a)//function
    function a(){
        /...
    }
}


'use strict';
if(true){
    console.log(typeof a)// uncaught ReferenceError: a is not defined
    let a = function(){
        /...
    }
}

从上面的对比可以看出,用let定义的function, 作用域不会提升,当执行typeof a的时候,抛出一个错误。这个本质上是let引起的临时死区的问题,具体可以参照变量的临时死区

4: 在非严谨模式下block-level function的作用域
在前面的1,2, 3点,我们都是在严格模式下面的探讨。但是,block-level funciton的作用域提升在严格模式和非严格模式下面的表现是不一样的。
4.1:let xx = function(){}也就是用function expression这种方式定义的block-level function在严格模式和非严格模式下表现一样:会抛出错误uncaught ReferenceError: xx is not defined.所以不做过多讨论。

4.2: 现在来看一个用function xx(){}的方式定义block-level funciton时的表现,且这个block是在另一个function里面
图片描述

上图是在Chrome Version 55.0.2883.95下面执行的结果。

* 从执行结果来看只有output 2的结果是function,这个是我们之前已经讨论过了的在block内部的作用域提升。
* 结合ouput 1和output 3的结果来看,block-level function的作用域会被提升到整个 function,但只在其定义代码执行之后的区间。
* output 4的结果表明,此种场景下,作用域并不会被提升至global.

4.3 在global下面的block里面定义一个block-level function
图片描述

从执行结果看来,此种场景下,作用域会被提升至global,但是也得是在其定义之后的区间,在其被定义的block之前的global区间之内,是不可见的。

所以我们可以做一个关于块级函数的作用域的完整的总结:

1: 对于function expression,无论在严格模式还是非严格模式下,作用域都不会提升,而且还有有临时死区的特征。
2: 对于定义形的块级函数,在严格模式下,作用域不会提升。
3: 对于定义形的块级函数,在非严格模式下,作用域会被提升;但是提升的区间为其最近的一层作用域内,且在其定义之后。

nanaistaken
586 声望43 粉丝