let 和 const

148 阅读3分钟

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

前言

ECMAScript 6.0 简称ES6 , 是 JavaScript 语言的新一代的标准,于在 2015 年 6 月发布,正式名称就是《ECMAScript 2015 标准》。

一般情况,ES6 一个泛指, 5.1版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017、ES2018、ES2019、ES2020、ES2021 等等

let 申明

在ES6之前,申明变量有两种方式,一种是var, 一种是非严格模式,直接赋值。

var a = 10;

function log(){
    b = 20;
}

log()
console.log(a) // 10
console.log(b) // 20

let与var非常相似,但是在let命令所在的代码块内有效, 并且不能重复申明。

同一作用域不能重复申明

同一作用域,下面的例子var申明可以重复,let却不可以。

var a = 1;
var a = 1;

var b = 1;
let b = 1;
// Uncaught SyntaxError: Identifier 'a' has already been declared

代码块内有效

ES6新增了代码块,let与const的申明仅仅在代码块中有效。

{
    var a = 1;
    let b = 1;
}
console.log(a);
console.log(b); 
// Uncaught ReferenceError: b is not defined

不存在变量提升

变量提升 : 变量可以在声明之前使用,值为undefined。 之前的var存在变量提升,而let不存在此现象。

console.log(a);  // undefined
console.log(b); // VM39:2 Uncaught ReferenceError: b is not defined
var a = 1
let b = 1

image.png

暂时性死区

块级作用域内let申明,不再受外部的影响。会导在块级作用域内申明之前不可以被访问, 这就是暂时性死区。

先来一个简单的例子。

var a = 10;
function log(){
    console.log(a);
    let a = {};
}
log();

image.png

再来一个嵌套级别多一点的例子:

function log(msg){  
   var prefix = "log:";
   function innerLog(){
    console.log(prefix + msg);
    let prefix = "innerLog";
   }

   innerLog();
}

image.png

一个经典闭包的例子

<div id="buttons">
  <button class="button">按钮1</button>
  <button class="button">按钮2</button>
  <button class="button">按钮3</button>
  <button class="button">按钮4</button>
  <button class="button">按钮5</button>
</div>

<script>
  var buttonsEl = document.getElementById("buttons");
  for (var i = 0; i < buttonsEl.children.length; i++) {
    buttonsEl.children[i].onclick = function () {
      console.log(i);
    };
  }
</script>

五个按钮,按个加上点击事件,点击时输出i的值,你会发现,无论是点击那个按钮,输出都会是 5。

这是闭包作怪,最经典的解决方案,就是

  1. IIFE
  2. let

let为什么能解决这个问题,大家可能还会存在疑问,这不是还能访问到吗? 这里啊,其实 for语句和循环体{}是两个不同的作用域。

我们可以看到{}申明let i,被没有报错。

for (let i = 0; i <= 2; i++) {
  let i = 1000;
  console.log(i);
}
// 1000
// 1000

更多关于 for let循环可以单独出一片文章讲解。

const 申明

const 申明可以认为是let的进一步的增强,一旦声明,常量的值就不能改变。

const NUM = 10;
NUM = 20;

image.png

如果其值是一个对象,值不能被直接替换,但是其属性依旧是可以更改的。

const person = {
    name: "tome",
    age: 10
}

person.name = "Jim"
person = {
    name: "tom",
    age: 10
}
// Uncaught TypeError: Assignment to constant variable.

所以const的本质: 并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动

  1. 基础类型变量的值
    数据的地址
  2. 引用类型变量的值
    一个指向实际数据的指针

小结

今天你收获了吗?