1、let的介绍
首先,初识let
是在MDN上面,介绍了let
的基本用法,根据它的介绍,我知道了以下几点:
let
声明的变量作用域是块级的let
变量不能重复声明let
存在暂时性死区(变量未初始化之前,不能使用)
一开始我是这么理解的,我相信也是大多数人理解的那样。
2、经典面试题
let liList = document.querySelectorAll('li') // 6个li for(var i=0; i<liList.length; i++){ liList[i].onclick = function(){ console.log(i) } }
上面这段代码会输出什么呢?答案是6个6,我想这一点大家应该知道,因为var
关键字会使变量提升,所以其实只有一个全局i
,当你去执行click
事件的时候,这时候i
已经变成6了。
那么把var
改成let
之后呢,
let liList = document.querySelectorAll('li') //6个li for(let i=0; i<liList.length; i++){ liList[i].onclick = function(){ console.log(i) } }
这段代码执行效果,依次点击会输出0,1,2,3,4,5
。
其实这里有两个点:1、每次进入循环体,都会在循环体中重新声明一个i
并初始化一次,2、for后面的括号里有一个作用域,
所以其实一共存在7个i
,六次循环,然后一个for
后面的作用域。
相当于这样子:
let liList = document.querySelectorAll('li') //6个li for(let i=0; i<liList.length; i++){ let i = i(这里的i是for后面括号中的) liList[i].onclick = function(){ console.log(i) } }
所以当let
和for
一起用的时候,如果搞不清i
是哪里的,那么自己声明一个重新初始化。
3、let和var、function的比较
众所周知,var
和 function
都是存在提升的,也就是说下面的代码不会报错:
console.log(i) // undefined var i = 2
fn() function fn() { console.log('hello') }
那么假如把var
变成let
呢?会报错,
console.log(i) // Uncaught ReferenceError: i is not defined let i = 2
现在就来看下它们三者的区别,
首先JS
变量的三个过程【创建、初始化、赋值】
3.1、var声明的过程
function fn() { var x = 1 } fn()
- 当进入
fn
后,会为fn
创建一个环境 - 找到所有用
var
声明的变量,然后创建它们 - 将它们初始化为
undefined
- 执行代码
x = 1
将x
变量赋值为1
也就是说,var
声明会在代码执行前就创建变量,并初始化为undefined。
3.2、let声明的过程
function fn() { let x = 1 x = 2 } fn()
- 当进入
fn
后,会为fn
创建一个环境 - 找到所有用
let
声明的变量,然后创建它们 - 执行代码(未初始化)
- 执行
x = 1
,将x
初始化为1 - 执行
x = 2
,将x
赋值为2
也就是说,let
声明会在代码执行前就创建变量,但不会初始化,所以初始化之前不能使用,存在暂时死区。
3.3、function声明的过程
fn() function fn() { console.log('hello') }
- 找到所有用
function
声明的变量,然后创建它们 - 将变量初始化并赋值为
function { console.log('hello') }
- 开始执行
fn
也就是说,function
声明会在代码执行前就创建,初始化并赋值。
3.4、总结
var
的创建和初始化都被提升了;let
的创建过程被提升了,但是初始化没有提升;function
的创建、初始化和赋值都被提升了;- 顺便说一下
const
,创建和初始化过程和let
一样,只是没有赋值过程。
4、总结
以上就是我对let
的理解。