問題一:浏覽器列印下面代碼回輸出什麼
var a = 10;
function foo() {
console.log(a); // ??
var a = 20;
}
foo();
答案: undefined
解析:使用var關鍵字聲明的變量在JavaScript中會被提升,并在記憶體中配置設定值undefined。 但初始化恰發生在你給變量指派的地方。 另外,var聲明的變量是函數作用域的,而let和const是塊作用域的。 是以,這就是這個過程的樣子
var a = 10; // 全局使用域
function foo() {
// var a 的聲明将被提升到到函數的頂部。
// 比如:var a
console.log(a); // 列印 undefined
// 實際初始化值20隻發生在這裡
var a = 20; // local scope
}
問題二:我們使用const和let代替var輸出是否相同
var a = 10;
function foo() {
console.log(a); // ??
let a = 20;
}
foo();
答案:ReferenceError:a undefined
解析:let和const聲明可以讓變量在其作用域上受限于它所使用的塊、語句或表達式。與var不同的是,這些變量沒有被提升,并且有一個所謂的暫時死區(TDZ)。試圖通路TDZ中的這些變量将引發ReferenceError,因為隻有在執行到達聲明時才能通路它們。
var a = 10; // 全局使用域
function foo() { // TDZ 開始
// 建立了未初始化的'a'
console.log(a); // ReferenceError
// TDZ結束,'a'僅在此處初始化,值為20
let a = 20;
}
問題三:"newArray"中有哪些元素
var array = [];
for(var i = 0; i <3; i++) {
array.push(() => i);
}
var newArray = array.map(el => el());
console.log(newArray); // ??
答案:[3,3,3]
解析:在for循環的頭部聲明帶有var關鍵字的變量會為該變量建立單個綁定(存儲空間)。 閱讀更多關于閉包的資訊。 讓我們再看一次for循環。
// 誤解作用域:認為存在塊級作用域
var array = [];
for (var i = 0; i < 3; i++) {
// 三個箭頭函數體中的每個`'i'`都指向相同的綁定,
// 這就是為什麼它們在循環結束時傳回相同的值'3'。
array.push(() => i);
}
var newArray = array.map(el => el());
console.log(newArray); // [3, 3, 3]
如果使用 let 聲明一個具有塊級作用域的變量,則為每個循環疊代建立一個新的綁定
// 使用ES6塊級作用域
var array = [];
for (let i = 0; i < 3; i++) {
// 這一次,每個'i'指的是一個新的的綁定,并保留目前的值。
// 是以,每個箭頭函數傳回一個不同的值。
array.push(() => i);
}
var newArray = array.map(el => el());
console.log(newArray); // [0, 1, 2]
解決這個問題的另一種方法是使用閉包。
let array = [];[/font]
[font=微軟雅黑]for (var i = 0; i < 3; i++) {
array[i] = (function(x) {
return function() {
return x;
};
})(i);
}
const newArray = array.map(el => el());
console.log(newArray); // [0, 1, 2]