摘要:模仿塊級(jí)作用域立即執(zhí)行函數(shù)前言最近在細(xì)讀高級(jí)程序設(shè)計(jì),對(duì)于我而言,中文版,書中很多地方一筆帶過,所以用自己所理解的,嘗試細(xì)致解讀下。語(yǔ)法如下這里是塊級(jí)作用域以上代碼定義并立即調(diào)用了一個(gè)匿名函數(shù)。
模仿塊級(jí)作用域-立即執(zhí)行函數(shù)
前言:最近在細(xì)讀Javascript高級(jí)程序設(shè)計(jì),對(duì)于我而言,中文版,書中很多地方一筆帶過,所以用自己所理解的,嘗試細(xì)致解讀下。如有紕漏或錯(cuò)誤,會(huì)非常感謝您的指出。文中絕大部分內(nèi)容引用自《JavaScript高級(jí)程序設(shè)計(jì)第三版》。
JavaScript沒有塊級(jí)作用域的概念(ES5中沒有)。這意味著在塊語(yǔ)句定義的變量,實(shí)際上是在函數(shù)中而非語(yǔ)句中創(chuàng)建的。
function outputNumbers(count) { for( var i = 0; i < count; i ++ ) { console.log(i); // 0,1,2,3,4,5,6,7,8,9 } console.log(i); //10 } outputNumbers(10);
在函數(shù)outputNumbers()中定義了一個(gè)for循環(huán), 而變量i的初始值被設(shè)置為0。
在Java、C++等語(yǔ)言中,變量i只會(huì)在for循環(huán)的語(yǔ)句中有定義,循環(huán)一旦結(jié)束,變量i就會(huì)被銷毀。
可是在JavaScript中,變量只是定義在函數(shù)outputNumbers()的活動(dòng)對(duì)象中的,因此從它有定義開始,就可以在函數(shù)內(nèi)部隨處訪問它。
即使像下面這樣錯(cuò)誤地重新聲明同一個(gè)變量,也不會(huì)改變它的值。
function outputNumbers(count) { // 注意變量提升 var i for(var i = 0; i < count; i++) { console.log(i); // 0, 1, 2, 4, 5, 6, 7, 8, 9 }; var i; console.log(i); // 10 } outputNumbers(10);
JavaScript從來(lái)不會(huì)告訴你是否多次聲明了同一個(gè)變量;
遇到這種情況,它只會(huì)對(duì)后續(xù)的聲明視而不見(不過,它會(huì)執(zhí)行后續(xù)聲明中的變量初始化)。
匿名函數(shù)可以用來(lái)模仿塊級(jí)作用域并避免這個(gè)問題(其實(shí)就是立即執(zhí)行函數(shù)), 一定要注意變量的生命周期,局部變量只在執(zhí)行環(huán)境中存在,塊級(jí)作用域其實(shí)就是立即執(zhí)行函數(shù),即刻產(chǎn)生一個(gè)作用域,塊級(jí)作用域里面的變量只在塊級(jí)作用域里面,避免了變量污染,隔離出一個(gè)獨(dú)立的作用域(私有作用域)。
//語(yǔ)法如下 (function(){ //這里是塊級(jí)作用域 })()
以上代碼定義并立即調(diào)用了一個(gè)匿名函數(shù)。
將函數(shù)聲明包含在一對(duì)圓括號(hào)中,表示它實(shí)際上是一個(gè)函數(shù)表達(dá)式。
而緊隨其后的另一對(duì)圓括號(hào)會(huì)立即調(diào)用這個(gè)函數(shù)。
這種語(yǔ)法,確實(shí)很不好理解。
來(lái)看下下面的例子
var someFunction = function() { //這里是塊級(jí)作用域 }; someFunction();
這個(gè)例子先定義了一個(gè)函數(shù),然后立即調(diào)用它。定義函數(shù)的方式是創(chuàng)建一個(gè)匿名函數(shù),并把匿名函數(shù)賦值給變量someFunction。而調(diào)用函數(shù)的方式是在函數(shù)名稱后面添加一對(duì)圓括號(hào),即someFunction()。那么我們可不可以,聲明函數(shù)和調(diào)用函數(shù)寫在一塊呢?
function(){ //這里是塊級(jí)作用域 }(); //出錯(cuò)
這段代碼會(huì)導(dǎo)致語(yǔ)法錯(cuò)誤,因?yàn)镴avaScript將function關(guān)鍵字當(dāng)做一個(gè)函數(shù)聲明的開始。而函數(shù)聲明后面不能跟圓括號(hào)。
如果我們?cè)趂unction關(guān)鍵字前面加一個(gè)運(yùn)算符,這樣就不會(huì)讓JavaScript將function關(guān)鍵字當(dāng)做函數(shù)聲明的開始。解析器,就會(huì)依次從左往右解析代碼。
//解析過程 運(yùn)算符 => 函數(shù)聲明function => 調(diào)用() !function(){ console.log("hi"); }(); // "hi" +function(){ console.log("hello"); }(); // "hello" -function(){ console.log("World"); }(); // "World" (function(){ console.log("ciao"); })(); // "ciao"
無(wú)論在什么地方,只要臨時(shí)需要一些變量,就可以使用私有作用域。
function outputNumbers(count) { //立即執(zhí)行函數(shù),隔離出一個(gè)獨(dú)立的作用域,避免變量的污染 //同時(shí)也是一個(gè)閉包, 能訪問到外部函數(shù)中的count (function(){ for(var i= 0; i < count; i++) { console.log(i); } })(); console.log(i); // error } outputNumbers(10); // 0,1,2,3,4,5,6,7,8,9 //i is not defined
這種技術(shù)(使用私有作用域),經(jīng)常在全局作用域使用。
**從而限制向全局作用域中添加過多的變量和函數(shù)。
因?yàn)闀?huì)產(chǎn)生變量污染,私有作用域可以訪問到全局變量,而全局變量訪問不到私有作用域里面的變量。**
一般來(lái)說,我們都應(yīng)該盡量少向全局作用域中添加變量和函數(shù)。
在一個(gè)由很多開發(fā)人員共同參與的大型應(yīng)用程序中,過多的全局變量和函數(shù)很容易導(dǎo)致命名沖突。
而通過創(chuàng)建私有作用域,每個(gè)開發(fā)人員都可以使用自己的變量,又不必?fù)?dān)心搞亂全局作用域。
(function(){ var now = new Date(); if(now.getMonth() == 0 && now.getDate() == 1) { console.log("Happy New Year!"); } })();
把上面這段代碼放在全局作用域中,可以用來(lái)確定哪一天是1月1日。
如果到了這一天,就會(huì)向用戶顯示一條祝賀新年的信息。
其中的變量now現(xiàn)在是匿名函數(shù)中的局部變量,而我們不必在全局作用域中創(chuàng)建它。
這種做法可以減少閉包占用的內(nèi)存問題,因?yàn)闆]有指向匿名函數(shù)的引用。只要函數(shù)執(zhí)行完畢,就可以立即銷毀其作用域鏈了。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/98849.html
摘要:指針指針指針重要的時(shí)期說三遍由于對(duì)象類型為指針引用在變量復(fù)制方面,基本類型和引用類型也有所不同。在瀏覽器中,全局執(zhí)行環(huán)境被認(rèn)為是對(duì)象。 javascript---Symbol類型, 引用類型, 作用域 javascript的引用類型, 即對(duì)象類型是我們最常用的的類型, 其中有許多讓我們需要注意的地方, 最新的 , ES6 的推出, 使得對(duì)象類型的屬性名不僅僅可以是字符串類型,還可是Si...
摘要:而閉包的妙處在于,當(dāng)函數(shù)在執(zhí)行完畢后它的活動(dòng)對(duì)象不會(huì)被銷毀,因?yàn)槟涿瘮?shù)的作用域鏈仍然在引用函數(shù)的活動(dòng)對(duì)象它的作用域鏈會(huì)被銷毀。 一、閉包 閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。創(chuàng)建閉包的常用方式是,在一個(gè)函數(shù)內(nèi)部創(chuàng)建另一個(gè)函數(shù)。 請(qǐng)看以下代碼:我們?cè)赾reateComparisonFunction函數(shù)里創(chuàng)建了一個(gè)閉包 function createComparisonFun...
摘要:遞歸閉包模仿塊級(jí)作用域私有變量小結(jié)在編程中,使用函數(shù)表達(dá)式可以無(wú)需對(duì)函數(shù)命名,從而實(shí)現(xiàn)動(dòng)態(tài)編程。匿名函數(shù)也稱為拉姆達(dá)函數(shù)。函數(shù)聲明要求有名字,但函數(shù)表達(dá)式不需要。中的函數(shù)表達(dá)式和閉包都是極其有用的特性,利用它們可以實(shí)現(xiàn)很多功能。 1、遞歸 2、閉包 3、模仿塊級(jí)作用域 4、私有變量 5、小結(jié) 在JavaScript編程中,使用函數(shù)表達(dá)式可以無(wú)需對(duì)函數(shù)命名,從而實(shí)現(xiàn)動(dòng)態(tài)編程。匿名函數(shù)也稱...
摘要:前言之前發(fā)了一篇文章,寫了一些對(duì)于閉包的理解。現(xiàn)在補(bǔ)上閉包的應(yīng)用篇,很慚愧因?yàn)閲?yán)重的拖延癥一直拖到現(xiàn)在。本文主要分享一些常見的閉包用法和分析,也希望能增加對(duì)閉包的理解。 前言 之前發(fā)了一篇文章,寫了一些對(duì)于閉包的理解?,F(xiàn)在補(bǔ)上閉包的應(yīng)用篇,(很慚愧因?yàn)閲?yán)重的拖延癥一直拖到現(xiàn)在)。本文主要分享一些常見的閉包用法和分析,也希望能增加對(duì)閉包的理解。 簡(jiǎn)單回顧 在之前的文章里,講解了閉包的原理...
摘要:關(guān)于函數(shù)聲明他的一個(gè)重要特征就是函數(shù)聲明提升就是在執(zhí)行代碼之前會(huì)先讀取函數(shù)聲明這意味著可以把函數(shù)聲明放到調(diào)用他的語(yǔ)句的后面將聲明放到了后面關(guān)于函數(shù)表達(dá)式創(chuàng)建一個(gè)匿名函數(shù)然后賦值給一個(gè)變量函數(shù)體可以返回一個(gè)匿名函數(shù)返回的函數(shù)可以賦值給一個(gè)變量 關(guān)于函數(shù)聲明 他的一個(gè)重要特征就是函數(shù)聲明提升,就是在執(zhí)行代碼之前會(huì)先讀取函數(shù)聲明,這意味著可以把函數(shù)聲明放到調(diào)用他的語(yǔ)句的后面 sayHi();...
閱讀 1465·2021-09-10 11:27
閱讀 2414·2019-08-30 15:53
閱讀 1333·2019-08-30 13:10
閱讀 2981·2019-08-30 11:09
閱讀 1092·2019-08-29 17:23
閱讀 672·2019-08-29 17:05
閱讀 2951·2019-08-29 15:10
閱讀 2349·2019-08-29 13:22