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