摘要:注意由定義可以知道,閉包函數(shù)肯定是定義在函數(shù)中,才可能有上級(jí)的函數(shù)作用域可以訪問(wèn),否則上級(jí)作用域就是全局作用域。造成這種結(jié)果的原因就是綁定的多個(gè)函數(shù)是閉包函數(shù),他們共同使用保留的上級(jí)函數(shù)作用域中的變量。
1 閉包的定義
維持了自由變量不被釋放的函數(shù), 稱為閉包,(自由變量指不在自身上下文,也不在全局上下文中的變量)。
那么閉包函數(shù)的特點(diǎn)在哪里,我們知道函數(shù)在創(chuàng)建的時(shí)候,它的[[scope]]屬性就已經(jīng)確定并不可以改變,所以閉包函數(shù)在創(chuàng)建的時(shí)候就保存了上級(jí)的作用域鏈,閉包函數(shù)通過(guò)作用域鏈去尋找使用到的變量,正常情況下,函數(shù)在執(zhí)行完畢后,將銷毀函數(shù)的執(zhí)行上下文,但是由于閉包函數(shù)的存在,包含閉包函數(shù)的上級(jí)函數(shù)執(zhí)行完畢后,如果閉包函數(shù)還存在,那么這個(gè)上級(jí)函數(shù)的作用域中的變量仍然保留在內(nèi)存中供閉包函數(shù)訪問(wèn)。
注意:
由定義可以知道,閉包函數(shù)肯定是定義在函數(shù)中,才可能有上級(jí)的函數(shù)作用域可以訪問(wèn),否則上級(jí)作用域就是全局作用域。全局作用域中的變量本身就一直在內(nèi)存中,所以訪問(wèn)全局作用域中變量的函數(shù)不能稱為閉包。
var name = "global"; function func1() { var name1 = "func1"; console.log(name); console.log(name); function func2() { console.log(name); var name2 = "func2"; function func3() { console.log(name2); } func3(); } func2(); } func1();
上面代碼中,func3為閉包函數(shù),因?yàn)樗L問(wèn)了上級(jí)函數(shù)作用域中的變量name2,func2不能稱為閉包函數(shù),因?yàn)樗鼈冊(cè)L問(wèn)的是全局作用域中的變量name。
2 常見(jiàn)的閉包場(chǎng)景 2.1 維持變量的閉包var person = (function(){ var _name = "yangyiliang"; var _age = 18; return { getName: function () { return _name; }, getAge: function () { return _age; }, addAge: function (num) { return _age += num; }, reduceAge: function (num) { return _age -= num; } } })(); console.log(person.addAge(5)); // 23 console.log(person.reduceAge(3)); //20
上面的代碼中,首先外層包裹了一個(gè)匿名立即執(zhí)行函數(shù),創(chuàng)造了一個(gè)上級(jí)函數(shù)作用域,getName和getAge方法都是在其內(nèi)部,并且訪問(wèn)了上級(jí)函數(shù)作用域中的變量,所以是閉包,所當(dāng)匿名函數(shù)執(zhí)行完畢后,本該銷毀的執(zhí)行上下文,卻因?yàn)殚]包函數(shù)而保留了作用域中的_name和 _age變量, 通過(guò)addAge 和reduceAge的結(jié)果發(fā)現(xiàn),兩個(gè)閉包共用保留的作用域。
2.2 維持參數(shù)的閉包function makeSizer(size) { return function() { document.body.style.fontSize = size + "px"; }; } var size12 = makeSizer(12); var size14 = makeSizer(14); var size16 = makeSizer(16); document.getElementById("size-12").onclick = size12; document.getElementById("size-14").onclick = size14; document.getElementById("size-16").onclick = size16;
上面的代碼中,makerSizer函數(shù)的返回值即為閉包函數(shù),閉包函數(shù)訪問(wèn)上級(jí)函數(shù)作用域中的參數(shù)。
2.3 循環(huán)創(chuàng)建閉包常見(jiàn)錯(cuò)誤
function bind() { var arr = document.getElementsByTagName("p"); for(var i = 0; i < arr.length;i++){ arr[i].onclick = function(){ alert(i); } } } bind();
上面的代碼中,假設(shè)arr的length為5,想要實(shí)現(xiàn)的功能是點(diǎn)擊5個(gè)P標(biāo)簽分別alert 0,1,2,3,4。但是事實(shí)上得到的結(jié)果卻是都alert 5。
造成這種結(jié)果的原因就是綁定的多個(gè)onclick函數(shù)是閉包函數(shù),他們共同使用保留的上級(jí)函數(shù)作用域中的變量 i 。 for循環(huán)執(zhí)行結(jié)束后 i 的值即為5。
要想解決這種錯(cuò)誤,就讓這些閉包保存不同的上級(jí)作用域即可。
function bind() { var arr = document.getElementsByTagName("p"); for(var i = 0; i < arr.length;i++){ (function (i) { arr[i].onclick = function(){ alert(i); } })(i); } } bind(); 或者 function bind() { var arr = document.getElementsByTagName("p"); for(var i = 0; i < arr.length;i++){ arr[i].onclick = (function(i){ return function () { alert(i); } })(i); } } bind();
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/88064.html
摘要:但是我們知道中是沒(méi)有重載的為什么沒(méi)重載不是的特性也會(huì)有的嗎,因?yàn)楹竺娑x的函數(shù)會(huì)覆蓋前面的同名函數(shù),但是重載那么好用,我們想在實(shí)現(xiàn)函數(shù)重載該怎么辦呢今天就來(lái)給大家講講在里面實(shí)現(xiàn)函數(shù)重載的兩個(gè)思路。這就是閉包的核心作用。 大家都知道,所謂重載,就是一組相同的函數(shù)名,有不同個(gè)數(shù)的參數(shù),在使用時(shí)調(diào)用一個(gè)函數(shù)名,傳入不同參數(shù),根據(jù)你的參數(shù)個(gè)數(shù),來(lái)決定使用不同的函數(shù)!重載這個(gè)在JAVA這些經(jīng)典的...
大家好:今天我們來(lái)徹底了解下什么是閉包:首先我們先看一個(gè)例子: var local =1; function a(){ console.log(local); }; 首先我來(lái)給大家介紹下:假設(shè)下如果上述代碼在一個(gè)立即執(zhí)行的函數(shù)中;那么變量local就是一個(gè)局部變量,有一個(gè)函數(shù)a,a可以訪問(wèn)到局部變量local;好了上述這個(gè)就是個(gè)閉包;在網(wǎng)上有許多介紹閉包的概念,如函數(shù)中嵌套一個(gè)函數(shù),然后將...
摘要:插件開(kāi)發(fā)前端掘金作者原文地址譯者插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。提供了與使用掌控異步前端掘金教你使用在行代碼內(nèi)優(yōu)雅的實(shí)現(xiàn)文件分片斷點(diǎn)續(xù)傳。 Vue.js 插件開(kāi)發(fā) - 前端 - 掘金作者:Joshua Bemenderfer原文地址: creating-custom-plugins譯者:jeneser Vue.js插件是為應(yīng)用添加全局功能的一種強(qiáng)大而且簡(jiǎn)單的方式。插....
摘要:使用閉包遇到的陷阱一陷阱在類的原型對(duì)象中添加特權(quán)方法首先定義一個(gè)類,該類中有一個(gè)私有變量定義個(gè)特權(quán)方法來(lái)訪問(wèn)修改私有變量然后我們對(duì)類進(jìn)行測(cè)試到目前為止,類正常工作。 使用JavaScript閉包遇到的陷阱(一) 陷阱:在類的原型對(duì)象中添加特權(quán)方法 首先定義一個(gè)Page類,該類中有一個(gè)私有變量dom: function Page(){ var dom; } 定義2個(gè)特權(quán)方法來(lái)訪問(wèn)...
摘要:什么時(shí)候需要用到單例模式呢其實(shí)單例模式在日常開(kāi)發(fā)中的使用非常的廣泛,例如各種浮窗像登錄浮窗等,無(wú)論我們點(diǎn)擊多少次,都是同一個(gè)浮窗,浮窗從始至終只創(chuàng)建了一次。這種場(chǎng)景就十分適合運(yùn)用單例模式。 單例模式 什么是單例模式? 單例模式的定義:一個(gè)類僅有一個(gè)實(shí)例,并且可以在全局訪問(wèn)。什么時(shí)候需要用到單例模式呢?其實(shí)單例模式在日常開(kāi)發(fā)中的使用非常的廣泛,例如各種浮窗、像登錄浮窗等,無(wú)論我們點(diǎn)擊多少...
閱讀 1120·2021-11-22 13:53
閱讀 1690·2021-11-17 09:33
閱讀 2455·2021-10-14 09:43
閱讀 2986·2021-09-01 11:41
閱讀 2355·2021-09-01 10:44
閱讀 3056·2021-08-31 09:39
閱讀 1576·2019-08-30 15:44
閱讀 1920·2019-08-30 13:02