什么是块范围函数ECMAScript 6与ECMAScript 5比较

nih*_*rma 16 javascript

ECMAScript 6中的块作用域功能是什么?

任何人都可以帮助我理解块区域功能与ECMAScript 5相比的主要区别吗?

T.J*_*der 42

新款letconstES2015(又称"ES6")与古老版相比有四个主要差异var:

  1. 他们有块范围

  2. 它们没有悬挂(好吧,它们有点悬挂,但是有用的方式)

  3. 重复声明是错误

  4. 在全局范围内使用时,它们不会创建全局对象的属性(尽管创建全局变量;这是ES2015的新概念)

阻止范围

var 变量存在于它们声明的函数中(或全局地,如果全局声明),它们不限于它们所在的块.所以这段代码是有效的:

function foo(flag) {
    a = 10;
    if (flag) {
        var a = 20;
    }
    return a;
}
console.log(foo(false)); // 10
console.log(foo(true));  // 20
Run Code Online (Sandbox Code Playgroud)

a无论是否flag为真,它都被定义,并且它存在于if块之外; a以上三个都是相同的变量.

let(或const)不是这样的:

function foo(flag) {
    if (flag) {
        let a = 10;
    }
    return a;           // ReferenceError: a is not defined
}
console.log(foo(true));
Run Code Online (Sandbox Code Playgroud)

a只存在它在声明块中.(有关for声明,声明中()for有效认为是块的一部分.)所以外if,a不存在.

letconst声明可以在封闭范围内影子声明,例如:

function foo() {
    let a = "outer";

    for (let a = 0; a < 3; ++a) {
        console.log(a);
    }
    console.log(a);
}
foo();
Run Code Online (Sandbox Code Playgroud)

那输出

0
1
2
outer

......因为afor循环是不一样a的一个内部for循环.

吊装

这是有效的代码:

function foo() {
    a = 5;
    var a = a * 2;
    return a;
}
Run Code Online (Sandbox Code Playgroud)

奇怪的,但有效(它返回10),因为var在函数中完成任何其他操作之前完成,所以这是真的:

function foo() {
    var a;             // <== Hoisted

    a = 5;
    a = a * 2;         // <== Left where it is
    return a;
}
Run Code Online (Sandbox Code Playgroud)

这不是真的letconst:

function foo() {
    a = 5;            // <== ReferenceError: a is not defined
    let a = a * 2;
    return a;
}
Run Code Online (Sandbox Code Playgroud)

在声明之前,您不能使用该变量.该声明并未"悬挂"(好吧,它已被部分悬挂,继续阅读).

我早些时候说过

  1. 它们没有悬挂(好吧,它们有点悬挂,但是有用的方式)

"有点"?是.A letconst声明在整个出现的块中隐藏标识符,即使它实际上只在它出现的地方生效.示例帮助:

function foo() {
    let a = "outer";

    for (let x = 0; x < 3; ++x) {
        console.log(a);            // ReferenceError: a is not defined
        let a = 27;
    }

}
Run Code Online (Sandbox Code Playgroud)

请注意"outer",我们收到错误而不是进入控制台.为什么?因为let afor块阴影的a外块,尽管我们还没有得到它呢.块的开头和之间的空间let被规范称为"时间死区".单词不是每个人的事情,所以这是一个图表:

TMZ

重复声明

这是有效的代码:

function foo() {
    var a;

    // ...many lines later...
    var a;
}
Run Code Online (Sandbox Code Playgroud)

第二个var被忽略了.

let(或const)不是这样的:

function foo() {
    let a;

    // ...many lines later...
    let a;                     // <== SyntaxError: Identifier 'a' has already been declared
}
Run Code Online (Sandbox Code Playgroud)

不是全局对象属性的全局变量

JavaScript具有"全局对象"的概念,它将各种全局事物作为属性保存.在松散模式下,this全局范围是指全局对象,而在浏览器上有一个全局引用全局对象:window.(某些其他环境提供不同的全局,例如global在NodeJS上.)

在ES2015之前,JavaScript中的所有全局变量都是全局对象的属性.由于ES2015的,这仍然与那些宣称真正的var,但声明没有那些letconst.因此,var在全局范围内,在浏览器上使用此代码显示42:

"use strict";
var a = 42; // Global variable called "a"
console.log(window.a); // Shows 42, because a is a property of the global object
Run Code Online (Sandbox Code Playgroud)

但是此代码显示undefined了属性,因为let并且const在全局范围内不会在全局对象上创建属性:

"use strict";
let a = 42; // Global variable called "a"
console.log(a); // 42 (of course)
console.log(window.a); // undefined, there is no "a" property on the global object
const q = "Life, the Universe, and Everything"; // Global constant
console.log(q); // "Life, the Universe, and Everything" (of course)
console.log(window.q); // undefined, there is no "q" property on the global object
Run Code Online (Sandbox Code Playgroud)


最后的注释:如果你class用功能声明(而不是函数表达式)比较新的ES2015 (它提供了一个新的,更清晰的语法来创建构造函数和与它相关的原型对象),上述内容也是如此:

  • class声明具有块范围.相反,在流控制块中使用函数声明是无效的.(它应该是一个语法错误;相反,不同的JavaScript引擎以不同的方式处理它.有些将它重定位到流控制块之外,其他的就像你使用了函数表达式一样.)
  • class声明没有悬挂; 函数声明是.
  • class在同一范围内使用具有两个声明的相同名称是语法错误; 使用函数声明,第二个获胜,覆盖第一个.
  • class全局范围内的声明不会创建全局对象的属性; 函数声明呢.

提醒一下,这是一个函数声明:

function Foo() {
}
Run Code Online (Sandbox Code Playgroud)

这些都是函数表达式(匿名的):

var Foo = function() {
};
doSomething(function() { /* ... */ });
Run Code Online (Sandbox Code Playgroud)

这些都是函数表达式(命名的):

var Foo = function Foo() {
};
doSomething(function Foo() { /* ... */ });
Run Code Online (Sandbox Code Playgroud)

  • 这教会了我很多关于ES6中可变吊装的知识.但问题是围绕ES6中的函数范围和块范围函数. (3认同)

归档时间:

查看次数:

5617 次

最近记录:

9 年,11 月 前