【ES6】一、 let 和 const命令

let 和 const命令

1. let命令

1.1 let 简单介绍——声明变量

let 用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效

//在控制台可输入验证
 for (let i = 0; i < 3; i++) {//父作用域  
       let i = 'abc';//子作用域
       console.log(i);//只针对子作用域
}
//输出为:abc abc abc

说明:每一轮循环的变量 i 都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
另外, for 循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

1.2 变量提升——未声明前使用

var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。按照一般的逻辑,变量应该在声明语句之后才可以使用。let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。

console.log(a);
var a=1
//输出为:VM1816:1 Uncaught SyntaxError: Identifier 'a' has already been declared    at <anonymous>:1:1
console.log(b);
let b=2
//输出为:VM1820:1 Uncaught ReferenceError: b is not defined      at <anonymous>:1:13

1.3 暂时性死区——变量提升的影响

变量的使用一定要在声明时候使用,否则就会引发‘暂时性死区’, 其影响let、const、import、class、typeof等关键字的可用性,不容忽视;与上述关键字相反、var、function等关键字却不会受到TDZ(暂时性死区)的影响,如果在变量常见之前访问,返回结果为undefined
typeof x; // ReferenceErrorlet x; 在没有let之前,typeof运算符是百分之百安全的,永远不会报错。现在这一点不成立了。这样的设计是为了让大家养成良好的编程习惯,变量一定要在声明之后使用,否则就报错。
暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

1.4 不允许重复声明

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

function func1(){
var a = 1;
let a = 4;
console.log(a)
}
func()
//输出为:Uncaught SyntaxError: Identifier 'a' has already been declared

function func2(3){
{
let c;         //替换let c=5;
console.log(c)
}
}
func2()
//输出为:undefined
//将let c; 替换为 let c=5; 则输出为:5

2. 块级作用域——暂时性死区

2.1 为什么需要块级作用域

(1)防止内层的变量覆盖外层的变量值
(2)防止全局变量发生泄漏
ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。

function f3() {
  var n = 5;
  if (true) {
    var n = 10;
  }
  console.log(n); 
}f3();// 5

function f1() {
  let n = 5;
  if (true) {
    let n = 10;
  }
  console.log(n);
}f1(); // 5

2.2 ES6 有自己的行为方式

  1. 允许在块级作用域内声明函数。
  2. 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
  3. 函数声明还会提升到所在的块级作用域的头部。
    注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。
    ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。 而let只能出现在当前作用域的顶层, 函数只能声明在当前作用域的顶层。
// 不报错'use strict';
if (true) { //有大括号,存在块级作用域
function f() {}
}

// 报错'use strict';
if (true) //无大括号,不存在块级作用域
     function f() {}

2.3 暂时性死区

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

3. const命令

3.1 const 简单介绍——声明变量

const声明一个只读的常量。一旦声明,常量的值就不能改变。对于const来说,只声明不赋值,就会报错。
const的作用域与let命令相同:只在声明所在的块级作用域内有效。

3.2 const 常量不变的本质

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
将对象冻结,应该使用Object.freeze方法。重新赋值将报错。
除了将对象本身冻结,对象的属性也应该冻结。下面是一个将对象彻底冻结的函数。

 var constantize = (obj) => { 
 Object.freeze(obj);   //冻结对象
 Object.keys(obj).forEach( (key, i) => {  //用forEach()进行遍历  
 if ( typeof obj[key] === 'object' ) { //用typeof确定obj是否是一个对象  
 constantize( obj[key] ); 
 } 
 }); 
 };

3.3 ES6声明变量的方式

ES6有六种声明变量的方法: var命令和function命令, let和const命令,import命令和class命令

3.4 ES6的顶层对象

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

ES6 规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。

var a = 1;
// 如果在 Node 的 REPL 环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1

let b = 1;
window.b // undefined    let声明的不是window的对象属性

ES2020 在语言标准的层面,引入globalThis作为顶层对象。也就是说,任何环境下,globalThis都是存在的,都可以从它拿到顶层对象,指向全局环境下的this。

4. var、let、const命令的区别

4.1 var

在ES5中,顶层对象的属性和全局变量是等价的,用var声明的变量既是全局变量,也是顶层变量
注意:顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象
使用var声明的变量存在变量提升的情况,使用var,我们能够对一个变量进行多次声明,后面声明的变量会覆盖前面的变量声明,在函数中使用使用var声明变量时候,该变量是局部的,而如果在函数内不使用var,该变量是全局的

4.2 let

let是ES6新增的命令,用来声明变量,用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效,不存在变量提升,只要块级作用域内存在let命令,这个区域就不再受外部影响,使用let声明变量前,该变量都不可用,也就是大家常说的“暂时性死区”
最后,let不允许在相同作用域中重复声明,因此,我们不能在函数内部重新声明参数

4.3 const

const声明一个只读的常量,一旦声明,常量的值就不能改变,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值,如果之前用var或let声明过变量,再用const声明同样会报错
const实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动
对于简单类型的数据,值就保存在变量指向的那个内存地址,因此等同于常量
对于复杂类型的数据,变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的,并不能确保改变量的结构不变
其它情况,const与let一致

4.4 区别

var、let、const三者区别可以围绕下面五点展开:

  • 变量提升
  • 暂时性死区
  • 块级作用域
  • 重复声明
  • 修改声明的变量
  • 使用
    变量提升
    var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined
    let和const不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错
    暂时性死区
    var不存在暂时性死区
    let和const存在暂时性死区,只有等到声明变量的那一行代码出现,才可以获取和使用该变量
    块级作用域
    var不存在块级作用域
    let和const存在块级作用域
    重复声明
    var允许重复声明变量
    let和const在同一作用域不允许重复声明变量
    修改声明的变量
    var和let可以修改声明的变量
    const声明一个只读的常量。一旦声明,常量的值就不能改变
    使用
    能用const的情况尽量使用const,其他情况下大多数使用let,避免使用var

参考资料

【1】https://wangdoc.com/es6/let.html
【2】https://es6.ruanyifeng.com/
【3】https://vue3js.cn/interview/es6/var_let_const.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值