[ES6] let和const变量声明

本文详细介绍了ES6中的let和const命令,包括它们的块级作用域、不存在变量提升、不允许重复声明等特性。const用于声明常量,其值不可更改。let则解决了var的一些问题,如变量提升。此外,文章还探讨了在for循环中let如何避免闭包问题,并提供了两种解决方案。
摘要由CSDN通过智能技术生成

1.let命令

1.1块级作用域

它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
在代码块之外调用这两个变量,结果let声明的变量报错
给两个例子


var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10


var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

1.2 let不存在变量提升

var命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined。
let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

1.3不允许重复声明

let不允许在相同作用域内,重复声明同一个变量。否则报错。

2.const命令

const声明一个只读的常量。一旦声明,常量的值就不能改变。否则会报错。


const PI = 3.1415;
PI // 3.1415

PI = 3;
// TypeError: Assignment to constant variable.

const的作用域与let命令相同:只在声明所在的块级作用域内有效。声明的常量也是不提升。

ES5 只有两种声明变量的方法:var命令和function命令。**ES6 一共有 6 种声明变量的方法。**除了上述讲的let和const命令。包括另外两种声明变量的方法:import命令和class命令。

3.顶层对象的属性

顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象。
ES6 一方面规定 var 命令和 function 命令声明的全局变量,依旧是顶层对象的属性;
另一方面规定,let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。

4.JS中for循环里面的闭包问题的原因及解决办法


//循环里面包含闭包函数
function box(){
    var arr = [];
    for(var i=0;i<5;i++){
        arr[i] = function(){
            return i;                            //由于这个闭包的关系,他是循环完毕之后才返回,最终结果是4++是5
        }                                        //这个匿名函数里面根本没有i这个变量,所以匿名函数会从父级函数中去找i,
    }                                            //当找到这个i的时候,for循环已经循环完毕了,所以最终会返回5
    return arr;
}
//alert(box());                                    //执行5次匿名函数本身
//alert(box()[1]);                   //执行第2个匿名函数本身
//alert(box().length);                            //最终返回的是一个数组,数组的长度为5
alert(box()[0]());                                //数组中的第一个数返回的是5,这是为什么?

上面这段代码就形成了一个闭包:

闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。
在for循环里面的匿名函数执行 return i 语句的时候,由于匿名函数里面没有i这个变量,所以这个i他要从父级函数中寻找i,而父级函数中的i在for循环中,当找到这个i的时候,是for循环完毕的i,也就是5,所以这个box得到的是一个数组[5,5,5,5,5]。

方案一 匿名立即执行函数


function box(){
    var arr = [];
    for(var i=0;i<5;i++){
        arr[i] = (function(num){                    //自我执行,并传参(将匿名函数形成一个表达式)(传递一个参数)
            return num;                            //这里的num写什么都可以                    
        })(i);                                    //这时候这个括号里面的i和上面arr[i]的值是一样的都是取自for循环里面的i                            
    }                                            
    return arr;
}
//alert(box());                                
//alert(box()[1]);
//alert(box().length);                            
alert(box()[0]);    

通过给匿名函数传参,而传递的这个参数i是每次执行for循环里面的i,每次传递的参数i的值都不一样,匿名函数里面的num接收传递的参数i,所以box()最终输出结果为[0,1,2,3,4]

方案二 es6 let


function box(){
    var arr = [];
    for(let i=0;i<5;i++){        //使用let声明块级变量
        arr[i] = function(){
            return i;
        }
    }
    return arr;
}
var b = box();
alert(b[0]());   //0

上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

https://www.cnblogs.com/wgphp/p/7805152.html

补充:
另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。


for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
// abc
// abc
// abc


上面代码正确运行,输出了 3 次abc。这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值