摘要:另一方面,函數(shù)外部無法直接讀取函數(shù)內(nèi)的局部變量。這說明,函數(shù)中的局部變量一直保存在內(nèi)存中,并沒有在調(diào)用后被自動清除。首先函數(shù)沒有使用關(guān)鍵字來聲明,因此是一個全局變量,而不是局部變量。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。
原文鏈接 - http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
一、變量的作用域要理解閉包,首先必須理解 Javascript 特殊的變量作用域。
變量的作用域無非就是兩種:全局變量和局部變量。
Javascript 語言的特殊之處,就在于函數(shù)內(nèi)部可以直接讀取全局變量。
var n = 999; function foo () { console.log(n); } foo(); // 999
另一方面,函數(shù)外部無法直接讀取函數(shù)內(nèi)的局部變量。
function foo () { var n = 999; } console.log(n); // error
這里有一個地方需要注意,在函數(shù)內(nèi)部一定要使用var聲明變量,否則這個變量就會聲明是一個全局變量!
function foo () { n = 999; } foo(); console.log(n); // 999二、如何從外部讀取局部變量?
出于種種原因,我們有時候需要得到函數(shù)內(nèi)的局部變量。但是,前面已經(jīng)說過了,正常情況下,這是辦不到的,只有通過變通方法才能實(shí)現(xiàn)。
那就是在函數(shù)的內(nèi)部,再定義一個函數(shù)。
function fn1 () { var n = 999; function fn2 () { console.log(n); // 999 } }
在上面的代碼中,函數(shù)fn2可以直接讀取其父函數(shù)fn1內(nèi)部的所有局部變量。但是反過來就不行,fn2內(nèi)部的局部變量,對fn1就是不可見的。
這就是 Javascript 語言特有的鏈?zhǔn)阶饔糜?/strong>,子對象會一級一級地向上尋找所有父對象的變量。所以,父對象的所有變量,對子對象都是可見的,反之則不成立。
既然fn2可以讀取fn1中的局部變量,那么只要把fn2作為返回值,就可以在fn1外部讀取它的內(nèi)部變量了。
function fn1 () { var n = 999; function fn2 () { console.log(n); } return fn2; } var result = fn1(); result(); // 999
這里的fn2函數(shù),就是閉包。
三、閉包的概念各種專業(yè)文獻(xiàn)上的"閉包"(closure)定義非常抽象,很難看懂。
我的理解是,閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。
由于在 Javascript 語言中,只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量,因此可以把閉包簡單理解成"定義在一個函數(shù)內(nèi)部的函數(shù)"。
所以,在本質(zhì)上,閉包就是將函數(shù)內(nèi)部和函數(shù)外部連接起來的一座橋梁。
閉包最大用處有兩個,一個是前面提到的可以讀取函數(shù)內(nèi)部的變量,另一個就是讓這些變量的值始終保持在內(nèi)存中。
function fn1 () { var n = 999; add = function(){ n += 1 } function fn2 () { alert(n); } return fn2; } var result = fn1(); result(); // 999 add(); result(); // 1000
在這段代碼中,result實(shí)際上就是閉包fn2函數(shù)。它一共運(yùn)行了兩次,第一次的值是999,第二次的值是1000。
這說明,函數(shù)fn1中的局部變量n一直保存在內(nèi)存中,并沒有在fn1調(diào)用后被自動清除。
為什么會這樣呢?原因就在于fn1是fn2的父函數(shù),而fn2被賦給了一個全局變量,這導(dǎo)致fn2始終在內(nèi)存中,而fn2的存在依賴于fn1,因此fn1也始終在內(nèi)存中,不會在調(diào)用結(jié)束后,被垃圾回收機(jī)制回收。
這段代碼中另一個值得注意的地方,就是add = function(){ n+=1 }這一行。
首先函數(shù)add沒有使用var關(guān)鍵字來聲明,因此add是一個全局變量,而不是局部變量。
其次,add的值是一個匿名函數(shù),而這個匿名函數(shù)本身也是一個閉包,所以add相當(dāng)于是一個setter,可以在函數(shù)外部對函數(shù)內(nèi)部的局部變量進(jìn)行操作。
由于閉包會使得函數(shù)中的變量都被保存在內(nèi)存中,因此內(nèi)存消耗很大,所以不能濫用閉包,否則會造成網(wǎng)頁的性能問題,在IE中可能導(dǎo)致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。
閉包會在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。所以,如果你把父函數(shù)當(dāng)作對象(object)使用,把閉包當(dāng)作它的公用方法(Public Method),把內(nèi)部變量當(dāng)作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值。
六、思考題如果能理解下面兩段代碼的運(yùn)行結(jié)果,應(yīng)該就算理解閉包的運(yùn)行機(jī)制了。
代碼片段一。
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; console.log(object.getNameFunc()());
代碼片段二。 var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; console.log(object.getNameFunc()());
提示:這兩個問題的關(guān)鍵在于this指向誰。
(完)文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/81718.html
摘要:下面讓我們來看一個例子上面就是一個最簡單的閉包。閉包的作用接下來來談?wù)勯]包的作用,初學(xué)者剛接觸時肯定是一臉懵逼,閉包的用處究竟是什么,下面就來談一談。同時也得感謝參考文章閉包的應(yīng)用讓你分分鐘理解閉包閉包,懂不懂由你,反正我是懂了 昨天在看思否時,發(fā)現(xiàn)了一篇文章是關(guān)于JavaScript如何實(shí)現(xiàn)重載的,由于以前也和學(xué)長討論過JavaScript是否能夠重載,就點(diǎn)進(jìn)去看了看,發(fā)現(xiàn)里面的兩個...
摘要:譯者按在上一篇博客,我們通過實(shí)現(xiàn)一個計(jì)數(shù)器,了解了如何使用閉包,這篇博客將提供一些代碼示例,幫助大家理解閉包。然而,如果通過代碼示例去理解閉包,則簡單很多。不過,將閉包簡單地看做局部變量,理解起來會更加簡單。 - 譯者按: 在上一篇博客,我們通過實(shí)現(xiàn)一個計(jì)數(shù)器,了解了如何使用閉包(Closure),這篇博客將提供一些代碼示例,幫助大家理解閉包。 原文: JavaScript Clos...
摘要:但閉包的情況不同嵌套函數(shù)的閉包執(zhí)行后,,然后還在被回收閉包會使變量始終保存在內(nèi)存中,如果不當(dāng)使用會增大內(nèi)存消耗。每個函數(shù),不論多深,都可以認(rèn)為是全局的子作用域,可以理解為閉包。 閉包(closure)是Javascript語言的一個難點(diǎn),也是它的特色,很多高級應(yīng)用都要依靠閉包實(shí)現(xiàn)。 閉包的特性 閉包有三個特性: 1.函數(shù)嵌套函數(shù) 2.函數(shù)內(nèi)部可以引用外部的參數(shù)和變量 3.參數(shù)和變量不會...
摘要:閉包的注意事項(xiàng)通常,函數(shù)的作用域及其所有變量都會在函數(shù)執(zhí)行結(jié)束后被銷毀。但是,在創(chuàng)建了一個閉包以后,這個函數(shù)的作用域就會一直保存到閉包不存在為止。最后通過釋放了和對閉包的引用。從而使用閉包模塊化代碼,減少全局變量的污染。 JavaScript 閉包 原文鏈接 什么是閉包(Closure) 簡單講,閉包就是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)。 MDN 上面這么說:閉包是一種特殊的...
摘要:但是閉包也不是什么復(fù)雜到不可理解的東西,簡而言之,閉包就是閉包就是函數(shù)的局部變量集合,只是這些局部變量在函數(shù)返回后會繼續(xù)存在??上У氖?,并沒有提供相關(guān)的成員和方法來訪問閉包中的局部變量。 (收藏自 技術(shù)狂) 前言:還是一篇入門文章。Javascript中有幾個非常重要的語言特性——對象、原型繼承、閉包。其中閉包 對于那些使用傳統(tǒng)靜態(tài)語言C/C++的程序員來說是一個新的語言特性。本文將...
閱讀 1206·2021-11-24 09:39
閱讀 2129·2021-11-22 13:54
閱讀 2111·2021-09-08 10:45
閱讀 1443·2021-08-09 13:43
閱讀 2985·2019-08-30 15:52
閱讀 3083·2019-08-29 15:38
閱讀 2848·2019-08-26 13:44
閱讀 3055·2019-08-26 13:30