什麼是 Javascript 的閉包
什麼是閉包?
閉包是什麼?閉包是Closure,這是靜態語言所不具有的一個新特性。但是閉包也不是什麼複雜到不可理解的東西,簡而言之,閉包就是:閉包就是函數的局部變數集合,只是這些局部變數在函數回傳後會繼續存在。閉包就是是函數的「堆疊」在函數返回後並不釋放,我們也可以理解為這些函數堆疊並不在棧上分配而是在堆上分配,當在一個函數內定義另一個函數就會產生閉包。
閉包= 函數內部建立的函數(或簡稱內部函數) + 函數建立時所處環境資訊
所以閉包並不等於匿名函數,雖然也有人稱這些在函數內部建立的函數為閉包函數,但是我覺得其實不準確。
我們看一下下面這段程式碼:
function init() { var name = "Zilongshanren"; // name 是在 init 函数里面创建的变量 // displayName() 是一个内部函数,即一个闭包。注意,它不是匿名的。 function displayName() { console.log(name); } //当 displayName 函数返回后,这个函数还能访问 init 函数里面定义的变量。 return displayName; } var closure = init(); closure(); Zilongshanren undefined
displayName 是一個在 init 函數內部創建的函數,它攜帶了 init 函數內部作用域的所有信息,例如這裡的 name 變數。當 displayName 函數傳回的時候,它本身就攜帶了當時創建時的環境訊息,也就是 init 函數裡面的 name 變數。
閉包有什麼作用?
在理解什麼是閉包之後,接下來你可能會問:這東西這麼難理解,它到底有什麼用啊?
因為在 Js 裡面是沒有辦法建立私有方法的,它不像 java 或 C++有什麼 private 關鍵字可以定義私有的屬性和方法。 Js 裡面只有函數可以創造出屬於自身的作用域的對象,Js 並沒有塊作用域!這個我後面會再寫一篇文章詳細介紹。
程式老鳥都知道,程式寫得好,封裝和抽像要運用得好!不能定義私有的屬性和方法,意味著封裝和抽像根本沒用。 。 。
無法定義私有的東西,所有變數和函數都 public 顯然有問題, Global is Evil!
閉包是我們的救星!
我們看一下下面這段程式碼:
var makeCounter = function() { var privateCounter = 0; function changeBy(val) { privateCounter += val; } return { increment: function() { changeBy(1); }, decrement: function() { changeBy(-1); }, value: function() { return privateCounter; } } }; var counter1 = makeCounter(); var counter2 = makeCounter(); console.log(counter1.value()); /* Alerts 0 */ counter1.increment(); counter1.increment(); console.log(counter1.value()); /* Alerts 2 */ counter1.decrement(); console.log(counter1.value()); /* Alerts 1 */ console.log(counter2.value()); /* Alerts 0 */ 0 2 1 0 undefined
這裡面的 privateCounter 變數和 changeBy 都是私有的,對於 makeCounter 函數外部是完全不可見的。這樣我們透過 makeCounter 產生的物件就把自己的私有資料和私有方法全部隱藏起來了。
這裡有沒有讓你想到點什麼?
哈哈,這不就是 OO 麼?封裝資料和操作資料的方法,然後透過公共的介面呼叫來完成資料處理。
當然,你也許會說,我用原型繼承也可以實作 OO 呀。沒錯,現在大部分人也正是這麼幹的,包括我們自己。不過繼承這個東西,在理解起來總是非常困難的,因為要理解一段程式碼,你必須要理解它的所有繼承鏈。如果一旦程式碼出 bug 了,這將是非常難調試的。
扯遠了,接下來,讓我們看看如何正確地使用閉包。
如何正確地使用閉包?
閉包會佔用內存,也會影響 js 引擎的執行效率,所以,如果一段程式碼被頻繁執行,那麼要謹慎考慮在這段程式碼裡面使用閉包。
讓我們來看一個創建物件的函數:
function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); this.getName = function() { return this.name; }; this.getMessage = function() { return this.message; };} var myobj = new MyObject(); var myobj = new MyObject();
每一次被呼叫產生一個新物件的時候,都會產生兩個閉包。如果你的程式裡面有成千上萬個這樣的 MyObject 對象,那麼就會多出很多記憶體佔用。
正確的做法應該是使用原型鏈:
function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); } MyObject.prototype.getName = function() { return this.name; }; MyObject.prototype.getMessage = function() { return this.message; }; var myobj = new MyObject();
現在MyObject 原型上面定義了兩個方法,當我們透過new 去建立物件的時候,這兩個方法只會在原型上面存有一份。
閉包的效能如何?
閉包也是一個函數,但是它存儲了額外的環境信息,所以理論上它比純函數佔用更多的內存,而且 Js 引擎在解釋執行閉包的時候消耗也更大。不過它們之間的效能差異在 3%和 5%之間(這是 Google 上得到的數據,可能不會太準確)。
但是,閉包的好處一定是大大的。多使用閉包和無狀態編程,讓 Bug 從此遠離我們。
了解閉包,你就能理解大部分 FP 範式的 Js 類別庫及其隱藏在背後的設計想法。當然只有閉包還不夠,你還需要被 FP 和無狀態,lambda calculus 等概念洗腦。
關於js閉包希望大家學完本篇內容之後就有所掌握。
相關推薦:
以上是什麼是 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)

人臉偵測辨識技術已經是一個比較成熟且應用廣泛的技術。而目前最廣泛的網路應用語言非JS莫屬,在Web前端實現人臉偵測辨識相比後端的人臉辨識有優勢也有弱勢。優點包括減少網路互動、即時識別,大大縮短了使用者等待時間,提高了使用者體驗;弱勢是:受到模型大小限制,其中準確率也有限。如何在web端使用js實現人臉偵測呢?為了實現Web端人臉識別,需要熟悉相關的程式語言和技術,如JavaScript、HTML、CSS、WebRTC等。同時也需要掌握相關的電腦視覺和人工智慧技術。值得注意的是,由於Web端的計

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

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

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

js和vue的關係:1、JS作為Web開發基石;2、Vue.js作為前端框架的崛起;3、JS與Vue的互補關係;4、JS與Vue的實踐應用。

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

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

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