Javascript學習筆記之 函數篇(三) : 閉包與引用_基礎知識
Javascript 中一個最重要的特性就是閉包的使用。因為閉包的使用,目前作用域總是可以存取外部的作用域。因為 Javascript 沒有區塊級作用域,只有函數作用域,所以閉包的使用與函數是緊密相關的。
模擬私有變數
function Counter(start) {
var count = start;
return {
increment: function() {
count ;
},
get: function() {
return count;
}
}
}
var foo = Counter(4);
foo.increment();
foo.get(); // 5
這裡 Counter 回傳兩個閉包:函數 increment 和 get。這兩個函數一直保持著對 Counter 作用域的訪問,因此它們能一直訪問到定義在 Counter 作用域的變數 count。
私有變數的工作機制
由於 Javascript 不可以對作用域賦值和引用,所以在上例中,是沒有辦法在外部直接存取內部私有變數 count。唯一的方法就是透過定義閉包來存取。
var foo = new Counter(4);
foo.hack = function() {
count = 1337;
};
上面的程式碼不會改變 Counter 作用域內的 count 變數值,因為 hack 沒有在 Counter 內定義。上面這段程式碼只會建立或覆蓋全域變數 count。
循環內的閉包
一個最容易犯的錯誤就是在循環內使用閉包。
for(var i = 0; i setTimeout(function() {
console.log(i);
}, 1000);
}
上面這段程式碼不會輸出0到9,而是連續輸出10次10。
上面的匿名會一直保持一個變數 i 的引用。當呼叫 console.log 函數開始輸出時,這是循環已經結束,而變數 i 已經為10了。
為了避免上面的錯誤發生,我們需要在每次循環時為變數 i 值建立拷貝。
避免引用錯誤
為了複製迴圈中變數的值,最好的方式是在外層加上一個匿名的立刻執行函數。
for(var i = 0; i (function(e) {
setTimeout(function() {
console.log(e);
}, 1000);
})(i);
}
這個外部的匿名函數接收循環變數 i 作為第一個參數,並將其值拷貝至它自己的參數 e。
外部的匿名函數將參數 e 再傳遞給 setTimeout,因此 setTimeout 有了指向參數 e 的參考。而這個參數 e 的值不會因為外在的循環改變而改變。
還有另一個方法可以達到相同的效果,就是在 setTimeout 內的匿名函數中再傳回一個匿名函數:
for(var i = 0; i setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
}
此外,透過 bind 方法也可以實現。
for(var i = 0; i setTimeout(console.log.bind(console, i), 1000);
}
文章最後我們來總結下:
(1)閉包是一種設計原則,它透過分析上下文,來簡化使用者的調用,讓使用者在不知曉的情況下,達到他的目的;
(2)網路上主流的對閉包剖析的文章其實是和閉包原則反向而馳的,如果需要知道閉包細節才能用好的話,這個閉包是設計失敗的;
(3)盡量少學習。

熱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表達式中的外部變數。閉包提供可重複使用性、資訊隱藏和延遲求值等優點。它們在事件處理程序等實際情況中很有用,其中即使外部變數被銷毀,閉包仍然可以存取它們。

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

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

C++中的函數傳回參考類型的好處包括:效能提升:引用傳遞避免了物件複製,從而節省了記憶體和時間。直接修改:呼叫方可以直接修改傳回的參考對象,而無需重新賦值。程式碼簡潔:引用傳遞簡化了程式碼,無需額外的賦值操作。

C++中引用和指標都是傳遞函式參數的方法,但有差別。引用是變數的別名,修改引用會修改原始變量,而指標儲存變數的位址,修改指標值不會修改原始變數。在選擇使用引用還是指標時,需要考慮是否需要修改原始變數、是否需要傳遞空值和效能考量等因素。

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

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

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