我們曉得再
ES5
中的
var
和
function
的申明都存在又變量提拔,
ES6
中的
let
、
const
則不存在有變量提拔。
var變量提拔
console.log(a);
var a =1;
// 等價於
var a ;
console.log(a); // undefined
a = 1;
js中的 function
也能夠看做是變量,也存在變量提拔
a(); // 1
function a() {
console.log(1);
}
總之
JavaScript引擎的工作方式是,先剖析代碼,獵取一切被聲明的變量,然後再一行一行地運轉。這形成的效果,就是一切的變量的聲明語句,都會被提拔到代碼的頭部,這就叫做變量提拔(hoisting)。
let深切明白
- let 聲明的變量的作用域是塊級的;
- let 不能反覆聲明已存在的變量;
- let 有臨時死區,不會被提拔。
// case1
var liList = document.querySelectorAll('li') // 共5個li
for( var i=0; i<liList.length; i++){
liList[i].onclick = function(){
console.log(i)
}
}
// case2
var liList = document.querySelectorAll('li') // 共5個li
for( let i=0; i<liList.length; i++){
liList[i].onclick = function(){
console.log(i)
}
}
順次點擊會湧現5個 5 。如果把var 改為了let 就是離別打印0 , 1 , 2, 3, 4 了。
我的明白是:
- for(let i = 0; i< 5; i++) 這句話的圓括號之間存在有一個隱蔽的作用域
- 再每次實行輪迴體的時刻都會在輪迴體高低文中從新初始化一次
var liList = document.querySelectorAll('li') // 共5個li
for( let i=0; i<liList.length; i++){
let i = 隱蔽作用域中的i // 看這裏看這裏看這裏
liList[i].onclick = function(){
console.log(i)
}
}
// 那樣的話,5 次輪迴,就會有 5 個差別的 i,console.log 出來的 i 固然也是差別的值。
下面我們再來細緻刨析一下詳細聲明的歷程
var變量聲明的建立、初始化和賦值歷程
function fn(){
var a = 0;
var b = 1;
}
fn();
歷程剖析:
- 進入fn,為其建立一個環境
- 找出fn中一切聲明的變量,在這個環境中建立這些變量(a,b)
- 將這些變量初始化為undefined
- 最先實行代碼
- a 賦值 0,b 賦值 1;
這就詮釋了為何在 var x = 1 之前 console.log(x) 會獲得 undefined。
function的聲明的建立、初始化、和賦值歷程
f2(); // 2
function f2() {
console.log(2);
}
歷程剖析:
- 找到function聲明的變量,在環境中建立
- 將這些變量初始化並賦值, function(){ console.log(2) }。
- 最先實行代碼 fn(); //2
let聲明的建立、初始化、賦值
{
let x = 1
x = 2
}
歷程剖析:
- 找到let變量在環境中建立,
- 最先實行代碼 ,注重還沒有舉行初始化哦
- 實行x = 1; x 初始化為 1
- 實行x = 2; x 舉行賦值
我們再來明白一下let 之前不能運用的緣由
{
console.log(a);
let a = 1;
}
緣由:
- console.log(a) 中的 a 指的是下面的 a,
- 實行 log 時 x 還沒「初始化」,所以不能運用(也就是臨時性死區)
總結
let
的「建立」歷程被提拔了,然則初始化沒有提拔。
var
的「建立」和「初始化」都被提拔了。
function
的「建立」「初始化」和「賦值」都被提拔了。
末了看 const
,實在 const 和 let 只要一個區分,那就是 const 只要「建立」和「初始化」,沒有「賦值」歷程。
所謂臨時死區
,就是不能在初始化之前,運用變量。