最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript 匿名函數(shù)(anonymous function)與閉包(closure)

 更新時間:2011年10月04日 20:14:24   投稿:mdxy-dxy  
JavaScript 匿名函數(shù)(anonymous function)與閉包(closure) ,學(xué)習(xí)js的朋友可以參考下。

引入
匿名函數(shù)
閉包
變量作用域
函數(shù)外部訪問函數(shù)內(nèi)部的局部變量
用閉包實現(xiàn)私有成員
引入
閉包是用匿名函數(shù)來實現(xiàn)。閉包就是一個受到保護(hù)的變量空間,由內(nèi)嵌函數(shù)生成。“保護(hù)變量”的思想在幾乎所有的編程語言中都能看到。

先看下 JavaScript 作用域:
JavaScript 具有函數(shù)級的作用域。這意味著,不能在函數(shù)外部訪問定義在函數(shù)內(nèi)部的變量。
JavaScript 的作用域又是詞法性質(zhì)的(lexically scoped)。這意味著,函數(shù)運行在定義它的作用域中,而不是在調(diào)用它的作用域中。這是 JavaScript 的一大特色,將在后面說明。
把這兩個因素結(jié)合在一起,就能通過把變量包裹在匿名函數(shù)中而對其加以保護(hù)。你可以這樣創(chuàng)建類的私有變量:

var baz; 
(function() { 
var foo = 10; 
var bar = 2; 
baz = function() { 
return foo * bar; 
}; 
})(); 
baz(); 

盡管在匿名函數(shù)外執(zhí)行,但 baz 仍然可以訪問 foo 和 bar。

說明:

1,第 1 行,baz 是全局變量;

2,第 3 ~第 9 行,定義一個匿名函數(shù);

3,第 4 和 5 行,foo 和 bar 是匿名函數(shù)內(nèi)的局部變量;第 6 ~ 8 行,在匿名函數(shù)內(nèi)定義一個匿名函數(shù),并將其賦值給全局變量 baz;

4,第 10 行,調(diào)用 baz。若改成 "alert(baz());",將顯示 20;

5,按理說,在匿名函數(shù)外不能訪問 foo 和 bar,但是現(xiàn)在可以。

在說明閉包前,先了解一下匿名函數(shù)。

匿名函數(shù)
匿名函數(shù)是指那些無需定義函數(shù)名的函數(shù)。匿名函數(shù)與 Lambda 表達(dá)式(拉姆達(dá)表達(dá)式)是一回事。唯一的不同——語法形式不同。Lambda 表達(dá)式更進(jìn)一步。本質(zhì)上,它們的作用都是:產(chǎn)生方法——內(nèi)聯(lián)方法,也就是說,省去函數(shù)定義,直接寫函數(shù)體。

Lambda 表達(dá)式一般形式:

(input parameters) => {statement;}
其中:

參數(shù)列表,可以有多個、一個或者無參數(shù)。參數(shù)可以隱式或者顯式定義。
表達(dá)式或者語句塊,也就是函數(shù)體。
上面代碼,第 6 ~ 8 行,沒有函數(shù)名,是個匿名函數(shù),采用 Lambda 表達(dá)式,嚴(yán)格意義上,雖然語法有差異,但目的一樣。


示例1:

var baz1 = function() { 
var foo = 10; 
var bar = 2; 
return foo * bar; 
}; 
function mutil() { 
var foo = 10; 
var bar = 2; 
return foo * bar; 
}; 
alert(baz1()); 
var baz2 = mutil(); 
alert(baz2); 

說明:

1,baz1 與 baz2 完全一樣,但 baz1 與 baz2 相比,省去了函數(shù)定義,直接函數(shù)體——看上去多簡約。

閉包
變量作用域
示例2:函數(shù)內(nèi)部可以訪問全局變量。

var baz = 10; 
function foo() { 
alert(baz); 
} 
foo(); 

這是可以。

示例3:函數(shù)外部不能訪問函數(shù)內(nèi)部的局部變量。

function foo() { 
var bar = 20; 
} 
alert(bar); 

這會報錯。

另外,函數(shù)內(nèi)部聲明變量時,一定要使用 var 關(guān)鍵字,否則,聲明的是一個全局變量。

示例4:

function foo() { 
bar = 20; 
} 
alert(bar); 

 函數(shù)外部訪問函數(shù)內(nèi)部的局部變量
實際情況,需要我們從函數(shù)外部獲得函數(shù)內(nèi)部的局部變量。先看示例5。

示例5:

function foo() { 
var a = 10; 
function bar() { 
a *= 2; 
} 
bar(); 
return a; 
} 
var baz = foo(); 
alert(baz); 

a 定義在 foo 內(nèi),bar 可以訪問,因為 bar 也定義在 foo 內(nèi)。現(xiàn)在,如何讓 bar 在 foo 外部被調(diào)用?

示例6:

function foo() { 
var a = 10; 
function bar() { 
a *= 2; 
return a; 
} 
return bar; 
} 
var baz = foo(); 
alert(baz()); 
alert(baz()); 
alert(baz()); 

var blat = foo(); 
alert(blat()); 

說明:

1,現(xiàn)在可以從外部訪問 a;
2,JavaScript 的作用域是詞法性的。a 是運行在定義它的 foo 中,而不是運行在調(diào)用 foo 的作用域中。 只要 bar 被定義在 foo 中,它就能訪問 foo 中定義的變量 a,即使 foo 的執(zhí)行已經(jīng)結(jié)束。也就是說,按理,"var baz = foo()" 執(zhí)行后,foo 已經(jīng)執(zhí)行結(jié)束,a 應(yīng)該不存在了,但之后再調(diào)用 baz 發(fā)現(xiàn),a 依然存在。這就是 JavaScript 特色之一——運行在定義,而不是運行的調(diào)用。

其中, "var baz = foo()" 是一個 bar 函數(shù)的引用;"var blat= foo()" 是另一個 bar 函數(shù)引用。

用閉包實現(xiàn)私有成員
現(xiàn)在,需要創(chuàng)建一個只能在對象內(nèi)部訪問的變量。用閉包再適合不過,因為通過閉包你可以創(chuàng)建只允許特定函數(shù)訪問的變量,而且這些變量在這些函數(shù)的各次調(diào)用間依然存在。

為了創(chuàng)建私有屬性,你需要在構(gòu)造函數(shù)的作用域中定義相關(guān)變量。這些變量可以被定義于該作用域中的所有函數(shù)訪問,包括那些特權(quán)方法。

示例7:

var Book = function(newIsbn, newTitle, newAuthor) { 
// 私有屬性 
var isbn, title, author; 
// 私有方法 
function checkIsbn(isbn) { 
// TODO 
} 
// 特權(quán)方法 
this.getIsbn = function() { 
return isbn; 
}; 
this.setIsbn = function(newIsbn) { 
if (!checkIsbn(newIsbn)) throw new Error('Book: Invalid ISBN.'); 
isbn = newIsbn; 
}; 
this.getTitle = function() { 
return title; 
}; 
this.setTitle = function(newTitle) { 
title = newTitle || 'No title specified.'; 
}; 
this.getAuthor = function() { 
return author; 
}; 
this.setAuthor = function(newAuthor) { 
author = newAuthor || 'No author specified.'; 
}; 
// 構(gòu)造器代碼 
this.setIsbn(newIsbn); 
this.setTitle(newTitle); 
this.setAuthor(newAuthor); 
}; 

// 共有、非特權(quán)方法 
Book.prototype = { 
display: function() { 
// TODO 
} 
}; 

說明:

1,用 var 聲明變量 isbn、title 和 author,而不是 this,意味著它們只存在 Book 構(gòu)造器中。checkIsbn 函數(shù)也是,因為它們是私有的;

2,訪問私有變量和方法的方法只需聲明在 Book 中即可。這些方法稱為特權(quán)方法。因為,它們是公共方法,但卻能訪問私有變量和私有方法,像 getIsbn、setIsbn、getTitle、setTitle、getAuthor、setAuthor(取值器和構(gòu)造器)。

3,為了能在對象外部訪問這些特權(quán)方法,這些方法前邊加了 this 關(guān)鍵字。因為這些方法定義在 Book 構(gòu)造器的作用域里,所以它們能夠訪問私有變量 isbn、title 和 author。但在這些特權(quán)方法里引用 isbn、title 和 author 變量時,沒有使用 this 關(guān)鍵字,而是直接引用。因為它們不是公開的。

4,任何不需要直接訪問私有變量的方法,像 Book.prototype 中聲明的,如 display。它不需要直接訪問私有變量,而是通過 get*、set* 簡介訪問。

5,這種方式創(chuàng)建的對象可以具有真正私有的變量。其他人不能直接訪問 Book 對象的任何內(nèi)部數(shù)據(jù),只能通過賦值器和。這樣一切盡在掌握。

但這種方式的缺點是:

“門戶大開型”對象創(chuàng)建模式中,所有方法都創(chuàng)建在原型 prototype 對象中,因此不管生成多少對象實例,這些方法在內(nèi)存中只有一份。
而采用本節(jié)的做法,沒生成一個新的對象實例,都將為每個私有方法(如,checkIsbn)和特權(quán)方法(如,getIsbn、setIsbn、getTitle、setTitle、getAuthor、setAuthor)生成一個新的副本。
因此,本節(jié)方法,只適于用在真正需要私有成員的場合。另外,這種方式也不利于繼承。

相關(guān)文章

  • 編寫高質(zhì)量JavaScript代碼的基本要點

    編寫高質(zhì)量JavaScript代碼的基本要點

    編寫高質(zhì)量JavaScript代碼的基本要點分享給大家,感興趣的小伙伴們可以參考一下
    2016-03-03
  • JavaScript檢測彈出窗口是否已經(jīng)關(guān)閉的方法

    JavaScript檢測彈出窗口是否已經(jīng)關(guān)閉的方法

    這篇文章主要介紹了JavaScript檢測彈出窗口是否已經(jīng)關(guān)閉的方法,涉及javascript中window屬性的closed屬性的使用技巧,需要的朋友可以參考下
    2015-03-03
  • 微信小程序?qū)崿F(xiàn)select下拉框

    微信小程序?qū)崿F(xiàn)select下拉框

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)select下拉框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • Javascript DOM的簡介,節(jié)點和獲取元素詳解

    Javascript DOM的簡介,節(jié)點和獲取元素詳解

    下面小編就為大家分享一篇詳談DOM的簡介,節(jié)點和獲取元素,具有非常好的參考價值,一起跟隨小編過來看看吧,希望對大家有所幫助
    2021-11-11
  • 通過實例解析js可枚舉屬性與不可枚舉屬性

    通過實例解析js可枚舉屬性與不可枚舉屬性

    這篇文章主要介紹了通過實例解析js可枚舉屬性與不可枚舉屬性,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-12-12
  • JS排序之冒泡排序詳解

    JS排序之冒泡排序詳解

    這篇文章主要為大家詳細(xì)介紹了JS冒泡排序的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • 淺談javascript中replace()方法

    淺談javascript中replace()方法

    這篇文章主要介紹了淺談javascript中replace()方法,replace函數(shù)方法是返回根據(jù)正則表達(dá)式進(jìn)行文字替換后的字符串的復(fù)制,需要的朋友可以參考下
    2015-11-11
  • 微信小程序按鈕巧妙用法

    微信小程序按鈕巧妙用法

    這篇文章主要介紹了微信小程序按鈕巧妙用法,按鈕組件功能比?HTML?中的?button?按鈕豐富,通過?open-type?屬性可以調(diào)用微信提供的各種功能(客服、轉(zhuǎn)發(fā)、獲取用戶授權(quán)、獲取用戶信息等),需要的朋友可以參考下
    2022-12-12
  • webpack4 SplitChunks實現(xiàn)代碼分隔詳解

    webpack4 SplitChunks實現(xiàn)代碼分隔詳解

    這篇文章主要介紹了webpack4 SplitChunks實現(xiàn)代碼分隔詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • uniapp項目實踐之全局公共組件樣式及方法使用示例詳解

    uniapp項目實踐之全局公共組件樣式及方法使用示例詳解

    這篇文章主要為大家介紹了uniapp項目實踐之全局公共組件樣式及方法使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09

最新評論

富阳市| 巴林右旗| 蓝田县| 松原市| 泽普县| 文山县| 读书| 富川| 浦北县| 赣榆县| 台江县| 遂宁市| 桐梓县| 禹城市| 长海县| 丹江口市| 仙游县| 本溪| 嘉鱼县| 卓尼县| 集贤县| 阳东县| 临朐县| 囊谦县| 昌平区| 磐石市| 东至县| 平阴县| 湾仔区| 昌平区| 泗阳县| 衢州市| 宜兰市| 五家渠市| 承德市| 康平县| 新昌县| 新化县| 忻城县| 莱州市| 沂南县|