摘要:閉包的注意事項通常函數的作用域及其所有變量都會在函數執行結束后被銷毀。閉包中的對象在上面這段代碼中,實際上是在全局作用域中調用了匿名函數,指向了。
1.閉包
2.原型鏈
3.深/淺拷貝
4.this指向
5.柯里式
6.ES6
7.webpack 配置 打包
8.虛擬dom
9.js 堆棧
1.浮動原理 為什么要清浮動
2.css選擇器優先級 瀏覽器怎么進行解讀及渲染
3.absolute relative的定位相對圓點是什么?
我個人認為,理解閉包的關鍵在于:外部函數調用之后其變量對象本應該被銷毀,但閉包的存在使我們仍然可以訪問外部函數的變量對象,這就是閉包的重要概念。
//看一個閉包的例子 function outer () { var a = 1;//定義一個內部變量 return function() { return a;//返回a的變量值 }; } var b = outer(); console.log(b());//打印1
創建閉包最常見方式,就是在一個函數內部創建另一個函數。
閉包的作用域包含著它自己的作用域,以及包含它的函數的作用域和全局作用域。
閉包的注意事項:
通常,函數的作用域及其所有變量都會在函數執行結束后被銷毀。但是,在創建一個閉包后,這個函數的作用域就會一直保存到閉包不存在為止。
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 //釋放對閉包的引用 add5 = null; add10 = null;
從上述代碼可以看到add5和add10都是閉包。它們共同享有相同的函數定義,但是保存了不同的環境。在add5的環境中,x為5。而在 add10 中,x 則為 10。最后通過 null 釋放了 add5 和 add10 對閉包的引用。
在javascript中,如果一個對象不再被引用,那么這個對象就會被垃圾回收機制回收;
如果兩個對象互相引用,而不再被第3者所引用,那么這兩個互相引用的對象也會被回收。
閉包只能取得包含函數中任何變量的最后一個值
function arrFunc() { var arr = []; for(var i=0;i<10;i++) { arr[i] = function() { return i; } } return arr; }
大家看一下上面這個代碼,arr數組中包含了10個匿名函數,每個匿名函數都能訪問外部函數的變量i,那么i是多少呢?
當arrFunc執行完畢后,其作用域被銷毀,但它的變量對象仍保存在內存中,得以被匿名訪問,這時i的值為10。
要想保存在循環過程中每一個i的值,需要在匿名函數外部再套用一個匿名函數,在這個匿名函數中定義另一個變量并且立即執行來保存i的值。
function arrFunc() { var arr = []; for(var i=0;i<10;i++) { arr[i] = function(num) { return function() { return num; }; }(i); } return arr; } console.log( arrFunc()[1]() );
這時最內部的匿名函數訪問的是num的值,所以數組中10個匿名函數的返回值就是1-10。
閉包中的this對象
var name = "window"; var obj = { name: "object", getName: function() { return function() { return this.name; }; } }; console.log(obj.getName()())
在上面這段代碼中,obj.getName()()實際上是在全局作用域中調用了匿名函數,this指向了window。
這里要理解函數名與函數功能是分割開的,不要認為函數在哪里,其內部的this就指向哪里。
window才是匿名函數功能執行的環境。
如果想使this指向外部函數的執行環境,可以這樣改寫:
var name = "window"; var obj = { name: "object", getName: function() { var that = this; return function() { return that.name; }; } }; console.log(obj.getName()()) //object
內存泄露
閉包會引用包含函數的整個變量對象,如果閉包的作用域鏈中保存著一個HTML元素,那么就意味著該元素無法被銷毀。所以我們有必要在對這個元素操作完之后主動銷毀。
function assignHandler() { var ele = document.getElementById("demo"); var id = ele.id; ele.onclick = function() { alert(id); }; ele = null; }
函數內部的定時器
當函數內部的定時器引用了外部函數的變量對象時,該變量對象不會被銷毀。
(function() { var a = 0; setInterval(function(){ console.log(a++); },1000); })()
閉包的應用
應用閉包的主要場合是:設計私有的方法和變量。
任何在函數中定義的變量,都可以認為是私有變量,因為不能在函數外部訪問這些變量。私有變量包括函數的參數、局部變量和函數內定義的其他函數。
把有權訪問私有變量的公有方法稱為特權方法(privileged method)。
function Animal() { //私有變量 var series = "哺乳動物"; function run() { console.log("Run!!!"); } //特權方法 this.getSeries = function() { return series; } }
在這里,我們需要理解兩個概念:
模塊模式(The Module Pattern):為單例創建私有變量和方法。
單例(singleton):指的是只有一個實例的對象。JavaScript 一般以對象字面量的方式來創建一個單例對象。
運用閉包的關鍵
閉包引用外部函數變量對象中的值;
在外部函數的外部調用閉包。
閉包的缺陷
閉包的缺點就是常駐內存會增大內存使用量,并且使用不當很容易造成內存泄露。
如果不是因為某些特殊任務而需要閉包,在沒有必要的情況下,在其它函數中創建函數是不明智的,因為閉包對腳本性能具有負面影響,包括處理速度和內存消耗。
最后 來一道有關閉包的面試題
下面代碼中,標記 ? 的地方輸出分別是什么?
function fun(n,o){ console.log(o); return { fun: function(m){ return fun(m,n); } }; } var a = fun(0); //undefined a.fun(1); //0 a.fun(2); //0 a.fun(3); //0 var b = fun(0).fun(1).fun(2).fun(3); //undefined 0 1 2 var c = fun(0).fun(1); //undefined 0 c.fun(2); // 0 1 c.fun(3); //0 1
為什么要用閉包
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102121.html
摘要:大名鼎鼎的閉包面試必問。閉包的作用是什么??吹介]包在哪了嗎閉包到底是什么五年前,我也被這個問題困擾,于是去搜了并總結下來。關于閉包的謠言閉包會造成內存泄露錯。閉包里面的變量明明就是我們需要的變量,憑什么說是內存泄露這個謠言是如何來的因為。 本文為饑人谷講師方方原創文章,首發于 前端學習指南。 大名鼎鼎的閉包!面試必問。請用自己的話簡述 什么是「閉包」。 「閉包」的作用是什么。 首先...
摘要:完美的閉包,對,閉包就這么簡單。這僅僅是閉包的一部分,閉包利用函數作用域達到了訪問外層變量的目的。此時一個完整的閉包實現了,的垃圾回收機制由于閉包的存在無法銷毀變量。 1.閉包是指有權訪問另一個函數作用域中的變量的函數。 上面這段話來自 javascript 高級程序設計 第三版 P178 。作者說閉包是一個函數,它有訪問另一個函數作用域中的變量的能力。 2.函數訪問它被創建時所處的...
摘要:到底什么是閉包這個問題在面試是時候經常都會被問,很多小白一聽就懵逼了,不知道如何回答好。上面這么說閉包是一種特殊的對象。閉包的注意事項通常,函數的作用域及其所有變量都會在函數執行結束后被銷毀。從而使用閉包模塊化代碼,減少全局變量的污染。 閉包,有人說它是一種設計理念,有人說所有的函數都是閉包。到底什么是閉包?這個問題在面試是時候經常都會被問,很多小白一聽就懵逼了,不知道如何回答好。這個...
閱讀 3030·2021-11-22 09:34
閱讀 2506·2021-09-30 09:47
閱讀 1439·2021-09-03 10:32
閱讀 3704·2021-08-16 10:49
閱讀 1784·2019-08-30 15:55
閱讀 2451·2019-08-30 15:52
閱讀 3316·2019-08-30 15:44
閱讀 1344·2019-08-30 15:44