首頁 web前端 js教程 什麼是 Javascript 的閉包

什麼是 Javascript 的閉包

Nov 20, 2017 pm 03:28 PM
javascript js 閉包

什麼是閉包?

閉包是什麼?閉包是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閉包希望大家學完本篇內容之後就有所掌握。

相關推薦:

JS中關於閉包的簡單解釋

js中閉包和類別如何理解

對js閉包的簡單理解

以上是什麼是 Javascript 的閉包的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1318
25
PHP教程
1269
29
C# 教程
1248
24
建議:優秀JS開源人臉偵測辨識項目 建議:優秀JS開源人臉偵測辨識項目 Apr 03, 2024 am 11:55 AM

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

C++ lambda 表達式中閉包的意思是什麼? C++ lambda 表達式中閉包的意思是什麼? Apr 17, 2024 pm 06:15 PM

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

C++ 函式中閉包的優點和缺點是什麼? C++ 函式中閉包的優點和缺點是什麼? Apr 25, 2024 pm 01:33 PM

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

C++ Lambda 表達式如何實作閉包? C++ Lambda 表達式如何實作閉包? Jun 01, 2024 pm 05:50 PM

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

js和vue的關係 js和vue的關係 Mar 11, 2024 pm 05:21 PM

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

函數指標和閉包對Golang效能的影響 函數指標和閉包對Golang效能的影響 Apr 15, 2024 am 10:36 AM

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

PHP 函數的鍊式呼叫與閉包 PHP 函數的鍊式呼叫與閉包 Apr 13, 2024 am 11:18 AM

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

golang函數閉包在測試中的作用 golang函數閉包在測試中的作用 Apr 24, 2024 am 08:54 AM

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

See all articles