var let const 区别

一句话,let和const是var的改良版,能用const就不用let, 能用let就不用var。
一、var的缺陷,先来看看使用var定义变量会有哪些问题:
1.var不是块级作用域,下面的代码循环已经结束了,却还可以访问到变量test,可能会引起bug

    for(var i=0;i<10;i++){
        var test = i;
    }

    console.log(test);//9
    console.log(i)//10 用来记数的变量也可以访问, 无意中就污染了全局变量

2.var定义的变量,有变量提升,变量提升,会对程序的维护带来困扰。

    if(true){
        console.log('执行了');
    }else{
        console.log('没执行');
        var j = 2;
    }

    console.log(j);   //输出undefined 定义变量j的代码虽然没有执行,但是却依然不会报错 

3.var定义的变量,不会为异步任务单独绑定变量,下面这段代码,本意是让它每隔一段时间输出0-9,结果却输出了10个10

for (var i = 0; i < 3; i++) {
      setTimeout(function () {
        console.log(i)
      }, 1000);
 }

4.var定义的变量,可以重复定义,这样就显得非常的随意松散

    var a =1;
    var a =2;

    console.log(a);//输出后面定义的2

二、let和const就是ES6针对以上问题提出的解决方案,let和var的区别具体如下:
1.let声明的变量是块级作用域的,这个特性解决了原来使用var容易污染全局变量的弊端。

    for(let i=0;i<10;i++){
        let test = i;
    }

    console.log(i);//Uncaught ReferenceError: i is not defined
    console.log(test)//Uncaught ReferenceError: test is not defined

2.let声明的变量不存在变量提升,从let的块级作用域开始,到初始化位置,称作“暂存死区”,对于变量的暂存死区中使用变量会报Reference错误。这个特性就使得我们先定义变量再使用的变量,避免了var变量提升带来的难以查找的bug,也增强了代码的可读性。(也有文章认为let和const是有变量提升的,但是从结果上我们直接把let和const理解成没有变量提升是正确的。)

    //使用var
    console.log(i); // 输出undefined
    var i = 2;

    //使用let
    console.log(j);
    let j =10; //Uncaught ReferenceError: Cannot access 'j' before initialization

3.var可以重复定义变量,而let不可以,使得定义变量不再像var那么随意

    //使用var
    var  a = 1;
    var  a = 2;
    console.log(a); // var可以重复定义,输出2

    //使用let
    let i =1;
    let i =2;
    console.log(i);// let不能重复定义, Uncaught SyntaxError: Identifier 'i' has already been declared

4.var定义的全局变量属于顶层对象,而let、const声明的全局变量属于顶层对象,这也很容易理解, 因为let的设计初衷就是块级作用域变量,不污染全局变量,显得自由灵活安全。以浏览器为例:

var a = 0;
console.log(window.a) // 0
let b = 1;
console.log(window.b) // undefined

三、以上let具有的特性,const都有,const和let的区别如下:
1.const在声明常量的时候, 一定要初始化一个值:

     const a=1; //正确
     const b = 1;
     b = 5;  //TypeError: Assignment to constant variable.
    const c;  //SyntaxError: Missing initializer in const declaration

2.const定义的常量值不允许修改,

const a = 0;
a = 1; // TypeError: Assignment to constant variabl

但是如果常量的类型为复杂类型(对象、数组等)时,对于常量值本身的操作是可以的, 因为const命令只是保证变量名指向的地址不变,并不保证该地址的数据不变。

     const a = {};
     a.name='小明'
    console.log(a);
     a = {name:'小明'};
     console.log(a);

四、总结
1.let和const声明的变量时块级作用域,避免了无意中全局变量污染,更加的灵活安全。另一个好处就是在循环语句中,let关键字为每次循环绑定单独绑定一个变量。
2.let和const没有变量提升,提高了代码的可维护性。
3.let和const不可以重复定义变量,修复var可以重复定义变量,使得变量的定义不再随意任性。
4.let和const定义的变量不属于顶层对象。目的也是为了让变量定义更加自由灵活安全。
5.const声明一个常量的时候,一定要赋值。
6.const声明的常量并非真正意义上的常量,只保证变量名指向的地址不变,并不保证该地址的数据不变。
五、拓展
1.对于以下代码,改如何改正

    //本意是要输出0-9,这段代码却输出10个10
    for (var i = 0; i < 10; i++) {
        setTimeout(function () {
            console.log(i)
        }, 1000);
    }

解析:在js中先执行同步任务,再执行异步任务,setTimeout里面的代码是异步任务,等到执行时,var声明的变量i已经是10了。
解法1,利用setTimeout函数的第三个参数把i单独绑定

    for (var i = 0; i < 10; i++) {
        setTimeout(function (i) {
            console.log(i)
        }, 1000, i);
    }

解法2,利用闭包强制让setTimeout记住变量i

        (function(i){
            setTimeout(function () {
                console.log(i) 
            }, 1000)
        })(i);

解法3,利用let关键字

    for (let i = 0; i < 10; i++) {
            setTimeout(function () {
                console.log(i)
            }, 1000)
    }

2.对于以下代码,本意是要每隔1秒输出0-9,但这段代码的效果却是1秒钟后,同时输出了0-9,如何修正?

    for (let i = 0; i < 10; i++) {
            setTimeout(function () {
                console.log(i)
            }, 1000)
    }

解析:在js中先执行同步任务,再执行异步任务,setTimeout函数的第二参数,相对的是同步任务结束的那一刻, 而不是上一个异步任务结束的那一刻,所以,修正的方法是动态改变第二个参数。

    for (let i = 0; i < 10; i++) {
            setTimeout(function () {
                console.log(i)
            }, 1000*i)
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值