一入前端深似海,從此紅塵是路人系列第三彈之淺析JavaScript閉包
前言:最近由於公司專案太忙,很久沒有更新部落格了,加上之前就一直說要發表一篇有關閉包的部落格幫助小夥伴們好好的理解一些JavaScript中的難點。所以,今天趁著國慶假期前趕緊寫了去,寫完國慶好好出去浪個夠。
首先,必須要提的就是閉包它絕對算的上是JavaScript中的一大難點,當然也是一大重點。N多高階程式都需要或者必須用到閉包才能得以實現。參考了N篇很牛叉的對於閉包理解的文章,接下來我將陳述一下鄙人自己對於閉包的理解,希望可以幫助小夥伴們通俗切入閉包這個點。
1、變數作用域
理解閉包很重要的一點就是需要先理解JavaScript特殊的變數作用域。
而變數作用域無非兩種形式,全域性變數和區域性變數。而在JavaScript中,所有的函式它都可以在其內部訪問到全域性變數。
var n = 123;
function test1(){
alert(n);
}
test1(); //123
而在函式外部也無法讀取函式內的區域性變數。
function test1(){
var n=123;
}
test1();
alert(n); // Uncaught ReferenceError: n is not defined
當然在定義變數的時候,一定要記住加上var關鍵字,不然,JavaScript會預設你定義了一個全域性變數。
function test1(){
n=123;
}
test1();
alert(n); // 123
2、函式外部訪問區域性變數
很多時候我們需要在一個函式中去訪問另外一個函式內部的區域性變數,可是上面又說了一個函式內部的區域性變數是不允許被其他函式訪問的。怎麼辦呢?
那我們就需要在函式內部在定義一個函式,這樣就可以在其內部函式中訪問到它內部的區域性變數了。上程式碼理解。
function test1(){
// 函式test2就被包括在函式test1內部,這時test1內部的所有區域性變數,對test2都是可見的
var n=123;
function test2(){
// test2內部的區域性變數則不能被test1訪問
// 這就是Javascript語言特有的"鏈式作用域"結構(chain scope),子物件會一級一級地向上尋找所有父物件的變數。所以,父物件的所有變數,對子物件都是可見的,反之則不成立。
var n1 = 321;
alert(n);
}
//alert(n1); // error
return test2;
}
var result=test1();
result(); // 123
而上面程式碼中的test2就是一個閉包,它是一種能夠讀取其他函式內部變數的函式,或者直接理解為定義在一個函式內部的函式。
3、閉包的用途
閉包可以用在很多地方。但它最大的用處有兩點。第一點是以上提到的,訪問其他函式內部的區域性變數。還有一個很重要的用途則是讓這些變數始終儲存在記憶體中。不多解釋,直接看程式碼理解
function test1(){
/**
* test1是test2的父函式,而test2被賦給了一個全域性變數result,這導致test2始終在記憶體中
* 而test2的存在依賴於test1,因此test1也始終在記憶體中
* 這樣test1中的區域性變數就不會在呼叫結束後,被垃圾回收機制回收。
*/
var n=123;
// nAdd前面沒有var關鍵字,它是一個全域性變數。nAdd的值是一個匿名函式,而這個匿名函式本身也是一個閉包
// 它相當於一個setter,可以在函式外部對函式內部的區域性變數進行操作。
nAdd = function(){
n+=1
}
function test2(){
alert(n);
}
return test2;
}
var result=test1();
result(); // 123
nAdd();
result(); // 124
4、閉包使用中需注意的問題
1)由於閉包會使得函式中的變數都被儲存在記憶體中,記憶體消耗很大,所以不能濫用閉包,否則會造成網頁的效能問題,在IE中可能導致記憶體洩露。解決方法是,在退出函式之前,將不使用的區域性變數全部刪除。
2)閉包會在父函式外部,改變父函式內部變數的值。所以,如果你把父函式當作物件使用,把閉包當作它的公用方法,把內部變數當作它的私有屬性,這時一定要小心,不要隨便改變父函式內部變數的值。
5、練習思考題
當你可以理解以下兩段程式碼執行結果時,那麼恭喜你,你已經理解了閉包的執行機制了。
//程式碼一
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());
//程式碼二
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()());
好了,文章最後。還是那句話,如果覺著可以幫助到小夥伴的話,求點個贊哦。若覺著哪裡有說錯或者寫錯的地方,還請小夥伴們輕噴,但是歡迎小夥伴隨時指正部落格中的錯誤然後大家一起交流探討!(*^__^*)
文釋出時間為:2016年09月30日
原文作者:qiangdada
本文來源:開源中國 如需轉載請聯絡原作者
相關文章
- 一入前端深似海,從此紅塵是路人系列第七彈之孤獨的劍客-單例模式前端單例模式
- 淺析Javascript閉包的特性JavaScript
- 玩轉雲端 | 資料管理深似海,運維如何變“路人”?運維
- 前端入門19-JavaScript進階之閉包前端JavaScript
- 深入淺出JavaScript之閉包(Closure)JavaScript
- 【Javascript】淺析JS中閉包的來龍去脈JavaScriptJS
- 前端小祕密系列之閉包前端
- PHP Clourse(閉包類) 淺析PHP
- 閉包捕捉(closure capture)淺析APT
- 閉包 | 淺談JavaScript閉包問題JavaScript
- javascript由淺入深JavaScript
- 前端小知識--從Javascript閉包看let前端JavaScript
- 合格前端系列第六彈-從指向看JavaScript前端JavaScript
- java閉包和回撥淺析Java
- 深入淺出Javascript閉包JavaScript
- JavaScript之淺析PromiseJavaScriptPromise
- JavaScript Promise由淺入深JavaScriptPromise
- JavaScript之閉包JavaScript
- 一入爬蟲深似海,總結python爬蟲學習筆記!爬蟲Python筆記
- JavaScript深入之閉包JavaScript
- JavaScript 深入之閉包JavaScript
- MySql架構原理(MySql從淺入深 一)MySql架構
- 自學Web前端的五個不同階段,從淺入深Web前端
- 無人機get新技能,從此男友成路人!無人機
- 遊戲出海全面分析系列(一):當藍海已成紅海,中國廠商何去何從?遊戲
- JavaScript從作用域到閉包JavaScript
- javascript之溫習閉包JavaScript
- IOS學習之淺析深拷貝與淺拷貝iOS
- JavaScript專題之深淺拷貝JavaScript
- 前端 JavaScript 程式設計風格淺析前端JavaScript程式設計
- 前端戰五渣學JavaScript——閉包前端JavaScript
- javascript中閉包是什麼JavaScript
- 淺入深出的微前端MicroApp前端APP
- JavaScript 閉包入門(譯文)JavaScript
- 深入JavaScript基礎之深淺拷貝JavaScript
- JavaScript之深拷貝和淺拷貝JavaScript
- 深入理解JavaScript之深淺複製JavaScript
- 征服 JavaScript 面試:什麼是閉包JavaScript面試