01-声明变量(var、let、const)

var

说明

  1. 使用var声明变量,在方法内部是局部变量,在方法外部是全局变量

  2. 没有使用var声明的变量,在方法内部或外部都是全局变量,但如果在方法内部声明,在方法外部使用之前需要先调用方法,告知系统声明了全局变量后方可在方法外部使用

  3. 不使用var关键字声明的全局变量,不会前置

一、var声明变量的问题

  • (1)允许重复的变量声明:导致数据被覆盖

  • (2)变量提升:怪异数据访问(闭包问题)

    • 怪异数据访问:即变量提升导致块级作用域内的变量可以在外部访问到

    • 闭包问题

      var body = document.getElementsByTagName('body')[0];
      for (var i = 1; i <= 10; i++) {
          var btn = document.createElement('button');
          btn.innerHTML = '按钮' + i;
          body.appendChild(btn);
          btn.onclick = function () {
              console.log(i);
      //每次都是输出11
          }
      }
      
      //闭包
      for (var i = 1; i <= 10; i++) {  
                  var btn = document.createElement('button');  
                  btn.innerHTML = '按钮' + i;  
                  body.appendChild(btn); 
                  (function(s) {
                      btn.onclick = function() {    
                          console.log(s);  
                      }
                  })(i)
              }
      
      //或在使用let声明变量
      for (let i = 1; i <= 10; i++) {
          var btn = document.createElement('button');
          btn.innerHTML = '按钮' + i;
          body.appendChild(btn);
          btn.onclick = function () {
              console.log(i);
          }
      }
      
  • (3)全局变量挂载到全局对象,全局对象成员污染问题

    console.log(window.name);
    var name = 'abc';
    console.log(window.name);

二、let声明变量

  • (1)let声明的变量不会挂载到全局对象

    let a = 123;
    console.log(window.a);//underfined

  • (2)let不允许在当前作用域内重复声明,在块级作用域中用let声明的变量在作用域外不能访问

    • 重复声明变量会报错

    let a = 123;
    let a = 456;
    //报错
    • 作用域外访问块级作用域的变量会报错

    {
        let a = 123;
    }
    console.log(a);//报错

  • (3)使用let不会有变量提升,因此不能再let定义变量之前使用该变量

    • 在变量声明前去访问该变量会报错

    console.log(a); //报错,该错误提示为:不能在a初始化之前访问,而不是a未被定义
    let a = 123;
    ​
    //该错误提示为:不能在a初始化之前访问,而不是a未被定义,可见在底层实现上,let声明的变量实际上是提升了,拓展如下

  • 扩展如下

    • 暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

    • (1)底层实现上,let声明的变量实际上也会有提升,但是提升后会将其放到“暂时性死区”,如果访问的变量位于暂时性死区,则报错如图2-2-3,当代码运行到该变量的声明语句时,会将其从暂时性死区中移出

    • (2)在循环中,用let声明的循环变量会被特殊处理,每次进入循环体都会开启一个新的作用域,并且将循环变量绑定到该作用域,则每次循环使用的是一个全新的循环变量

    • (3)在循环中,使用let声明的循环变量在循环结束后会销毁

  • 解决闭包问题

    let body = document.getElementsByTagName('body')[0];
    for (let i = 1; i <= 10; i++) {
        let btn = document.createElement('button');
        btn.innerHTML = "按钮" + i;
        body.appendChild(btn);
        btn.onclick = function () {
            console.log(i);
        }
    }

三、使用const声明变量

  • const和let基本相同,区别在于用const声明的变量,必须在声明时赋值,而且不可以重新赋值

  • 【例】在声明时未赋值,报错

    const a;
    a = 1;
    console.log(a);
    //报错,该报错信息为:在变量声明时没有初始化

  • 【例】修改const声明的变量,报错

    const a = 1;
    a = 2;
    console.log(a);
    //报错

  • 实际上,在开发中应该尽量使用const来声明变量,以保证变量的值不会随意篡改,原因如下:

    • 根据经验,开发中的很多变量,都是不会更改的,也不应该更改

    • 后续的很多框架或者第三方JS库,都要求数据不可变,使用常量可以一定程度上保证这一点

【注】

  • (1)常量不可变,是指声明的常量的内存空间不可变,并不保证内存空间中的地址指向的其他空间不可变【例】

    const a = {
        name: 'jwh',
        age: 18
    };
    a.name = 'zdw'
    console.log(a);
    //结果:{name:"zdw",age:18}

  • (2)常量的命名

    • 特殊的常量:该常量从字面意义上,一定是不可变的,比如圆周率、月地距离或者其他一些绝不可能变化的配置。通常,这些常量的名称全部使用大写,多个单词之间用下划线分割

    • 普通的常量:命名规则与之前相同

  • (3)在for循环中,循环变量不可以使用常量【例】

    var arr = [{name:'jwh'},{age: 18}]
    for (const i = 0; i < arr.length; i++) {
        console.log(arr[i]);
    }
    //结果,会报错
     
      
    • 例】for  in循环可以用const声明变量

    var obj = {
        name: 'jwh',
        age: 18
    }
    for(const prop in obj) {
        console.log(obj[prop]);
    }
    //结果,jwh
    //18

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值