JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記9 js函數(shù)(下)
更新時(shí)間:2012年10月11日 14:56:30 作者:
函數(shù)是一種對(duì)象,擁有一般對(duì)象具有的所有特征,除了函數(shù)可以有自己的屬性和方法外,還可以做為一個(gè)引用類型的值去使用,實(shí)際上我們前面的例子中已經(jīng)有過將函數(shù)作為一個(gè)對(duì)象屬性的值,又比如函數(shù)也可以作為另一個(gè)函數(shù)的參數(shù)或者返回值,異步處理中的回調(diào)函數(shù)就是一個(gè)典型的用法
再接著看函數(shù)——具有魔幻色彩的對(duì)象。
9、作為值的函數(shù)
在一般的編程語言中,如果要將函數(shù)作為值來使用,需要使用類似函數(shù)指針或者代理的方式來實(shí)現(xiàn),但是在ECMAScript中,函數(shù)是一種對(duì)象,擁有一般對(duì)象具有的所有特征,除了函數(shù)可以有自己的屬性和方法外,還可以做為一個(gè)引用類型的值去使用,實(shí)際上我們前面的例子中已經(jīng)有過將函數(shù)作為一個(gè)對(duì)象屬性的值,又比如函數(shù)也可以作為另一個(gè)函數(shù)的參數(shù)或者返回值,異步處理中的回調(diào)函數(shù)就是一個(gè)典型的用法。
var name = 'linjisong';
var person = {name:'oulinhai'};
function getName(){
return this.name;
}
function sum(){
var total = 0,
l = arguments.length;
for(; l; l--)
{
total += arguments[l-1];
}
return total;
}
// 定義調(diào)用函數(shù)的函數(shù),使用函數(shù)作為形式參數(shù)
function callFn(fn,arguments,scope){
arguments = arguments || [];
scope = scope || window;
return fn.apply(scope, arguments);
}
// 調(diào)用callFn,使用函數(shù)作為實(shí)際參數(shù)
console.info(callFn(getName));//linjisong
console.info(callFn(getName,'',person));//oulinhai
console.info(callFn(sum,[1,2,3,4]));//10
再看一個(gè)使用函數(shù)作為返回值的典型例子,這個(gè)例子出自于原書第5章:
function createComparisonFunction(propertyName) {
return function(object1, object2){
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 < value2){
return -1;
} else if (value1 > value2){
return 1;
} else {
return 0;
}
};
}
var data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29}];
data.sort(createComparisonFunction("name"));
console.info(data[0].name); //Nicholas
data.sort(createComparisonFunction("age"));
console.info(data[0].name); //Zachary
10、閉包(Closure)
閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。對(duì)象是帶函數(shù)的數(shù)據(jù),而閉包是帶數(shù)據(jù)的函數(shù)。
首先閉包是一個(gè)函數(shù),然后閉包是一個(gè)帶有數(shù)據(jù)的函數(shù),那么,帶有的是什么數(shù)據(jù)呢?我們往上看看函數(shù)作為返回值的例子,返回的是一個(gè)匿名函數(shù),而隨著這個(gè)匿名函數(shù)被返回,外層的createComparisonFunction()函數(shù)代碼也就執(zhí)行完成,按照前面的結(jié)論,外層函數(shù)的執(zhí)行環(huán)境會(huì)被彈出棧并銷毀,但是接下來的排序中可以看到在返回的匿名函數(shù)中依舊可以訪問處于createComparisonFunction()作用域中的propertyName,這說明盡管createComparisonFunction()對(duì)應(yīng)的執(zhí)行環(huán)境已經(jīng)被銷毀,但是這個(gè)執(zhí)行環(huán)境相對(duì)應(yīng)的活動(dòng)對(duì)象并沒有被銷毀,而是作為返回的匿名函數(shù)的作用域鏈中的一個(gè)對(duì)象了,換句話說,返回的匿名函數(shù)構(gòu)成的閉包帶有的數(shù)據(jù)就是:外層函數(shù)相應(yīng)的活動(dòng)對(duì)象。由于活動(dòng)對(duì)象的屬性(也就是外層函數(shù)中定義的變量、函數(shù)和形式參數(shù))會(huì)隨著外層函數(shù)的代碼執(zhí)行而變化,因此最終返回的匿名函數(shù)構(gòu)成的閉包帶有的數(shù)據(jù)是外層函數(shù)代碼執(zhí)行完成之后的活動(dòng)對(duì)象,也就是最終狀態(tài)。
希望好好理解一下上面這段話,反復(fù)理解一下。雖然我已經(jīng)盡我所能描述的更易于理解一些,但是閉包的概念還是有些抽象,下面看一個(gè)例子,這個(gè)例子來自原書第7章:
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}
var funcs = createFunctions();
for (var i=0,l=funcs.length; i < l; i++){
console.info(funcs[i]());//每一個(gè)函數(shù)都輸出10
}
這里由于閉包帶有的數(shù)據(jù)是createFunctions相應(yīng)的活動(dòng)對(duì)象的最終狀態(tài),而在createFunctions()代碼執(zhí)行完成之后,活動(dòng)對(duì)象的屬性i已經(jīng)變成10,因此在下面的調(diào)用中每一個(gè)返回的函數(shù)都輸出10了,要處理這種問題,可以采用匿名函數(shù)作用域來保存狀態(tài):
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = (function(num){
return function(){
return num;
};
})(i);
}
return result;
}
將每一個(gè)狀態(tài)都使用一個(gè)立即調(diào)用的匿名函數(shù)來保存(保存在匿名函數(shù)相應(yīng)的活動(dòng)對(duì)象中),然后在最終返回的函數(shù)被調(diào)用時(shí),就可以通過閉包帶有的數(shù)據(jù)(相應(yīng)的匿名函數(shù)活動(dòng)對(duì)象中的數(shù)據(jù))來正確訪問了,輸出結(jié)果變成0,1,...9。當(dāng)然,這樣做,就創(chuàng)建了10個(gè)閉包,在性能上會(huì)有較大影響,因此建議不要濫用閉包,另外,由于閉包會(huì)保存其它執(zhí)行環(huán)境的活動(dòng)對(duì)象作為自身作用域鏈中的一環(huán),這也可能會(huì)造成內(nèi)存泄露。盡管閉包存在效率和內(nèi)存的隱患,但是閉包的功能是在太強(qiáng)大,下面就來看看閉包的應(yīng)用——首先讓我們回到昨天所說的函數(shù)綁定方法bind()。
(1)函數(shù)綁定與柯里化(currying)
A、再看this,先看一個(gè)例子(原書第22章):
<button id='my-btn' title='Button'>Hello</button>
<script type="text/javascript">
var handler = {
title:'Event',
handleClick:function(event){
console.info(this.title);
}
};
var btn = document.getElementById('my-btn');//獲取頁(yè)面按鈕
btn.onclick = handler.handleClick;//給頁(yè)面按鈕添加事件處理函數(shù)
</script>
如果你去點(diǎn)擊“Hello”按鈕,控制臺(tái)打印的是什么呢?竟然是Button,而不是期望中的Event,原因就是這里在點(diǎn)擊按鈕的時(shí)候,處理函數(shù)內(nèi)部屬性this指向了按鈕對(duì)象??梢允褂瞄]包來解決這個(gè)問題:
btn.onclick = function(event){
handler.handleClick(event);//形成一個(gè)閉包,調(diào)用函數(shù)的就是對(duì)象handler了,函數(shù)內(nèi)部屬性this指向handler對(duì)象,因此會(huì)輸出Event}
B、上面的解決方案并不優(yōu)雅,在ES5中新增了函數(shù)綁定方法bind(),我們使用這個(gè)方法來改寫一下:
if(!Function.prototype.bind){//bind為ES5中新增,為了保證運(yùn)行正常,在不支持的瀏覽器上添加這個(gè)方法
Function.prototype.bind = function(scope){
var that = this;//調(diào)用bind()方法的函數(shù)對(duì)象
return function(){
that.apply(scope, arguments);//使用apply方法,指定that函數(shù)對(duì)象的內(nèi)部屬性this
};
};
}
btn.onclick = handler.handleClick.bind(handler);//使用bind()方法時(shí)只需要使用一條語句即可
這里添加的bind()方法中,主要技術(shù)也是創(chuàng)建一個(gè)閉包,保存綁定時(shí)的參數(shù)作為函數(shù)實(shí)際調(diào)用時(shí)的內(nèi)部屬性this。如果你不確定是瀏覽器本身就支持bind()還是我們這里的bind()起了作用,你可以把特性檢測(cè)的條件判斷去掉,然后換個(gè)方法名稱試試。
C、上面對(duì)函數(shù)使用bind()方法時(shí),只使用了第一個(gè)參數(shù),如果調(diào)用bind()時(shí)傳入多個(gè)參數(shù)并且將第2個(gè)參數(shù)開始作為函數(shù)實(shí)際調(diào)用時(shí)的參數(shù),那我們就可以給函數(shù)綁定默認(rèn)參數(shù)了。
if(!Function.prototype.bind){
Function.prototype.bind = function(scope){
var that = this;//調(diào)用bind()方法的函數(shù)對(duì)象
var args = Array.prototype.slice.call(arguments,1);//從第2個(gè)參數(shù)開始組成的參數(shù)數(shù)組
return function(){
var innerArgs = Array.prototype.slice.apply(arguments);
that.apply(scope, args.concat(innerArgs));//使用apply方法,指定that函數(shù)對(duì)象的內(nèi)部屬性this,并且填充綁定時(shí)傳入的參數(shù)
};
};
}
D、柯里化:在上面綁定時(shí),第一個(gè)參數(shù)都是用來設(shè)置函數(shù)調(diào)用時(shí)的內(nèi)部屬性this,如果把所有綁定時(shí)的參數(shù)都作為預(yù)填的參數(shù),則稱之為函數(shù)柯里化。
if(!Function.prototype.curry){
Function.prototype.curry = function(){
var that = this;//調(diào)用curry()方法的函數(shù)對(duì)象
var args = Array.prototype.slice.call(arguments);//預(yù)填參數(shù)數(shù)組
return function(){
var innerArgs = Array.prototype.slice.apply(arguments);//實(shí)際調(diào)用時(shí)參數(shù)數(shù)組
that.apply(this, args.concat(innerArgs));//使用apply方法,并且加入預(yù)填的參數(shù)
};
};
}
(2)利用閉包緩存
還記得前面使用遞歸實(shí)現(xiàn)斐波那契數(shù)列的函數(shù)嗎?使用閉包緩存來改寫一下:
var fibonacci = (function(){//使用閉包緩存,遞歸
var cache = [];
function f(n){
if(1 == n || 2 == n){
return 1;
}else{
cache[n] = cache[n] || (f(n-1) + f(n-2));
return cache[n];
}
}
return f;
})();
var f2 = function(n){//不使用閉包緩存,直接遞歸
if(1 == n || 2 == n){
return 1;
}else{
return f2(n-1) + f2(n-2);
}
};
下面是測(cè)試代碼以及我機(jī)器上的運(yùn)行結(jié)果:
var test = function(n){
var start = new Date().getTime();
console.info(fibonacci(n));
console.info(new Date().getTime() - start);
start = new Date().getTime();
console.info(f2(n));
console.info(new Date().getTime() - start);
};
test(10);//55,2,55,2
test(20);//6765,1,6765,7
test(30);//832040,2,832040,643
可以看到,n值越大,使用緩存計(jì)算的優(yōu)勢(shì)越明顯。作為練習(xí),你可以嘗試自己修改一下計(jì)算階乘的函數(shù)。
(3)模仿塊級(jí)作用域
在ECMAScript中,有語句塊,但是卻沒有相應(yīng)的塊級(jí)作用域,但我們可以使用閉包來模仿塊級(jí)作用域,一般格式為:
(function(){
//這里是塊語句
})();
上面這種模式也稱為立即調(diào)用的函數(shù)表達(dá)式,這種模式已經(jīng)非常流行了,特別是由于jQuery源碼使用這種方式而大規(guī)模普及起來。
閉包還有很多有趣的應(yīng)用,比如模仿私有變量和私有函數(shù)、模塊模式等,這里先不討論了,在深入理解對(duì)象之后再看這些內(nèi)容。
關(guān)于函數(shù),就先說這些,在網(wǎng)上也有很多非常棒的文章,有興趣的可以自己搜索一下閱讀。這里推薦一篇文章,《JavaScript高級(jí)程序設(shè)計(jì)(第3版)》譯者的一篇譯文:命名函數(shù)表達(dá)式探秘。
9、作為值的函數(shù)
在一般的編程語言中,如果要將函數(shù)作為值來使用,需要使用類似函數(shù)指針或者代理的方式來實(shí)現(xiàn),但是在ECMAScript中,函數(shù)是一種對(duì)象,擁有一般對(duì)象具有的所有特征,除了函數(shù)可以有自己的屬性和方法外,還可以做為一個(gè)引用類型的值去使用,實(shí)際上我們前面的例子中已經(jīng)有過將函數(shù)作為一個(gè)對(duì)象屬性的值,又比如函數(shù)也可以作為另一個(gè)函數(shù)的參數(shù)或者返回值,異步處理中的回調(diào)函數(shù)就是一個(gè)典型的用法。
復(fù)制代碼 代碼如下:
var name = 'linjisong';
var person = {name:'oulinhai'};
function getName(){
return this.name;
}
function sum(){
var total = 0,
l = arguments.length;
for(; l; l--)
{
total += arguments[l-1];
}
return total;
}
// 定義調(diào)用函數(shù)的函數(shù),使用函數(shù)作為形式參數(shù)
function callFn(fn,arguments,scope){
arguments = arguments || [];
scope = scope || window;
return fn.apply(scope, arguments);
}
// 調(diào)用callFn,使用函數(shù)作為實(shí)際參數(shù)
console.info(callFn(getName));//linjisong
console.info(callFn(getName,'',person));//oulinhai
console.info(callFn(sum,[1,2,3,4]));//10
再看一個(gè)使用函數(shù)作為返回值的典型例子,這個(gè)例子出自于原書第5章:
復(fù)制代碼 代碼如下:
function createComparisonFunction(propertyName) {
return function(object1, object2){
var value1 = object1[propertyName];
var value2 = object2[propertyName];
if (value1 < value2){
return -1;
} else if (value1 > value2){
return 1;
} else {
return 0;
}
};
}
var data = [{name: "Zachary", age: 28}, {name: "Nicholas", age: 29}];
data.sort(createComparisonFunction("name"));
console.info(data[0].name); //Nicholas
data.sort(createComparisonFunction("age"));
console.info(data[0].name); //Zachary
10、閉包(Closure)
閉包是指有權(quán)訪問另一個(gè)函數(shù)作用域中的變量的函數(shù)。對(duì)象是帶函數(shù)的數(shù)據(jù),而閉包是帶數(shù)據(jù)的函數(shù)。
首先閉包是一個(gè)函數(shù),然后閉包是一個(gè)帶有數(shù)據(jù)的函數(shù),那么,帶有的是什么數(shù)據(jù)呢?我們往上看看函數(shù)作為返回值的例子,返回的是一個(gè)匿名函數(shù),而隨著這個(gè)匿名函數(shù)被返回,外層的createComparisonFunction()函數(shù)代碼也就執(zhí)行完成,按照前面的結(jié)論,外層函數(shù)的執(zhí)行環(huán)境會(huì)被彈出棧并銷毀,但是接下來的排序中可以看到在返回的匿名函數(shù)中依舊可以訪問處于createComparisonFunction()作用域中的propertyName,這說明盡管createComparisonFunction()對(duì)應(yīng)的執(zhí)行環(huán)境已經(jīng)被銷毀,但是這個(gè)執(zhí)行環(huán)境相對(duì)應(yīng)的活動(dòng)對(duì)象并沒有被銷毀,而是作為返回的匿名函數(shù)的作用域鏈中的一個(gè)對(duì)象了,換句話說,返回的匿名函數(shù)構(gòu)成的閉包帶有的數(shù)據(jù)就是:外層函數(shù)相應(yīng)的活動(dòng)對(duì)象。由于活動(dòng)對(duì)象的屬性(也就是外層函數(shù)中定義的變量、函數(shù)和形式參數(shù))會(huì)隨著外層函數(shù)的代碼執(zhí)行而變化,因此最終返回的匿名函數(shù)構(gòu)成的閉包帶有的數(shù)據(jù)是外層函數(shù)代碼執(zhí)行完成之后的活動(dòng)對(duì)象,也就是最終狀態(tài)。
希望好好理解一下上面這段話,反復(fù)理解一下。雖然我已經(jīng)盡我所能描述的更易于理解一些,但是閉包的概念還是有些抽象,下面看一個(gè)例子,這個(gè)例子來自原書第7章:
復(fù)制代碼 代碼如下:
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}
var funcs = createFunctions();
for (var i=0,l=funcs.length; i < l; i++){
console.info(funcs[i]());//每一個(gè)函數(shù)都輸出10
}
這里由于閉包帶有的數(shù)據(jù)是createFunctions相應(yīng)的活動(dòng)對(duì)象的最終狀態(tài),而在createFunctions()代碼執(zhí)行完成之后,活動(dòng)對(duì)象的屬性i已經(jīng)變成10,因此在下面的調(diào)用中每一個(gè)返回的函數(shù)都輸出10了,要處理這種問題,可以采用匿名函數(shù)作用域來保存狀態(tài):
復(fù)制代碼 代碼如下:
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = (function(num){
return function(){
return num;
};
})(i);
}
return result;
}
將每一個(gè)狀態(tài)都使用一個(gè)立即調(diào)用的匿名函數(shù)來保存(保存在匿名函數(shù)相應(yīng)的活動(dòng)對(duì)象中),然后在最終返回的函數(shù)被調(diào)用時(shí),就可以通過閉包帶有的數(shù)據(jù)(相應(yīng)的匿名函數(shù)活動(dòng)對(duì)象中的數(shù)據(jù))來正確訪問了,輸出結(jié)果變成0,1,...9。當(dāng)然,這樣做,就創(chuàng)建了10個(gè)閉包,在性能上會(huì)有較大影響,因此建議不要濫用閉包,另外,由于閉包會(huì)保存其它執(zhí)行環(huán)境的活動(dòng)對(duì)象作為自身作用域鏈中的一環(huán),這也可能會(huì)造成內(nèi)存泄露。盡管閉包存在效率和內(nèi)存的隱患,但是閉包的功能是在太強(qiáng)大,下面就來看看閉包的應(yīng)用——首先讓我們回到昨天所說的函數(shù)綁定方法bind()。
(1)函數(shù)綁定與柯里化(currying)
A、再看this,先看一個(gè)例子(原書第22章):
復(fù)制代碼 代碼如下:
<button id='my-btn' title='Button'>Hello</button>
<script type="text/javascript">
var handler = {
title:'Event',
handleClick:function(event){
console.info(this.title);
}
};
var btn = document.getElementById('my-btn');//獲取頁(yè)面按鈕
btn.onclick = handler.handleClick;//給頁(yè)面按鈕添加事件處理函數(shù)
</script>
如果你去點(diǎn)擊“Hello”按鈕,控制臺(tái)打印的是什么呢?竟然是Button,而不是期望中的Event,原因就是這里在點(diǎn)擊按鈕的時(shí)候,處理函數(shù)內(nèi)部屬性this指向了按鈕對(duì)象??梢允褂瞄]包來解決這個(gè)問題:
復(fù)制代碼 代碼如下:
btn.onclick = function(event){
handler.handleClick(event);//形成一個(gè)閉包,調(diào)用函數(shù)的就是對(duì)象handler了,函數(shù)內(nèi)部屬性this指向handler對(duì)象,因此會(huì)輸出Event}
B、上面的解決方案并不優(yōu)雅,在ES5中新增了函數(shù)綁定方法bind(),我們使用這個(gè)方法來改寫一下:
復(fù)制代碼 代碼如下:
if(!Function.prototype.bind){//bind為ES5中新增,為了保證運(yùn)行正常,在不支持的瀏覽器上添加這個(gè)方法
Function.prototype.bind = function(scope){
var that = this;//調(diào)用bind()方法的函數(shù)對(duì)象
return function(){
that.apply(scope, arguments);//使用apply方法,指定that函數(shù)對(duì)象的內(nèi)部屬性this
};
};
}
btn.onclick = handler.handleClick.bind(handler);//使用bind()方法時(shí)只需要使用一條語句即可
這里添加的bind()方法中,主要技術(shù)也是創(chuàng)建一個(gè)閉包,保存綁定時(shí)的參數(shù)作為函數(shù)實(shí)際調(diào)用時(shí)的內(nèi)部屬性this。如果你不確定是瀏覽器本身就支持bind()還是我們這里的bind()起了作用,你可以把特性檢測(cè)的條件判斷去掉,然后換個(gè)方法名稱試試。
C、上面對(duì)函數(shù)使用bind()方法時(shí),只使用了第一個(gè)參數(shù),如果調(diào)用bind()時(shí)傳入多個(gè)參數(shù)并且將第2個(gè)參數(shù)開始作為函數(shù)實(shí)際調(diào)用時(shí)的參數(shù),那我們就可以給函數(shù)綁定默認(rèn)參數(shù)了。
復(fù)制代碼 代碼如下:
if(!Function.prototype.bind){
Function.prototype.bind = function(scope){
var that = this;//調(diào)用bind()方法的函數(shù)對(duì)象
var args = Array.prototype.slice.call(arguments,1);//從第2個(gè)參數(shù)開始組成的參數(shù)數(shù)組
return function(){
var innerArgs = Array.prototype.slice.apply(arguments);
that.apply(scope, args.concat(innerArgs));//使用apply方法,指定that函數(shù)對(duì)象的內(nèi)部屬性this,并且填充綁定時(shí)傳入的參數(shù)
};
};
}
D、柯里化:在上面綁定時(shí),第一個(gè)參數(shù)都是用來設(shè)置函數(shù)調(diào)用時(shí)的內(nèi)部屬性this,如果把所有綁定時(shí)的參數(shù)都作為預(yù)填的參數(shù),則稱之為函數(shù)柯里化。
復(fù)制代碼 代碼如下:
if(!Function.prototype.curry){
Function.prototype.curry = function(){
var that = this;//調(diào)用curry()方法的函數(shù)對(duì)象
var args = Array.prototype.slice.call(arguments);//預(yù)填參數(shù)數(shù)組
return function(){
var innerArgs = Array.prototype.slice.apply(arguments);//實(shí)際調(diào)用時(shí)參數(shù)數(shù)組
that.apply(this, args.concat(innerArgs));//使用apply方法,并且加入預(yù)填的參數(shù)
};
};
}
(2)利用閉包緩存
還記得前面使用遞歸實(shí)現(xiàn)斐波那契數(shù)列的函數(shù)嗎?使用閉包緩存來改寫一下:
復(fù)制代碼 代碼如下:
var fibonacci = (function(){//使用閉包緩存,遞歸
var cache = [];
function f(n){
if(1 == n || 2 == n){
return 1;
}else{
cache[n] = cache[n] || (f(n-1) + f(n-2));
return cache[n];
}
}
return f;
})();
var f2 = function(n){//不使用閉包緩存,直接遞歸
if(1 == n || 2 == n){
return 1;
}else{
return f2(n-1) + f2(n-2);
}
};
下面是測(cè)試代碼以及我機(jī)器上的運(yùn)行結(jié)果:
復(fù)制代碼 代碼如下:
var test = function(n){
var start = new Date().getTime();
console.info(fibonacci(n));
console.info(new Date().getTime() - start);
start = new Date().getTime();
console.info(f2(n));
console.info(new Date().getTime() - start);
};
test(10);//55,2,55,2
test(20);//6765,1,6765,7
test(30);//832040,2,832040,643
可以看到,n值越大,使用緩存計(jì)算的優(yōu)勢(shì)越明顯。作為練習(xí),你可以嘗試自己修改一下計(jì)算階乘的函數(shù)。
(3)模仿塊級(jí)作用域
在ECMAScript中,有語句塊,但是卻沒有相應(yīng)的塊級(jí)作用域,但我們可以使用閉包來模仿塊級(jí)作用域,一般格式為:
復(fù)制代碼 代碼如下:
(function(){
//這里是塊語句
})();
上面這種模式也稱為立即調(diào)用的函數(shù)表達(dá)式,這種模式已經(jīng)非常流行了,特別是由于jQuery源碼使用這種方式而大規(guī)模普及起來。
閉包還有很多有趣的應(yīng)用,比如模仿私有變量和私有函數(shù)、模塊模式等,這里先不討論了,在深入理解對(duì)象之后再看這些內(nèi)容。
關(guān)于函數(shù),就先說這些,在網(wǎng)上也有很多非常棒的文章,有興趣的可以自己搜索一下閱讀。這里推薦一篇文章,《JavaScript高級(jí)程序設(shè)計(jì)(第3版)》譯者的一篇譯文:命名函數(shù)表達(dá)式探秘。
您可能感興趣的文章:
- JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記13 ECMAScript5新特性
- JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記12 js正則表達(dá)式
- JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記11 內(nèi)建js對(duì)象
- JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記10 再訪js對(duì)象
- JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記8 js函數(shù)(中)
- JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記7 js函數(shù)(上)
- JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記6 初識(shí)js對(duì)象
- JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記5 js語句
- JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記4 js運(yùn)算符和操作符
- JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記3 js簡(jiǎn)單數(shù)據(jù)類型
- JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記2 js基礎(chǔ)語法
- JavaScript高級(jí)程序設(shè)計(jì)(第3版)學(xué)習(xí)筆記 概述
相關(guān)文章
JavaScript中setTimeout和setInterval函數(shù)的傳參及調(diào)用
這篇文章主要介紹了JavaScript中setTimeout和setInterval函數(shù)的傳參及調(diào)用,著兩個(gè)函數(shù)可以把要執(zhí)行的代碼在設(shè)定的一個(gè)時(shí)間點(diǎn)插入js引擎維護(hù)的一個(gè)代碼隊(duì)列中,需要的朋友可以參考下2016-03-03jquery和javascript的區(qū)別(常用方法比較)
jquery 就對(duì)javascript的一個(gè)擴(kuò)展,封裝,就是讓javascript更好用,更簡(jiǎn)單,為了說明區(qū)別,下面與大家分享下JavaScript 與JQuery 常用方法比較2013-07-07基于dom編程中 動(dòng)態(tài)創(chuàng)建與刪除元素的使用
本篇文章小編將為大家介紹,基于dom編程中動(dòng)態(tài)創(chuàng)建與刪除元素的使用,有需要的朋友可以參考一下2013-04-04JavaScript中Array 對(duì)象相關(guān)的幾個(gè)方法
JavaScript中Array 對(duì)象相關(guān)的幾個(gè)方法...2006-12-12