二、let变量声明方式介绍

153 阅读2分钟

作用域指的是一个变量的生命周期,也就是说,在代码中它是可见的。
在es5以前,是没有块级作用域的概念的,在es6中才引入进来的,在传统的java和c++中块级作用域是包裹在{ }里面的代码

{
//这里面的是块级作用域
}

==//这边不是块级作用域==

以上所示是其他语言的块级作用域,以上可知,声明一个变量在块中,只能在块中可见和其他内嵌的块中可见

但是在es5中,只有两种作用域,就是全局作用域和函数作用域,所以,如果写

{
  var a = "block";
}
console.log(a);		//block

以上可以看出,变量a存在于全局范围内,所以作用范围也在全局。

在es5中,除了全局作用域,就是函数作用域了

function hello() {
    var a = "function";
}
hello();
console.log(a);		//a is not defined

报错是因为a变量声明在函数内部,所以作用范围只在函数内部,但是如果在函数体内部加上for循环的话

function hello() {
    var a = "function";
    for (var i = 0; i < 10; i++) {
        var a = "block";
    }
    console.log(a);
}
hello(); 	//block

没有块级作用域,但是有很多替代方案,大部分都是用闭包的原理,比如以下其中一种方案
==IIFE(Immediately Invoked Function Expression)自执行函数==

function hello() {
    var a = "function";

    for (var i=0; i<5; i++) {
        (function() {
            var a = "block";
        })();
    }
    console.log(a);
}
hello();	//function

以上就会打印出function

在es5中,使用块级作用域特别麻烦,直到es6中出现了let块级元素,可以用简短的写法就解决以上问题,同样上面的例子我们可以写为

function hello() {
    var a = "function";
    for (var i = 0; i < 5; i++) {
        let a = "block";
    }
    console.log(a);
}
hello();	//function

现在,for循环体中声明的a只存在于{ }里面,上面的代码片段按预期打印出函数。
在循环中使用let

var funcs = [];
for (var i = 0; i < 5; i += 1) {
    var y = i;
    funcs.push(function () {
        console.log(y);
    })
}
funcs.forEach(function (func) {
    func()	//4	4	4	4	4
});

以上例子我们本来想输出0 1 2 3 4的,结果....当然也可以使用IIFE,但是那样太麻烦了,而使用let

var funcs = [];
for (var i = 0; i < 5; i += 1) {
    let y = i;
    funcs.push(function () {
        console.log(y);
    })
}
funcs.forEach(function (func) {
    func()
});

就直接得到了想要的结果0 1 2 3 4 以上无非就是想输出0 1 2 3 4,其实还有更简单的方法

var funcs = [];
for (let i = 0; i < 5; i += 1) {
    funcs.push(function () {
        console.log(i);
    })
}
funcs.forEach(function (func) {
    func()
});

上面在循环中声明i,所以i的作用域在循环内部,具体解释起为什么,还得涉及到域解析的过程; 还得注意的是let声明方式不能重复声明,如:

let a=10;
let a=20;

这样会报错Identifier 'a' has already been declared