做淘寶客網(wǎng)站要注意什么免費(fèi)建站免費(fèi)推廣的網(wǎng)站
theme: smartblue
題目描述
給定一個(gè)整型參數(shù)?n
,請(qǐng)你編寫(xiě)并返回一個(gè)?counter
函數(shù)。這個(gè)?counter
函數(shù)最初返回?n
,每次調(diào)用它時(shí)會(huì)返回前一個(gè)值加 1 的值 (?n
?,??n + 1
?,??n + 2
?,等等)。
示例 1:
輸入: n = 10 ["call","call","call"] 輸出: [10,11,12] 解釋: counter() = 10 // 第一次調(diào)用 counter(),返回 n。 counter() = 11 // 返回上次調(diào)用的值加 1。 counter() = 12 // 返回上次調(diào)用的值加 1。
示例 2:
輸入: n = -2 ["call","call","call","call","call"] 輸出: [-2,-1,0,1,2] 解釋: counter() 最初返回 -2。然后在每個(gè)后續(xù)調(diào)用后增加 1。
提示:
-1000?<= n <= 1000
0 <= calls.length <= 1000
calls[i] === "call"
題解
概述
這個(gè)問(wèn)題旨在介紹?閉包(closures) *?的概念。在 JavaScript 中,函數(shù)具有對(duì)在相同作用域以及任何外部作用域中聲明的所有變量的引用。這些作用域被稱(chēng)為函數(shù)的?詞法環(huán)境。函數(shù)與其環(huán)境的組合被稱(chēng)為?閉包*。
閉包示例
在 JavaScript 中,你可以在其他函數(shù)內(nèi)部聲明并返回函數(shù)。內(nèi)部函數(shù)可以訪(fǎng)問(wèn)在其上方聲明的任何變量。
function createAdder(a) { return function add(b) { const sum = a + b; return sum; } } const addTo2 = createAdder(2); addTo2(5); // 7
在示例代碼中,內(nèi)部函數(shù)?add
?可以訪(fǎng)問(wèn)?a
。這允許了外部函數(shù)充當(dāng)新函數(shù)的工廠(chǎng),每個(gè)函數(shù)都具有不同的行為。
閉包 VS 類(lèi)
你可能會(huì)注意到,在上面的示例中,createAdder
?非常類(lèi)似于類(lèi)構(gòu)造函數(shù)。
``` class Adder { constructor(a) { this.a = a; }
add(b) { const sum = this.a + b; return sum; } } const addTo2 = new Adder(2); addTo2.add(5); // 7 ```
除了語(yǔ)法上的差異之外,這兩個(gè)示例在本質(zhì)上具有相同的目的。它們都允許你在「構(gòu)造函數(shù)(Constructor)」中傳遞一些狀態(tài),并具有可以訪(fǎng)問(wèn)此狀態(tài)的「方法 (Method)」。
它們之間一個(gè)關(guān)鍵的區(qū)別是閉包允許真正的?封裝。在類(lèi)的示例中,沒(méi)有任何限制阻止你編寫(xiě)?addTo2.a = 3;
?并破壞其預(yù)期行為。然而,在閉包的示例中,理論上無(wú)法訪(fǎng)問(wèn)?a
。請(qǐng)注意,截至2022年,使用?# 前綴語(yǔ)法?的類(lèi)仍然可以實(shí)現(xiàn)真正的封裝。
另一個(gè)區(qū)別是函數(shù)在內(nèi)存中的存儲(chǔ)方式。如果創(chuàng)建了許多類(lèi)的實(shí)例,每個(gè)實(shí)例都存儲(chǔ)對(duì)?原型對(duì)象?的單一引用,其中都存儲(chǔ)了所有「方法(Method)」。而對(duì)于閉包,所有「方法(Method)」都在每次調(diào)用外部函數(shù)時(shí)生成并存儲(chǔ)了一個(gè)「副本(Copy)」。因此,在同時(shí)有多種方法可用的情況下,類(lèi)可以在性能方面體現(xiàn)更高的效率。
與像 Java 這樣的語(yǔ)言不同,你會(huì)發(fā)現(xiàn)使用其他語(yǔ)言編寫(xiě)的代碼通常使用函數(shù)而不是類(lèi)。但由于 JavaScript 是一種多范式語(yǔ)言,代碼如何編寫(xiě)取決于你正在處理的具體項(xiàng)目。
方法
現(xiàn)在讓我們討論實(shí)現(xiàn)計(jì)數(shù)器的方法。
方法 1: 先增加再返回
我們先聲明一個(gè)變量?currentCount
?并將其設(shè)置為?n - 1
。然后在?counter
?函數(shù)內(nèi)部,增加?currentCount
?并返回其值。請(qǐng)注意,由于修改了?currentCount
?,應(yīng)該使用?let
?而不是?const
?來(lái)聲明它。
實(shí)現(xiàn):
var createCounter = function(n) { let currentCount = n - 1; return function() { currentCount += 1; return currentCount; }; };
var createCounter = function(n: number) { let currentCount = n - 1; return function() { currentCount += 1; return currentCount; }; };
方法 2: 后綴遞增語(yǔ)法
JavaScript 提供了方便的語(yǔ)法,可以先返回一個(gè)值然后遞增它。這使我們可以避免把初始值設(shè)置為?n - 1
?。
代碼實(shí)現(xiàn):
var createCounter = function(n) { return function() { return n++; }; };
var createCounter = function(n: number) { return function() { return n++; }; };
方法 3: 前綴遞減和遞增語(yǔ)法
JavaScript 還有一種語(yǔ)法,允許你先遞增一個(gè)值返回它。由于遞增發(fā)生在值返回之前,因此我們必須先對(duì)初始值進(jìn)行遞減,類(lèi)似于方法 1 。
代碼實(shí)現(xiàn):
var createCounter = function(n) { --n; return function() { return ++n; }; };
var createCounter = function(n: number) { --n; return function() { return ++n; }; };
方法 4: 帶箭頭函數(shù)的后綴遞增語(yǔ)法
我們可以使用帶有隱式返回的箭頭函數(shù)來(lái)減少方法 2 中的代碼量。
實(shí)現(xiàn):
var createCounter = function(n) { return () => n++; };
var createCounter = function(n: number) { return () => n++; };
這些是不同的方法來(lái)實(shí)現(xiàn)計(jì)數(shù)器,你可以根據(jù)項(xiàng)目的需要選擇其中之一。