let和 const 命令

letconst 命令

let 命令

  • let 声明的变量只在块级作用域内有效
  • 不存在变量提升
  • 不能重复声明
  • 存在暂时性死区

变量提升

// var 会有变量提升
        console.log(a);//undefined,说明变量a提升了为:var a;
        var a = 10;
        console.log(a);//10

        // console.log(a1);//报错
        let a1 = 10;
        console.log(a1);//10

暂时性死区

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

        // 暂时性死区
        var a = 100;
        function fn() {
            // console.log(a);//报错,变量a的“死区”。
            let a = 10;
            console.log(a);//10
        }
        fn();
        console.log(a);//100

不能重复声明

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

        // let 不能重复声明同一个变量,var可以
        {
            var a = 10;
            var a = 20;
            console.log(a);//不报错,20

            let b = 10;
            let b = 20;
            console.log(b);//报错
        }
        function fn() {
            let a = 10;
            var a = 1;
            console.log(a);
        }
        fn();//错误

因此,不能在函数内部重新声明参数。

				function func(arg) {
            let arg;// 报错
        }
        func(); // 报错

        function func(arg) {
            {
                let arg = 'yami';
                console.log(arg);
            }
        }
        func();// yami

只在块级作用域内有效

        // let声明的变量是块级作用域,不存在变量提升
        {

            let b = 10;
            console.log(b);//10
        }
        console.log(b);//报错,不在块级作用域内

为什么需要块级作用域?

  • 第一种场景,内层变量可能会覆盖外层变量。

    				var b = "我是外部b";
            function fn1() {
              //这个地方undefined存在变量提升,导致内层b变量覆盖了外层的b变量
                console.log(b);//undefined
                {
                    var b = "我是内部b";
                    console.log(b);
                }
            }
            fn1();//undefined 我是内部b(内层变量覆盖外层变量)
    

    解決:

     				let a = "我是外部a";
            function fn() {
                console.log(a);
                {
                    let a = "我是内部a";
                    console.log(a);
                }
            }
            fn();//我是外部a  我是内部a (沒有覆蓋)
    
  • 第二种场景,用来计数的循环变量泄露为全局变量。

    var array = [1, 2, 3];
    for (var j = 0; j < array.length; j++) {
        console.log(array[j]);
    }
    console.log('j=' + j);//3
    

    上面代码中,变量j只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。

    然而使用let则不会有这种现象,会报错:

    var array = [1, 2, 3];
    for (let i = 0; i < array.length; i++) {
        console.log(array[i]);
    }
    console.log(i);//报错
    

块级作用域与函数声明

function f() {
    console.log('I am outside!');
}
(function () {
    if (false) {
        // 重复声明一次函数f
        function f() { console.log('I am inside!'); }
    }
    f();// f is not a function
}());

理论上会得到“I am outside!”。因为块级作用域内声明的函数类似于let,对作用域之外没有影响。但是,如果你真的在 ES6 浏览器中运行一下上面的代码,是会报错的,这是为什么呢?

浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于var声明的变量,导致变量提升。上面的例子实际运行的代码如下。

function f() {
    console.log('I am outside!');
}
(function () {
  var f = undefined;
    if (false) {
        // 重复声明一次函数f
        function f() { console.log('I am inside!'); }
    }
    f();// f is not a function
}());
  • 应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。
  • ES6 的块级作用域必须有大括号{},如果没有大括号,JavaScript 引擎就认为不存在块级作用域。
  • 函数声明也是如此,严格模式下,函数只能声明在当前作用域的顶层。
//建议写成函数表达式:let f=function(){ }
 {
            let a = 1;
            let f = function () {
                console.log(a);
            }
            f();
        }
//块级作用域必须有大括号{}
if (true) {
            let b=2; 
        }
'use strict';
        if (true) {
            function f() {
                console.log('严格模式下也要加{}')
            }
            f();
        }

const命令

基本用法

实际开发的项目中,大部分情况下建议使用const声明。

问自己,这个变量是否需要修改。如果需要修改 直接改成let

letconst的使用建议:

在默认情况下用const,而只有你在知道变量值需要被修改的情况下使用let

  • const声明一个只读常量。一旦声明,常量的值就不能改变。
  • const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
  • const的作用域与let命令相同:只在声明所在的块级作用域内有效。
  • const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用
  • const声明的常量,也与let一样不可重复声明。

本质

常量对象可以更改

可以更改常量对象的属性:( 但是无法重新为常量对象赋值)

// 可以创建 const 对象:
const car = {type:"porsche", model:"911", color:"Black"};

// 可以更改属性:
car.color = "White";

// 可以添加属性:
car.owner = "Bill";
常量数组可以更改

您可以更改常量数组的元素:

// 可以创建常量数组:
const cars = ["Audi", "BMW", "porsche"];

// 可以更改元素:
cars[0] = "Honda";

// 可以添加元素:
cars.push("Volvo");

但是您无法重新为常量数组赋值:

const cars = ["Audi", "BMW", "porsche"];
cars = ["Honda", "Toyota", "Volvo"];    // ERROR

如果真的想将对象冻结,应该使用Object.freeze方法。

const foo = Object.freeze({});

// 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
foo.prop = 123;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值