摘要:這段代碼中另一個值得注意的地方,就是這一行,首先在前面沒有使用關鍵字,因此是一個全局變量,而不是局部變量。
閉包的定義閉包在js里面的存在就好像奧利奧冰淇淋里面的奧利奧,沒了奧利奧,冰淇淋還是冰淇淋,畢竟js 就是一個你怎么寫都能好好運行的好語言。可是人寫的代碼總是要高級484,所以好好理解閉包好么。
閉包是指有權訪問另一個函數作用域中的變量的函數,創建閉包的最常見的方式就是在一個函數內創建另一個函數,通過另一個函數訪問這個函數的局部變量
閉包的特性1.函數嵌套函數
2.函數內部可以引用外部的參數和變量
3.參數和變量不會被垃圾回收機制回收
下面是一個更有意思的示例 — makeAdder 函數:
function makeAdder(x) { return function(y) { return x + y; }; } var add5 = makeAdder(5); var add10 = makeAdder(10); console.log(add5(2)); // 7 console.log(add10(2)); // 12
在這個示例中,我們定義了 makeAdder(x) 函數:帶有一個參數 x 并返回一個新的函數。返回的函數帶有一個參數 y,并返回 x 和 y 的和。
從本質上講,makeAdder 是一個函數工廠 — 創建將指定的值和它的參數求和的函數,在上面的示例中,我們使用函數工廠創建了兩個新函數 — 一個將其參數和 5 求和,另一個和 10 求和。
add5 和 add10 都是閉包。它們共享相同的函數定義,但是保存了不同的環境。在 add5 的環境中,x 為 5。而在 add10 中,x 則為 10。
理論就是這些 — 可是閉包確實有用嗎?閉包允許將函數與其所操作的某些數據(環境)關連起來。這顯然類似于面向對象編程。在面對象編程中,對象允許我們將某些數據(對象的屬性)與一個或者多個方法相關聯。
因而,一般說來,可以使用只有一個方法的對象的地方,都可以使用閉包。
在 Web 中,可能想這樣做的情形非常普遍。大部分我們所寫的 Web JavaScript 代碼都是事件驅動的 — 定義某種行為,然后將其添加到用戶觸發的事件之上(比如點擊或者按鍵)。我們的代碼通常添加為回調:響應事件而執行的函數。
閉包的最大用處有兩個,一個是前面提到的可以讀取函數內部的變量,另一個就是讓這些變量的值始終保持在內存中。
function f1() { var n = 999; nAdd = function(){ n += 1 } function f2(){ console.log(n); } return f2; } var result = f1(); result();//999 nAdd(); result();//1000
在這段代碼中,result實際上就是閉包f2函數。它一共運行了兩次,第一次的值是999,第二次的值是1000。這證明了,函數f1中的局部變量n一直保存在內存中,并沒有在f1調用后被自動清除。
為什么會這樣呢?原因就在于f1是f2的父函數,而f2被賦給了一個全局變量,這導致f2始終在內存中,而f2的存在依賴于f1,因此f1也始終在內存中,不會在調用結束后,被垃圾回收機制(garbage collection)回收。
這段代碼中另一個值得注意的地方,就是"nAdd=function(){n+=1}"這一行,首先在nAdd前面沒有使用var關鍵字,因此nAdd是一個全局變量,而不是局部變量。其次,nAdd的值是一個匿名函數(anonymous function),而這個匿名函數本身也是一個閉包,所以nAdd相當于是一個setter,可以在函數外部對函數內部的局部變量進行操作。
如果不是因為某些特殊任務而需要閉包,在沒有必要的情況下,在其它函數中創建函數是不明智的,因為閉包對腳本性能具有負面影響,包括處理速度和內存消耗。
例如,在創建新的對象或者類時,方法通常應該關聯于對象的原型,而不是定義到對象的構造器中。原因是這將導致每次構造器被調用,方法都會被重新賦值一次(也就是說,為每一個對象的創建)。
以下雖然不切實際但卻說明問題的示例:
function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); } MyObject.prototype = { getName: function() { return this.name; }, getMessage: function() { return this.message; } };
上面的代碼并未利用到閉包的益處,因此,應該修改為如下常規形式:
function MyObject(name, message) { this.name = name.toString(); this.message = message.toString(); } MyObject.prototype = { getName: function() { return this.name; }, getMessage: function() { return this.message; } };
參考備注:
阮一峰 學習Javascript閉包(Closure) MDN Web技術文檔 JavaScript 閉包
附上我的訂閱號,歡迎關注,一起學前端
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79896.html
摘要:從我年開始接觸前端,知道閉包這個詞,已經過去兩年了。概念閉包,在高級程序設計里面是這樣介紹的閉包是指有權訪問另一個作用域中的變量的函數。這樣形成的閉包雖然可以使外部可以訪問到內部的函數,但是導致了原有的作用域鏈不釋放,會造成內存泄漏。 從我16年開始接觸前端,知道閉包這個詞,已經過去兩年了。這兩年里,閉包這個概念我在很多地方了解過,卻實在沒有真的理解,久而久之,變成了一塊心病。這不,趁...
摘要:模塊化編程首先,我想說說模塊化編程這個概念當我不清楚這個概念的時候,其實說什么模塊化編程多好多好都是懵逼的而我一直不覺得有多好,其實也是因為我從開始寫,就一直都在模塊化編程啊我們寫一個文件然后我們在文件中引入然后調用方法哈哈這樣已經是模塊化 模塊化編程 首先,我想說說模塊化編程這個概念當我不清楚這個概念的時候,其實說什么模塊化編程多好多好都是懵逼的而我一直不覺得有多好,其實也是因為我從...
摘要:有時候你寫一個方法,里面一堆循環,循環里一堆自己看看都覺得死了其實人家自帶的方法已經寫了,你用一下就好了。好了,撩一張圖。 有時候你寫一個方法,里面一堆for循環,for循環里一堆if else自己看看都覺得low死了其實人家js自帶的方法已經寫了,你用一下就好了。 因為我寫erp的么,然后就會用到金額,金額的話一般保留兩位小數,然后用千分位顯示,你打算怎么寫,先用小數點區分小數位和整...
摘要:鑒于此目的,我決定快速構建一個用于此目的的問卷調查應用程序。這將啟動一個服務器并將應用程序部署到該服務器。圖應用程序配置基礎前端這個問卷調查應用程序對常見用戶界面和布局使用了框架。 全棧教程。轉自 使用 Node.js、Express、AngularJS 和 MongoDB 構建一個實時問卷調查應用程序 最近,在向大學生們介紹 HTML5 的時候,我想要對他們進行問卷調查,并向他們顯...
摘要:代表公司去參加今年的第二屆前端開發者年度大會,散會的時候,技術老大問我,今天感覺怎么樣,有什么收獲,當時就零零碎碎的回答了一些,不算完美趁著還記得點什么,在這里做個自我回顧總結,謹代表個人見解,有不當之處,或若涉及圖片隱私或者其它問題,煩請 代表公司去參加今年的 第二屆前端開發者年度大會,散會的時候,Team 技術老大問我,今天感覺怎么樣,有什么收獲,當時就零零碎碎的回答了一些,不算完...
閱讀 1751·2021-09-27 14:02
閱讀 3100·2021-09-27 13:36
閱讀 1046·2019-08-30 12:46
閱讀 1834·2019-08-30 10:51
閱讀 3571·2019-08-29 17:02
閱讀 941·2019-08-29 16:38
閱讀 1846·2019-08-29 16:37
閱讀 3004·2019-08-26 10:32