理解var、let和const 以及用法

912 阅读3分钟

「这是我参与2022首次更文挑战的第4天,活动详情查看:2022首次更文挑战

1、let变量的使用

let变量和var的使用区别:

  1. let和var都用于声明变量,但是let所声明得变量只在代码块内有效;
{
    let a = 10;
    var b = 10;
}
console.log(a);//报错:a is not defined
console.log(b);//1

2.不存在变量提升——在声明之前可以使用,值为undefined

let 声明变量,必须先声明后使用,否则便会报错;
​
//var 的情况
console.log(foo);//输出undefinedif
var foo =2;
​
//let 的情况
console.log(bar); //报错
let bar = 2;

3.暂时性死区TDZ(temporal dead zero)——在进入作用域之前,所要使用的变量就已经存在,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

iftrue){
    //TDZ 开始
    tmp='abc';  // 报错
    console.log(tmp);  //报错
    
   let tmp ; //TDZ结束
   console.log(tmp);  //undefined
   
   temp = 123; 
   conlose.log(tmp);  //123
 }
 
 在let 命令声明 tmp 之前,都属于变量tmp的‘死区’。

4.不允许重复声明

let不允许在相同作用域内重复声明同一个变量。
​
//报错
function (){
    let a = 10;
    var b =10;
}
​
因此,不能在函数内部重新声明参数。
function axx(arg){
    let arg;//报错
}
​
function BXX(arg){
    {
        let arg;//不报错
    }
}

补充;let的使用语法,最常见使用在for循环里。

块级作用域

1.使用的原因:

  • 内层变量可能会覆盖外层变量
  • var a=new Date();
    function f(){
        console.log(a);
        if(false){
            var a='hello'
        }
    }
    ​
    f();//undefined
    说明:内层变量var a='hello'在声明之前打印,变量提升导致修改了外层的变量的值。
    
  • 用来计数的循环变量泄露为全局变量
  • var a='hello'
    for(var i=0;i<a.length;i++){
        console.log(s[i]);
    }
    ​
    console.log(i);  //5
    ​
    i用来控制变量的循环,但是循环结束后他没有消失,而是泄露成了全局变量。
    ​
    

2.ES6的块级作用域:

外层的作用域无法读取内层的作用域的变量,且内层作用域可以定义外层作用域的同名变量。

说明:块级作用域的出现,使立即执行的匿名函数不在必要了。

//ITFE匿名函数写法function (){
           }());
​
//块级作用域
{
    let tmp - ....;
}

3.块级作用域与函数声明

ES5规定:函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域中声明。

而ES6中规定:

  • 允许在块级作用域内声明函数。
  • 函数声明类似于var,可以提升到全局作用域或者函数作用域的头部。
  • 函数声明还会提升到所在的块级作用域的头部。

2、const命令:

1.基本用法:

  • 声明一个常量,声明之后不能改变,即一旦声明之后就必须立即初始化。
  • 与let 作用域相识,只在生命所在的块级作用域有效。
  • 存在暂时性死区,必须在声明后使用。

2.本质

const并不是保证变量的值不会变化,而是变量指向的内存地址不变。

const foo = {};
//添加一个属性可以成功
foo.prop=123;
​
//foo指向另一个对象时,就会报错
foo = {}
​
说明:只是对象的地址不可变,对象本身的属性是可变化的。
foo.push('hello');   //正确
foo = { 'a' }    //错误

3.es6声明变量的6种方法:

es5:var 和 function命令,es6中添加了 let 和 const 命令;import 和 class 命令。

3、顶层对象属性:

顶层环境对象在浏览器中指的是window对象,在node环境中指的是global对象。

es6规定,var和function声明是(全局)顶层对象的属性,而let、const、等声明的不是顶层对象属性。

4、var 、const 和 let 在for-in/for-of 的区别

<script>
    function fooConst() {
        console.log("这是 const 循环 obj 和 arr")
        for (const key in {a: 1, b: 2}) {
            console.log(key);
        }
        // a, b
        for (const value of [1,2,3,4,5]) {
            console.log(value);
        }
        // 1, 2, 3, 4, 5
    }
    fooConst();

    function fooLet() {
        console.log("这是let 循环 obj 和 arr")
        for (let key in {a: 1, b: 2}) {
            console.log(key);
        }
        // a, b
        for (let value of [1,2,3,4,5]) {
            console.log(value);
        }
        // 1, 2, 3, 4, 5
    }
    fooLet();


    function fooVar() {
        console.log("这是var循环")
       for (var i = 0; i < 5; ++i) { 
           setTimeout(() => console.log(i), 0) 
       } 
       // 你可能以为会输出 0、1、2、3、4 
       // 实际上会输出 5、5、5、5、5
       // 数据迭代保存的是最后退出的数据的值,所以在执行输出逻辑的时候保存的都是一个值
        for (let i = 0;i<6;i++) {
            console.log("i:",i);
        }
        
        // 1 2 3 4 5
        for (const j = 0;j<6;j++) {
            // j 输出0之后就报错,因为j 为常量,不可以修改这个值
            console.log("j:",j);
        }
    }
    fooVar();
</script>