摘要:朋友,這就是閉包的效果。那么函數(shù)就是一個閉包,它可以在作用域外被訪問。封閉函數(shù)必須返回至少一個內(nèi)部函數(shù),這樣內(nèi)部函數(shù)才能在私有作用域中形成閉包,并且可以訪問或者修改私有的狀態(tài)。的模塊機(jī)制中為模塊增加了一級語法支持。
閉包 閉包是什么?
當(dāng)函數(shù)可以記住并訪問所在的詞法作用域時,就產(chǎn)生了閉包,即使函數(shù)是在當(dāng)前詞法作用域之外執(zhí)行,簡單上講,就是在一個函數(shù)中內(nèi)部的函數(shù)。
function foo() { var a = 2; function bar() { console.log( a ); } return bar; } var baz = foo(); baz(); // 2 —— 朋友,這就是閉包的效果。
那么bar函數(shù)就是一個閉包,它可以在作用域外被訪問。
各種閉包實(shí)例:
function foo() { var a = 2; function baz() { console.log( a ); // 2 } bar( baz ); } function bar(fn) { fn(); // 媽媽快看呀,這就是閉包! }
function setupBot(name, selector) { $( selector ).click( function activator() { console.log( "Activating: " + name ); } ); } setupBot( "Closure Bot 1", "#bot_1" ); setupBot( "Closure Bot 2", "#bot_2" );
function wait(message) { setTimeout( function timer() { console.log( message ); }, 1000 ); } wait( "Hello, closure!" );
本質(zhì)上無論何時何地,如果將函數(shù)當(dāng)作第一級的值類型并到處傳遞,就會由閉包,在定時器、事件監(jiān)聽器、Ajax請求、跨窗口通信、Web Workers或者其他的異步(或者同步)任務(wù)中,只要使用了回調(diào)函數(shù),實(shí)際上就是閉包
模塊模塊實(shí)例:
function CoolModule() { var something = "cool"; var another = [1, 2, 3]; function doSomething() { console.log( something ); } function doAnother() { console.log( another.join( " ! " ) ); } return { doSomething: doSomething, doAnother: doAnother }; } var foo = CoolModule(); foo.doSomething(); // cool foo.doAnother(); // 1 ! 2 ! 3
這種模式在JavaScript中就是模塊。
最常見的實(shí)現(xiàn)模塊模式的方法通常被稱為模塊暴露。
模塊模式所具備的兩個必要特點(diǎn):
必須有外部的封閉函數(shù),該函數(shù)至少被調(diào)用一次(每次調(diào)用都會產(chǎn)生新的模塊實(shí)例)。 封閉函數(shù)必須返回至少一個內(nèi)部函數(shù),這樣內(nèi)部函數(shù)才能在私有作用域中形成閉包,并且可以訪問或者修改私有的狀態(tài)。
模塊模式的另一個簡單但強(qiáng)大的用法是命名將要作為公共API返回的對象。
var foo = (function CoolModule(id) { function change() { // 修改公共 API publicAPI.identify = identify2; } function identify1() { console.log( id ); } function identify2() { console.log( id.toUpperCase() ); } var publicAPI = { change: change, identify: identify1 }; return publicAPI; })( "foo module" ); foo.identify(); // foo module foo.change(); foo.identify(); // FOO MODULE
通過在模塊實(shí)例的內(nèi)部保留對公共API對象的內(nèi)部引用,可以從內(nèi)部對模塊實(shí)例進(jìn)行修改,包括添加或刪除方法和屬性,以及修改他們的值。
現(xiàn)代的簡單模塊機(jī)制:
var MyModules = (function Manager() { var modules = {} function define(name, argus, func) { for (var i = 0; i < argus.length; i++) { argus[i] = modules[argus[i]] } modules[name] = func.apply(func,argus) } function get(name) { return modules[name] } return { define: define, get: get } })() MyModules.define("bar", [], function () { function hello(who) { return "Let me introduce: " + who; } return { hello: hello }; }); MyModules.define("foo", ["bar"], function (bar) { var hungry = "hippo"; function awesome() { console.log(bar.hello(hungry).toUpperCase()); } return { awesome: awesome }; }); var bar = MyModules.get("bar"); var foo = MyModules.get("foo"); console.log( bar.hello.call(undefined, "hippo") ); // Let me introduce: hippo foo.awesome.call(undefined); // LET ME INTRODUCE: HIPPO
"foo"和"bar"模塊都是通過一個返回公共API的函數(shù)來定義的,“foo”甚至接受“bar”的實(shí)例作為依賴參數(shù),并能相應(yīng)的使用它。
它們符合前面列出的模塊模式的兩個特點(diǎn):調(diào)用包裝了函數(shù)定義的包裝函數(shù),并且將返回值作為該模塊的API。
ES6的模塊機(jī)制
ES6中為模塊增加了一級語法支持。在通過模塊系統(tǒng)進(jìn)行加載時,ES6會將文件當(dāng)作獨(dú)立的模塊來處理。每個模塊都可以導(dǎo)入其他模塊或特定的API成員,同時也可以導(dǎo)出自身的API成員。
重構(gòu)之前的模塊得三個文件
bar.js
function hello(who) { return "Let me introduce: " + who } export hello
foo.js
import hello from "bar" var hungry = "hippo" function awesome() { console.log(hello(hungry).toUpperCase()) } export awesome
baz.js
module foo from "foo" module bar from "bar" console.log(bar.hello("hippo")) foo.awesome
import方法:將一個模塊中的一個或多個API導(dǎo)入到當(dāng)前作用域中,并綁定在一個變量上。
module方法:將整個模塊的API導(dǎo)入并綁定到一個變量上
export方法:將當(dāng)前模塊的一個標(biāo)識符導(dǎo)出為公共API
模塊文件中的內(nèi)容會被當(dāng)作包含在作用域閉包中一樣來處理。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/93151.html
摘要:也許最好的理解是閉包總是在進(jìn)入某個函數(shù)的時候被創(chuàng)建,而局部變量是被加入到這個閉包中。在函數(shù)內(nèi)部的函數(shù)的內(nèi)部聲明函數(shù)是可以的可以獲得不止一個層級的閉包。 前言 總括 :這篇文章使用有效的javascript代碼向程序員們解釋了閉包,大牛和功能型程序員請自行忽略。 譯者 :文章寫在2006年,可直到翻譯的21小時之前作者還在完善這篇文章,在Stackoverflow的How do Java...
摘要:但是閉包也不是什么復(fù)雜到不可理解的東西,簡而言之,閉包就是閉包就是函數(shù)的局部變量集合,只是這些局部變量在函數(shù)返回后會繼續(xù)存在。可惜的是,并沒有提供相關(guān)的成員和方法來訪問閉包中的局部變量。 (收藏自 技術(shù)狂) 前言:還是一篇入門文章。Javascript中有幾個非常重要的語言特性——對象、原型繼承、閉包。其中閉包 對于那些使用傳統(tǒng)靜態(tài)語言C/C++的程序員來說是一個新的語言特性。本文將...
摘要:當(dāng)在中調(diào)用匿名函數(shù)時,它們用的都是同一個閉包,而且在這個閉包中使用了和的當(dāng)前值的值為因?yàn)檠h(huán)已經(jīng)結(jié)束,的值為。最好將閉包當(dāng)作是一個函數(shù)的入口創(chuàng)建的,而局部變量是被添加進(jìn)這個閉包的。 閉包不是魔法 這篇文章使用一些簡單的代碼例子來解釋JavaScript閉包的概念,即使新手也可以輕松參透閉包的含義。 其實(shí)只要理解了核心概念,閉包并不是那么的難于理解。但是,網(wǎng)上充斥了太多學(xué)術(shù)性的文章,對于...
摘要:深入系列第八篇,介紹理論上的閉包和實(shí)踐上的閉包,以及從作用域鏈的角度解析經(jīng)典的閉包題。定義對閉包的定義為閉包是指那些能夠訪問自由變量的函數(shù)。 JavaScript深入系列第八篇,介紹理論上的閉包和實(shí)踐上的閉包,以及從作用域鏈的角度解析經(jīng)典的閉包題。 定義 MDN 對閉包的定義為: 閉包是指那些能夠訪問自由變量的函數(shù)。 那什么是自由變量呢? 自由變量是指在函數(shù)中使用的,但既不是函數(shù)參數(shù)也...
摘要:一言以蔽之,閉包,你就得掌握。當(dāng)函數(shù)記住并訪問所在的詞法作用域,閉包就產(chǎn)生了。所以閉包才會得以實(shí)現(xiàn)。從技術(shù)上講,這就是閉包。執(zhí)行后,他的內(nèi)部作用域并不會消失,函數(shù)依然保持有作用域的閉包。 網(wǎng)上總結(jié)閉包的文章已經(jīng)爛大街了,不敢說筆者這篇文章多么多么xxx,只是個人理解總結(jié)。各位看官瞅瞅就好,大神還希望多多指正。此篇文章總結(jié)與《JavaScript忍者秘籍》 《你不知道的JavaScri...
摘要:但是,必須強(qiáng)調(diào),閉包是一個運(yùn)行期概念。通過原型鏈可以實(shí)現(xiàn)繼承,而與閉包相關(guān)的就是作用域鏈。常理來說,一個函數(shù)執(zhí)行完畢,其執(zhí)行環(huán)境的作用域鏈會被銷毀。所以此時,的作用域鏈雖然銷毀了,但是其活動對象仍在內(nèi)存中。 學(xué)習(xí)Javascript閉包(Closure)javascript的閉包JavaScript 閉包深入理解(closure)理解 Javascript 的閉包JavaScript ...
閱讀 4179·2021-11-22 13:52
閱讀 2509·2021-11-22 13:52
閱讀 3683·2021-11-19 09:59
閱讀 1185·2021-11-17 09:33
閱讀 2447·2019-08-30 10:53
閱讀 1219·2019-08-29 17:28
閱讀 1308·2019-08-29 17:03
閱讀 3099·2019-08-26 11:31