相關推薦:2021年大前端面試題總結(收藏)
每個JavaScript 程式設計師都必須知道閉包是什麼。在 JavaScript 面試中,你很可能會被問到閉包的概念。
以下是 7 個有關 JavaScript 閉包的面試題,比較有挑戰性。
不要查看答案或運行程式碼,看看自己的水平到底如何。做完這些題大約要半小時左右。
有以下函數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影片教學
下列程式碼輸出什麼:
(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
。
下面的程式碼將會輸出什麼內容?
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
變數是從外部作用域存取的。
下列程式碼輸出什麼:
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。
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'到控制台。
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
变量。
编写一个函数 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中文網其他相關文章!