閉包機制是JavaScript的重點與困難點,本文希望能幫助大家輕鬆的學習閉包。以下跟著小編一起來看吧
摘要
閉包機制是Javascript的重點與困難點,本文希望能幫助大家輕鬆的學習閉包
一、什麼是閉包?
閉包就是可以存取另一個函數作用域中變數的函數。
下面列舉常見的閉包實作方式,以例子講解閉包概念
function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999 nAdd(); result(); // 1000
f1是f2的父函數,而f2被賦給了一個全域變數(return的值) ,這導致f2始終在記憶體中,而f2的存在依賴f1,因此f1也始終在記憶體中,不會在呼叫結束後,被垃圾回收機制(garbage collection)回收,這便形成了閉包。
因此,可以這麼理解。 閉包機制就是,如果A函數引用了另一個函數B的變量,但B返回後A仍沒有返回,仍存在,因為A的引用,所以B的所有局部變數並不會隨B退出而註銷,會一直存在,直到A註銷。此時A就是閉包。
二、閉包的this指標
#閉包通常在全域環境呼叫的,所以this通常指向window,具體情況還是需要視執行環境而言,總之this指向執行環境。
若需要閉包的this指向閉包的包含物件,則需要將包含物件的this當作變數傳進閉包。
三、使用閉包的注意點
#由於閉包會使得函數中的變數都保存在記憶體中,記憶體消耗很大,所以不能濫用閉包,否則會造成網頁的效能問題,在IE中可能導致記憶體外洩。解決方法是,在退出函數之前,將不使用的局部變數全部刪除。
閉包會在父函數外部,改變父函數內部變數的值。所以,如果你把父函數當作物件(object)使用,把閉包當作它的公用方法(Public Method),把內部變數當作它的私有屬性 (private value),這時一定要小心,不要隨便改變父函數內部變數的值。
四、解決一道閉包常見面試題
問題:
#function onMyLoad(){ /* 抛出问题: 此题的目的是想每次点击对应目标时弹出对应的数字下标 0~4,但实际是无论点击哪个目标都会弹出数字5 问题所在: arr 中的每一项的 onclick 均为一个函数实例(Function 对象),这个函数实例也产生了一个闭包域, 这个闭包域引用了外部闭包域的变量,其 function scope 的 closure 对象有个名为 i 的引用, 外部闭包域的私有变量内容发生变化,内部闭包域得到的值自然会发生改变 */ var arr = document.getElementsByTagName("p"); for(var i = 0; i < arr.length;i++){ arr[i].onclick = function(){ alert(i); } } }
解決方法
1、在外面再加一層函數,將i當作函數參數傳進來,這樣每次保存的是函數內部的變量,與外部i不是同一個記憶體空間,而每次呼叫函數都會產生一個局部變量,所以可以保證每次保存的值互不影響。
for(var i = 0; i<arr.length;i++){ arr[i].onclick = (function(arg){ return function () { alert(arg); } })(i); }
2、用ES6新特let,將for循環的var i改成let i,這樣當前的i只在本輪循環有效,所以每一次循環的i其實都是一個新的變數。你可能會問,如果每一輪循環的變數i都是重新聲明的,那它怎麼知道上一輪循環的值,從而計算出本輪循環的值?這是因為 Javascript 引擎內部會記住上一輪循環的值,初始化本輪的變數i時,就在上一輪循環的基礎上進行計算。
以上是JavaScript閉包的輕鬆理解的詳細內容。更多資訊請關注PHP中文網其他相關文章!