【前端】(二)ES6新特性之 let、const

let(声明局部变量)

let特点是什么?

作用域为 块级作用域、无变量提升、同一作用域内不可以重复声明

和var的区别?

var 作用域为 函数作用域、有变量提升、可以重复声明、有暂时性死区

关于作用域

作用域:JS(ES6之前)作用域有 全局作用域 、函数作用域(局部作用域)。
ES6新增块级作用域。

  1. 全局作用域:
    最外层函数和在最外层函数外面定义的变量拥有全局作用域。
    所有末定义直接赋值的变量自动声明为拥有全局作用域(不论函数内外)。

    在全局作用域中创建的变量和函数都被作为window对象的属性。
    全局作用域在页面打开时创建,页面关闭时销毁。
    全局变量在全局(代码的任何位置)下都可以使用;全局作用域中无法访问到局部作用域中的变量。
    在这里插入图片描述
    在这里插入图片描述

  2. 函数作用域(局部作用域):函数内部为局部作用域。
    调用函数时创建函数作用域,函数执行完毕之后,函数作用域销毁;
    每调用一次函数就会创建一个新的函数作用域,它们之间是相互独立的。

 var num = 10; // 全局作用域内
    function nu(){
        var num = 20; //函数作用域内
        console.log(num); //20
    }
    nu();
    console.log(num); //10
  1. 块级作用域:{} 的内部即为块级作用域,if语句和for语句里面的{}也属于块作用域。
    function nu() {
    {
      var a = 10;
      let b = 20;
      console.log(a); //10
      console.log(b); //20
    }
    console.log(a) //10,var并不能将变量的适用范围限制在块级作用域内
    console.log(b) // b is not defined,let可以将变量范围限制在块级作用域内
  }
  nu();
  console.log(a); // not defined
  console.log(b) // not defined

如果没有块级作用域,可能会:
(1)变量提升导致内层变量可能会覆盖外层变量

var i = 5;  
function func() {  
    console.log(i);  
    if (true) {  
        var i = 6;  
    }  
}  
func(); // undefined 

详细解释(2021-3-4):
疑问:是先执行console.log还是先变量提升,如果先执行console.log那么执行到true的时候,再变量提升将var i提升到console之前但此时console已经执行完毕了啊;如果先变量提升那么不是先执行true再console吗,这不符合js的从上往下执行。
解释:因为没有块级作用域,所以var i =6和console其实是在一个作用域里面的,所以理所应当地直接变量提升,var i;提升到console之前。

(2) 用来计数的循环变量泄露为全局变量

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

详细解释(2021-3-4)
由于var有变量提升机制,所以var会只声明一次,然后在每次地作用域中改变i 的值;
而let没有变量提升机制,所以每次循环都会执行一次,声明一个新变量(但初始化的值不一样),又因为let声明的变量是在各自的块级作用域中,所以不存在重复声明的情况,即
{let i = 0}
{let i = 1}

为什么会是三个3?

{
  //我是父作用域
  var i = 0;
  if (0 < 3) {
    a[0] = function () {
      //我是子作用域
      console.log(i);
    };
  };
  i++; //为1
  if (1 < 3) {
    a[1] = function () {
      console.log(i);
    };
  };
  i++; //为2
  if (2 < 3) {
    a[2] = function () {
      console.log(i);
    };
  };
  i++; //为3
  // 跳出循环
}
//调用N次指向都是最终的3
a[0](); //3
a[1](); //3
a[2](); //3
  • 为什么let不会?
    因为let在每一次循环中都在其作用域中新声明了一个。
  • 为什么会记得上一个i是多少并在此基础上自增?
    从阮一峰ES6入门获取到知识:JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

借鉴:for循环中let与var的区别,块级作用域如何产生与迭代中变量i如何记忆上一步的猜想

块级作用域的一般使用:
(1)for 循环和 let 配合使用

for (let i = 0; i < 10; i++) {    
        console.log(i);    
}    
console.log(i);  // i is not defined

const(声明一个只读的常量)

一旦声明,常量的值就不能改变,并且需要立即初始化。

function func(){
    const PI;//未立即赋值导致报错,Missing initializer in const declaration
    PI = 3.14;
    console.log(PI);
};
func();

常见面试题

  1. var、let、const的区别
    let、const 有块级作用域,var没有块级作用域
    let、const 没有变量提升,var有变量提升
    let、const 不可以重复声明,var可以
    let、var可以先声明再赋值,const声明同时必须赋值
    let、var声明赋值后变量值还可以修改,const声明的是常量,不可以修改

推荐文章: JS 全局作用域和局部作用域.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值