日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產(chǎn)品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
十個用圖表解釋JavaScript 閉包的面試題

你準備好了嗎?我們現(xiàn)在要開始了。

成都創(chuàng)新互聯(lián)專注于秦都企業(yè)網(wǎng)站建設,成都響應式網(wǎng)站建設,成都商城網(wǎng)站開發(fā)。秦都網(wǎng)站建設公司,為秦都等地區(qū)提供建站服務。全流程定制設計,專業(yè)設計,全程項目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務

每個題目都有一個代碼片段,你需要說出這段代碼的輸出是什么。

1、范圍

在說閉包之前,我們必須了解作用域的概念,它是理解閉包的基石。

此代碼段的輸出是什么?

var a = 10
function foo(){
console.log(a)
}
foo()

這很簡單,相信所有人都知道輸出結果是10。

  • 默認情況下,有一個全局范圍。
  • 本地作用域由函數(shù)或代碼塊創(chuàng)建。

當執(zhí)行 console.log(a) 時,JavaScript 引擎將首先在函數(shù) foo 創(chuàng)建的本地范圍內查找 a。當 JavaScript 引擎找不到 a 時,它會嘗試在其外部作用域(即全局作用域)中查找 a。然后事實證明a的值為10。

2、 局部作用域

var a = 10
function foo(){
var a = 20
console.log(a)
}
a = 30
foo()

在這段代碼中,變量 a 也存在于 foo 的范圍內。所以當執(zhí)行 console.log(a) 時,JavaScript 引擎可以直接從本地作用域獲取 a 的值。

所以輸出是 20 。

記?。寒?JavaScript 引擎需要查詢一個變量的值時,它會首先在本地范圍內查找,如果沒有找到該變量,它會繼續(xù)在上層范圍內查找。

3、詞法作用域

var a = 10
function foo(){
console.log(a)
}
function bar() {
var a = 20
foo()
}
bar()

這個問題容易出錯,也是面試中經(jīng)常出現(xiàn)的問題,你可以考慮一下。

簡單地說,JavaScript 實現(xiàn)了一種名為詞法作用域(或靜態(tài)作用域)的作用域機制。它被稱為詞法(或靜態(tài)),因為引擎僅通過查看 JavaScript 源代碼來確定范圍的嵌套,無論它在哪里調用。

所以輸出是 10 :

4、修改詞法作用域

如果我們將代碼片段更改為:

var a = 10
function bar() {
var a = 20
function foo(){
console.log(a)
}
foo()
}
bar()

輸出是什么?

foo 范圍成為 bar 范圍的子范圍:

當 JavaScript 引擎在 Foo 作用域中沒有找到 a 時,它會首先從 Foo 作用域的父作用域,也就是 Bar 作用域中尋找 a,它確實找到了 a。

所以輸出是 20:

好了,以上就是關于范圍的一些基本挑戰(zhàn),相信你能順利通過?,F(xiàn)在我們開始進入閉包的部分。

5、 閉包

function outerFunc() {
let a = 10;
function innerFunc() {
console.log(a);
}
return innerFunc;
}
let innerFunc = outerFunc();
innerFunc()

輸出是什么?這段代碼會拋出異常嗎?

在詞法范圍內,innerFunc 仍然可以訪問 a,即使在其詞法范圍之外執(zhí)行。

換句話說,innerFunc 從其詞法范圍中記住(或關閉)變量 a。

換句話說,innerFunc 是一個閉包,因為它在變量 a 的詞法范圍內關閉。

因此,這段代碼不會拋出異常,而是輸出 10。

6、 IIFE

(function(a) {
return (function(b) {
console.log(a);
})(1);
})(0);

此代碼片段使用 JavaScript 立即調用函數(shù)表達式 (IIFE)。

我們可以簡單地將這段代碼翻譯成這樣:

function foo(a){
function bar(b){
console.log(a)
}
return bar(1)
}
foo(0)

所以輸出是 0 。

閉包的一個經(jīng)典應用是隱藏變量。

比如現(xiàn)在要寫一個計數(shù)器,基本的寫法是這樣的:

let i = 0
function increase(){
i++
console.log(`courrent counter is ${i}`)
return i
}
increase()
increase()
increase()

可以這樣寫,但是在全局范圍內會多出一個變量i,這樣就不好了。

這時候,我們可以使用閉包來隱藏這個變量。

let increase = (function(){
let i = 0
return function(){
i++
console.log(`courrent counter is ${i}`)
return i
}
})()
increase()
increase()
increase()

這樣,變量 i 就隱藏在局部范圍內,不會污染全局環(huán)境。

7、多重聲明和使用

let count = 0;
(function() {
if (count === 0) {
let count = 1;
console.log(count);
}
console.log(count);
})();

在這個代碼片段中,有兩個 count 的聲明和三個 count 的用法。這是一個難題,你應該仔細考慮。

首先,我們要知道if代碼塊也創(chuàng)建了一個局部作用域,上面的作用域大致是這樣的。

  • Function Scope 沒有聲明自己的計數(shù),所以我們在這個作用域中使用的計數(shù)是全局作用域的計數(shù)。
  • If Scope 聲明了自己的計數(shù),所以我們在這個作用域中使用的計數(shù)就是當前作用域的計數(shù)。

或在此圖中:

所以輸出是 1 , 0 :

8、調用多個閉包

function cr
eateCounter(){
let i = 0
return function(){
i++
return i
}
}
let increase1 = createCounter()
let increase2 = createCounter()
console.log(increase1())
console.log(increase1())
console.log(increase2())
console.log(increase2())

這里需要注意的是,increase1和increase2是通過不同的函數(shù)調用createCounter創(chuàng)建的,它們不共享內存,它們的i是獨立的,不同的。

所以輸出是 1 , 2 , 1 , 2 。

9、返回函數(shù)

function createCounter() {
let count = 0;
function increase() {
count++;
}
let message = `Count is ${count}`;
function log() {
console.log(message);
}
return [increase, log];
}
const [increase, log] = createCounter();
increase();
increase();
increase();
log();

這段代碼很容易理解,但是有個陷阱:message其實是一個靜態(tài)字符串,它的值固定為Count為0,當我們調用increase或者log時不會改變。

所以每次調用 log 函數(shù),輸出結果總是 Count is 0 。

如果您希望 log 函數(shù)及時檢查 count 的值,請將 message 移入 log :

function createCounter() {
let count = 0;
function increase() {
count++;
}
- let message = `Count is ${count}`;
function log() {
+ let message = `Count is ${count}`;
console.log(message);
}
return [increase, log];
}
const [increase, log] = createCounter();
increase();
increase();
increase();
log();

10、異步閉包

for (var i = 0; i < 5; i++) {
setTimeout(function () {
console.log(i);
}, 0)
}

輸出是什么?

上面的代碼等價于:

var i = 0;
setTimeout(function(){
console.log(i);
},0)
i = 1;
setTimeout(function(){
console.log(i);
},0)
i = 2;
setTimeout(function(){
console.log(i);
},0)
i = 3;
setTimeout(function(){
console.log(i);
},0)
i = 4;
setTimeout(function(){
console.log(i);
},0)
i = 5

而且我們知道JavaScript會先執(zhí)行同步代碼,然后再執(zhí)行異步代碼。所以每次執(zhí)行console.log(i)時,i的值已經(jīng)變成了5。

所以輸出是 5 , 5 , 5 , 5 , 5 。

如果我們想要代碼輸出 0 , 1 , 2 , 3 , 4 ,需要怎么操作?

使用閉包的解決方案是:

for ( var i = 0 ; i < 5 ; ++i ) {
(function(cacheI){
setTimeout(function(){
console.log(cacheI);
},0)
})(i)
} ;

上面的代碼等價于:

var i = 0;
(function(cacheI){setTimeout(function(){
console.log(cacheI);
},0)})(i)
i = 1;
(function(cacheI){setTimeout(function(){
console.log(cacheI);
},0)})(i)
i = 2;
(function(cacheI){setTimeout(function(){
console.log(cacheI);
},0)})(i)
i = 3;
(function(cacheI){setTimeout(function(){
console.log(cacheI);
},0)})(i)
i = 4;
(function(cacheI){setTimeout(function(){
console.log(cacheI);
},0)})(i)

我們通過 JavaScript 立即調用的函數(shù)表達式創(chuàng)建函數(shù)范圍。i 的值是通過閉包保存的。

恭喜你,到這里,你已經(jīng)學會了這些面試挑戰(zhàn)題。

希望在開發(fā)面試中,閉包相關的問題不會再困擾你了。

最后,感謝你的閱讀,如果你覺得有用的話,請點贊我,關注我,并將其分享給你的身邊做開發(fā)的朋友,也許能夠幫助到他。


分享題目:十個用圖表解釋JavaScript 閉包的面試題
分享URL:http://m.5511xx.com/article/djcdcec.html