溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JavaScript中關(guān)于閉包的面試題有哪些

發(fā)布時間:2021-03-26 10:16:08 來源:億速云 閱讀:172 作者:小新 欄目:web開發(fā)

小編給大家分享一下JavaScript中關(guān)于閉包的面試題有哪些,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!


每個 JavaScript 程序員都必須知道閉包是什么。在 JavaScript 面試中,你很可能會被問到閉包的概念。

以下是 7 個有關(guān) JavaScript 閉包的面試題,比較有挑戰(zhàn)性。

不要查看答案或運行代碼,看看自己的水平到底如何。做完這些題大約需要半小時左右。

1. 范圍

有以下函數(shù) clickHandler,immediatedelayedReload

let countClicks = 0;
button.addEventListener('click', function clickHandler() {
  countClicks++;
});
const result = (function immediate(number) {
  const message = `number is: ${number}`;
  return message;
})(100);
setTimeout(function delayedReload() {
  location.reload();
}, 1000);

這3個函數(shù)中哪個能夠訪問外部范圍變量?

答案
  • clickHandler 能夠從外部作用域訪問變量 countClicks。

  • immediate 無法訪問外部作用域中的任何變量。

  • delayedReload 從全局作用域(也就是最外層作用域)中訪問全局變量 location。

相關(guān)教程推薦:javascript視頻教程

2.  丟失的參數(shù)

下列代碼輸出什么:

(function immediateA(a) {
  return (function immediateB(b) {
    console.log(a); // => ?
  })(1);
})(0);
答案

輸出為:0

用參數(shù) 0 調(diào)用 immediateA,因此 a 參數(shù)為 0。

immediateB 函數(shù)嵌套在 immediateA 函數(shù)中,是一個閉包,它從外部 immediateA 作用域中得到 a 變量,其中 a0。因此 console.log(a) 的輸出為 0。

3. 誰是誰

下面的代碼將會輸出什么內(nèi)容?

let count = 0;
(function immediate() {
  if (count === 0) {
    let count = 1;
    console.log(count); // 輸出什么?
  }
  console.log(count); // 輸出什么?
})();
答案

輸出 10

第一個語句  let count = 0 聲明了一個變量 count。

immediate() 是一個閉包,它從外部作用域得到 count 變量。在 immediate()  函數(shù)作用域內(nèi), count0。

但是,在條件內(nèi),另一個 let count = 1 聲明了局部變量 count,該變量覆蓋了作用域之外的 count。第一個 console.log(count) 輸出 1。

第二個 console.log(count) 輸出為 0 ,因為這里的 count 變量是從外部作用域訪問的。

4. 棘手的閉包

下列代碼輸出什么:

for (var i = 0; i < 3; i++) {
  setTimeout(function log() {
    console.log(i); // => ?
  }, 1000);
}
答案

輸出:3, 3, 3。

代碼分為兩個階段執(zhí)行。

階段1

  1. for() 重復(fù) 3 次。在每次循環(huán)都會創(chuàng)建一個新函數(shù) log(),該函數(shù)將捕獲變量 i。 setTimout() 安排log() 在 1000 毫秒后執(zhí)行。

  2. 當(dāng) for() 循環(huán)完成時,變量 i 的值為 3。

階段2

第二階段發(fā)生在 1000ms 之后:

  1. setTimeout() 執(zhí)行預(yù)定的 log() 函數(shù)。 log() 讀取變量 i 當(dāng)前的值 3,并輸出 3

所以輸出 3, 3, 3。

5. 錯誤的信息

下面的代碼將會輸出什么:

function createIncrement() {
  let count = 0;
  function increment() { 
    count++;
  }

  let message = `Count is ${count}`;
  function log() {
    console.log(message);
  }
  
  return [increment, log];
}

const [increment, log] = createIncrement();
increment(); 
increment(); 
increment(); 
log(); // => ?
答案

輸出:'Count is 0'

increment() 函數(shù)被調(diào)用 3 次,將 count 增加到 3。

message 變量存在于 createIncrement() 函數(shù)的作用域內(nèi)。其初始值為 'Count is 0'。但即使 count 變量已經(jīng)增加了幾次,message 變量的值也始終為 'Count is 0'。

log() 函數(shù)是一個閉包,它從 createIncrement() 作用域中獲取 message 變量。 console.log(message) 輸出錄'Count is 0'到控制臺。

6. 重新封裝

下面的函數(shù) createStack() 用于創(chuàng)建棧結(jié)構(gòu):

function createStack() {
  return {
    items: [],
    push(item) {
      this.items.push(item);
    },
    pop() {
      return this.items.pop();
    }
  };
}

const stack = createStack();
stack.push(10);
stack.push(5);
stack.pop(); // => 5

stack.items; // => [10]
stack.items = [10, 100, 1000]; // 棧結(jié)構(gòu)的封裝被破壞了

它能正常工作,但有一個小問題,因為暴露了 stack.items 屬性,所以任何人都可以直接修改 items 數(shù)組。

這是一個大問題,因為它破壞了棧的封裝:應(yīng)該只有 push()pop() 方法是公開的,而 stack.items 或其他任何細(xì)節(jié)都不能被訪問。

使用閉包的概念重構(gòu)上面的棧實現(xiàn),這樣就無法在 createStack() 函數(shù)作用域之外訪問 items 數(shù)組:

function createStack() {
  // 把你的代碼寫在這里
}

const stack = createStack();
stack.push(10);
stack.push(5);
stack.pop(); // => 5

stack.items; // => undefined
答案

以下是對 createStack() 的重構(gòu):

function createStack() {
  const items = [];
  return {
    push(item) {
      items.push(item);
    },
    pop() {
      return items.pop();
    }
  };
}

const stack = createStack();
stack.push(10);
stack.push(5);
stack.pop(); // => 5

stack.items; // => undefined

items 已被移至 createStack() 作用域內(nèi)。

這樣修改后,從 createStack() 作用域的外部無法訪問或修改 items 數(shù)組。現(xiàn)在 items 是一個私有變量,并且棧被封裝:只有 push()pop() 方法是公共的。

push()pop() 方法是閉包,它們從 createStack() 函數(shù)作用域中得到 items 變量。

7. 智能乘法

編寫一個函數(shù)  multiply() ,將兩個數(shù)字相乘:

function multiply(num1, num2) {
  // 把你的代碼寫在這里...
}

要求:

如果用 2 個參數(shù)調(diào)用 multiply(num1,numb2),則應(yīng)返回這 2 個參數(shù)的乘積。

但是如果用 1個參數(shù)調(diào)用,則該函數(shù)應(yīng)返回另一個函數(shù): const anotherFunc = multiply(num1) 。返回的函數(shù)在調(diào)用 anotherFunc(num2)  時執(zhí)行乘法  num1 * num2。

multiply(4, 5); // => 20
multiply(3, 3); // => 9

const double = multiply(2);
double(5);  // => 10
double(11); // => 22
答案

以下是  multiply()  函數(shù)的一種實現(xiàn)方式:

function multiply(number1, number2) {
  if (number2 !== undefined) {
    return number1 * number2;
  }
  return function doMultiply(number2) {
    return number1 * number2;
  };
}

multiply(4, 5); // => 20
multiply(3, 3); // => 9

const double = multiply(2);
double(5);  // => 10
double(11); // => 22

如果 number2 參數(shù)不是 undefined,則該函數(shù)僅返回 number1 * number2。

但是,如果 number2undefined,則意味著已經(jīng)使用一個參數(shù)調(diào)用了 multiply() 函數(shù)。這時就要返回一個函數(shù) doMultiply(),該函數(shù)稍后被調(diào)用時將執(zhí)行實際的乘法運算。

doMultiply() 是閉包,因為它從 multiply() 作用域中得到了number1 變量。

以上是“JavaScript中關(guān)于閉包的面試題有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI