天天看點

前端面試JS問題

問題一:浏覽器列印下面代碼回輸出什麼

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]