7個JavaScript中關於閉包的面試題,你能回答上來嗎?
相關推薦:2021年大前端面試題總結(收藏)
每個JavaScript 程式設計師都必須知道閉包是什麼。在 JavaScript 面試中,你很可能會被問到閉包的概念。
以下是 7 個有關 JavaScript 閉包的面試題,比較有挑戰性。
不要查看答案或運行程式碼,看看自己的水平到底如何。做完這些題大約要半小時左右。
1. 範圍
有以下函數clickHandler
,immediate
和delayedReload
#:
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
變量,其中a
為0
。因此 console.log(a)
的輸出為 0
。
3. 誰是誰
下面的程式碼將會輸出什麼內容?
let count = 0; (function immediate() { if (count === 0) { let count = 1; console.log(count); // 输出什么? } console.log(count); // 输出什么? })();
答案
輸出1
和0
第一個語句 let count = 0
宣告了一個變數count
。
immediate()
是一個閉包,它從外部作用域得到 count
變數。在 immediate()
函數作用域內, count
是 0
。
但是,在條件內,另一個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
-
for()
重複 3 次。在每次循環都會建立一個新函數log()
,該函數將捕獲變數i
。setTimout()
安排log()
在 1000 毫秒後執行。 - 當
for()
迴圈完成時,變數i
的值為3
。
階段2
第二階段發生在1000ms 之後:
-
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
。
但是,如果 number2
是 undefined
,则意味着已经使用一个参数调用了 multiply()
函数。这时就要返回一个函数 doMultiply()
,该函数稍后被调用时将执行实际的乘法运算。
doMultiply()
是闭包,因为它从 multiply()
作用域中得到了number1
变量。
总结
如果你答对了 5 个以上,说明对闭包掌握的很好。如果你答对了不到 5 个,则需要好好的复习一下了。
原文地址:https://dmitripavlutin.com/simple-explanation-of-javascript-closures/
转载地址:https://segmentfault.com/a/1190000039366748
更多编程相关知识,请访问:编程视频!!
以上是7個JavaScript中關於閉包的面試題,你能回答上來嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

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

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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

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

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

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

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

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

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

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

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