目錄
1. 範圍
答案
#2.  遺失的參數
3. 誰是誰
4. 棘手的閉包
7. 智能乘法
总结
首頁 web前端 js教程 7個JavaScript中關於閉包的面試題,你能回答上來嗎?

7個JavaScript中關於閉包的面試題,你能回答上來嗎?

Mar 26, 2021 am 09:41 AM
javascript 閉包 面試題

7個JavaScript中關於閉包的面試題,你能回答上來嗎?

相關推薦:2021年大前端面試題總結(收藏)

每個JavaScript 程式設計師都必須知道閉包是什麼。在 JavaScript 面試中,你很可能會被問到閉包的概念。

以下是 7 個有關 JavaScript 閉包的面試題,比較有挑戰性。

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

1. 範圍

有以下函數clickHandlerimmediatedelayedReload#:

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個函數中哪一個能夠存取外部範圍變數?

答案

  • clickHandler 能夠從外部作用域存取變數 countClicks

  • immediate 無法存取外部作用域中的任何變數。

  • delayedReload 從全域作用域(也就是最外層作用域)存取全域變數 location

相關教學建議:javascript影片教學

#2.  遺失的參數

下列程式碼輸出什麼:

(function immediateA(a) {
  return (function immediateB(b) {
    console.log(a); // => ?
  })(1);
})(0);
登入後複製

答案

輸出為:0

用參數0 呼叫immediateA,因此a 參數為0

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

3. 誰是誰

下面的程式碼將會輸出什麼內容?

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()  函數作用域內, count0

但是,在條件內,另一個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

程式碼分為兩個階段執行。

階段1

  1. for() 重複 3 次。在每次循環都會建立一個新函數 log(),該函數將捕獲變數 isetTimout() 安排log() 在 1000 毫秒後執行。
  2. for() 迴圈完成時,變數 i 的值為 3

階段2

第二階段發生在1000ms 之後:

  1. setTimeout() 執行預定的log() 函數。 log() 讀取變數i 目前的值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() 函數被呼叫3 次,將count 增加到3

message 變數存在於 createIncrement() 函數的作用域內。其初始值為 'Count is 0'。但即使 count 變數已經增加了幾次,message 變數的值也總是為 'Count is 0'

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

6. 重新封裝

下面的函數

createStack() 用來建立堆疊結構:

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]; // 栈结构的封装被破坏了
登入後複製
它能正常工作,但有一個小問題,因為暴露了

stack.items 屬性,所以任何人都可以直接修改items 陣列。

這是一個大問題,因為它破壞了堆疊的封裝:應該只有

push()pop() 方法是公開的,而 stack.items 或其他任何細節都不能被存取。

使用闭包的概念重构上面的栈实现,这样就无法在 createStack() 函数作用域之外访问 items 数组:

function createStack() {
  // 把你的代码写在这里
}

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

stack.items; // => undefined
登入後複製

答案

以下是对 createStack() 的重构:

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() 作用域内。

这样修改后,从 createStack() 作用域的外部无法访问或修改 items 数组。现在 items 是一个私有变量,并且栈被封装:只有 push()pop() 方法是公共的。

push()pop() 方法是闭包,它们从 createStack() 函数作用域中得到 items 变量。

7. 智能乘法

编写一个函数  multiply() ,将两个数字相乘:

function multiply(num1, num2) {
  // 把你的代码写在这里...
}
登入後複製

要求:

如果用 2 个参数调用 multiply(num1,numb2),则应返回这 2 个参数的乘积。

但是如果用 1个参数调用,则该函数应返回另一个函数: const anotherFunc = multiply(num1) 。返回的函数在调用 anotherFunc(num2)  时执行乘法  num1 * num2

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

const double = multiply(2);
double(5);  // => 10
double(11); // => 22
登入後複製

答案

以下是  multiply()  函数的一种实现方式:

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 参数不是 undefined,则该函数仅返回 number1 * number2

但是,如果 number2undefined,则意味着已经使用一个参数调用了 multiply() 函数。这时就要返回一个函数 doMultiply(),该函数稍后被调用时将执行实际的乘法运算。

doMultiply() 是闭包,因为它从 multiply() 作用域中得到了number1 变量。

总结

如果你答对了 5 个以上,说明对闭包掌握的很好。如果你答对了不到 5 个,则需要好好的复习一下了。

原文地址:https://dmitripavlutin.com/simple-explanation-of-javascript-closures/

转载地址:https://segmentfault.com/a/1190000039366748

更多编程相关知识,请访问:编程视频!!

以上是7個JavaScript中關於閉包的面試題,你能回答上來嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1667
14
CakePHP 教程
1426
52
Laravel 教程
1328
25
PHP教程
1273
29
C# 教程
1255
24
C++ lambda 表達式中閉包的意思是什麼? C++ lambda 表達式中閉包的意思是什麼? Apr 17, 2024 pm 06:15 PM

在C++中,閉包是能夠存取外部變數的lambda表達式。若要建立閉包,請擷取lambda表達式中的外部變數。閉包提供可重複使用性、資訊隱藏和延遲求值等優點。它們在事件處理程序等實際情況中很有用,其中即使外部變數被銷毀,閉包仍然可以存取它們。

C++ 函式中閉包的優點和缺點是什麼? C++ 函式中閉包的優點和缺點是什麼? Apr 25, 2024 pm 01:33 PM

閉包是一種巢狀函數,它能存取外層函數作用域的變量,優點包括資料封裝、狀態保持和靈活性。缺點包括記憶體消耗、效能影響和調試複雜性。此外,閉包還可以建立匿名函數,並將其作為回調或參數傳遞給其他函數。

解決閉包導致的記憶體洩漏問題 解決閉包導致的記憶體洩漏問題 Feb 18, 2024 pm 03:20 PM

標題:閉包造成的記憶體洩漏及解決方法引言:閉包是JavaScript中一個非常常見的概念,它可以讓內部函數存取外部函數的變數。然而,閉包在使用不當的情況下可能導致記憶體洩漏。本文將探討閉包所造成的記憶體洩漏問題,並提供解決方法及具體程式碼範例。一、閉包引起的記憶體洩漏問題閉包的特性是內部函數可以存取外部函數的變量,這意味著在閉包中引用的變數不會被垃圾回收。如果使用不當,

C++ Lambda 表達式如何實作閉包? C++ Lambda 表達式如何實作閉包? Jun 01, 2024 pm 05:50 PM

C++Lambda表達式支援閉包,即保存函數作用域變數並供函數存取。語法為[capture-list](parameters)->return-type{function-body}。 capture-list定義要捕獲的變量,可以使用[=]按值捕獲所有局部變量,[&]按引用捕獲所有局部變量,或[variable1,variable2,...]捕獲特定變量。 Lambda表達式只能存取捕獲的變量,但無法修改原始值。

PHP 函數的鍊式呼叫與閉包 PHP 函數的鍊式呼叫與閉包 Apr 13, 2024 am 11:18 AM

是的,可以透過鍊式呼叫和閉包優化程式碼簡潔性和可讀性:鍊式呼叫可將函數呼叫連結為一個流暢介面。閉包可建立可重複使用程式碼區塊,並在函數外部存取變數。

函數指標和閉包對Golang效能的影響 函數指標和閉包對Golang效能的影響 Apr 15, 2024 am 10:36 AM

函數指針和閉包對Go性能的影響如下:函數指針:稍慢於直接調用,但可提高可讀性和可復用性。閉包:通常更慢,但可封裝資料和行為。實戰案例:函數指標可最佳化排序演算法,閉包可建立事件處理程序,但會帶來效能損失。

golang函數閉包在測試中的作用 golang函數閉包在測試中的作用 Apr 24, 2024 am 08:54 AM

Go語言函數閉包在單元測試中發揮著至關重要的作用:捕獲值:閉包可以存取外部作用域的變量,允許在巢狀函數中捕獲和重複使用測試參數。簡化測試程式碼:透過擷取值,閉包消除了對每個循環重複設定參數的需求,從而簡化了測試程式碼。提高可讀性:使用閉包可以組織測試邏輯,使測試程式碼更清晰、更易於閱讀。

golang匿名函數和閉包的優缺點總結 golang匿名函數和閉包的優缺點總結 May 05, 2024 am 09:54 AM

匿名函數簡潔、匿名,但可讀性差、調試困難;閉包能封裝資料、管理狀態,但可能導致記憶體消耗和循環引用。實戰案例:匿名函數可用於簡單數值處理,閉包可實現狀態管理。

See all articles