javascript奇異的arguments分析
更新時(shí)間:2010年10月20日 11:51:03 作者:
在 Javascript 的函數(shù)中有個(gè)名為 arguments 的類數(shù)組對(duì)象。它看起來(lái)是那么的詭異而且名不經(jīng)傳,但眾多的 Javascript 庫(kù)都使用著它強(qiáng)大的功能。所以,它的特性需要每個(gè) Javascript 程序員去熟悉它。
在每個(gè)函數(shù)中,都有個(gè)名為 arguments 的變量,它以類似數(shù)組的形式保存了當(dāng)前調(diào)用的參數(shù)。而它實(shí)際上并不是個(gè)數(shù)組,使用 typeof arguments 語(yǔ)句嘗試會(huì)返回“object”(對(duì)象),所以它不能像 Array 一樣使用 push 和 pop 等方法。即便如此,仍然可以使用下標(biāo)以及長(zhǎng)度屬性(length)獲取它的值。
編寫靈活的函數(shù)
雖看起來(lái)名不經(jīng)傳,但的確 arguments 是非常有用的對(duì)象。比如,你可以讓函數(shù)處理不定數(shù)目的參數(shù)。在 Dean Edwards 寫的 base2 庫(kù)中,有個(gè)叫 format 的函數(shù)充分發(fā)揮了這一特性:
function format(string) {
var args = arguments;
var pattern = new RegExp("%([1-" + arguments.length + "])", "g");
return String(string).replace(pattern, function(match, index) {
return args[index];
});
};
這個(gè)函數(shù)實(shí)現(xiàn)了模板替換,你可以在要?jiǎng)討B(tài)替換的地方使用 %1 到 %9 標(biāo)記,然后其余的參數(shù)就會(huì)依次替換這些地方。例如:
format("And the %1 want to know whose %2 you %3", "papers", "shirt", "wear");上面的腳本就會(huì)返回
"And the papers want to know whose shirt you wear" 。在這里需要注意的是,即便在 format 函數(shù)定義中,我們僅定義了個(gè)名為 string 的參數(shù)。而 Javascript 不管函數(shù)自身定義的參數(shù)數(shù)量,它都允許我們向一個(gè)函數(shù)傳遞任意數(shù)量的參數(shù),并將這些參數(shù)值保存到被調(diào)用函數(shù)的 arguments 對(duì)象中。
轉(zhuǎn)換成實(shí)際數(shù)組
雖然 arguments 對(duì)象并不是真正意義上的 Javascript 數(shù)組,但是我們可以使用數(shù)組的 slice 方法將其轉(zhuǎn)換成數(shù)組,類似下面的代碼
var args = Array.prototype.slice.call(arguments);
這樣,數(shù)組變量 args 包含了所有 arguments 對(duì)象包含的值。
創(chuàng)建預(yù)置參數(shù)的函數(shù)
使用 arguments 對(duì)象能夠簡(jiǎn)短我們編寫的 Javascript 代碼量。下面有個(gè)名為 makeFunc 的函數(shù),它根據(jù)你提供的函數(shù)名稱以及其他任意數(shù)目的參數(shù),然后返回個(gè)匿名函數(shù)。此匿名函數(shù)被調(diào)用時(shí),合并的原先被調(diào)用的參數(shù),并交給指定的函數(shù)運(yùn)行然后返回其返回值。
function makeFunc() {
var args = Array.prototype.slice.call(arguments);
var func = args.shift();
return function() {
return func.apply(null, args.concat(Array.prototype.slice.call(arguments)));
};
}
makeFunc 的第一個(gè)參數(shù)指定需要調(diào)用的函數(shù)名稱(是的,在這個(gè)簡(jiǎn)單的例子中沒有錯(cuò)誤檢查),獲取以后從 args 中刪除。makeFunc 返回一個(gè)匿名函數(shù),它使用函數(shù)對(duì)象的(Function Object)apply 方法調(diào)用指定的函數(shù)。
apply 方法的第一個(gè)參數(shù)指定了作用域,基本上的作用域是被調(diào)用的函數(shù)。不過(guò)這樣在這個(gè)例子中看起來(lái)會(huì)有點(diǎn)復(fù)雜,所以我們將其設(shè)定成 null ;其第二個(gè)參數(shù)是個(gè)數(shù)組,它指定了其調(diào)用函數(shù)的參數(shù)。makeFunc 轉(zhuǎn)換其自身的 arguments 并連接匿名函數(shù)的 arguments,然后傳遞到被調(diào)用的函數(shù)。
有種情況就是總是要有個(gè)輸出的模板是相同的,為了節(jié)省每次是使用上面提到的 format 函數(shù)并指定重復(fù)的參數(shù),我們可以使用 makeFunc 這個(gè)工具。它將返回一個(gè)匿名函數(shù),并自動(dòng)生成已經(jīng)指定模板后的內(nèi)容:
var majorTom = makeFunc(format, "This is Major Tom to ground control. I'm %1.");
你可以像這樣重復(fù)指定 majorTom 函數(shù):
majorTom("stepping through the door");
majorTom("floating in a most peculiar way");
那么當(dāng)每次調(diào)用 majorTom 函數(shù)時(shí),它都會(huì)使用第一個(gè)指定的參數(shù)填寫已經(jīng)指定的模板。例如上述的代碼返回:
"This is Major Tom to ground control. I'm stepping through the door."
"This is Major Tom to ground control. I'm floating in a most peculiar way."
自引用的函數(shù)
您可能會(huì)認(rèn)為這很酷,先別急著高興,后面還有個(gè)更大的驚喜。它(arguments)還有個(gè)其他非常有用的屬性:callee 。arguments.callee 包含了當(dāng)前調(diào)用函數(shù)的被引用對(duì)象。那么我們?nèi)绾问褂眠@玩意做些的事情?arguments.callee 是個(gè)非常有用的調(diào)用自身的匿名函數(shù)。
下面有個(gè)名為 repeat 的函數(shù),它的參數(shù)需要個(gè)函數(shù)引用和兩個(gè)數(shù)字。第一個(gè)數(shù)字表示運(yùn)行的次數(shù),而第二個(gè)函數(shù)定義運(yùn)行的間隔時(shí)間(毫秒為單位)。下面是相關(guān)的代碼:
function repeat(fn, times, delay) {
return function() {
if(times-- > 0) {
fn.apply(null, arguments);
var args = Array.prototype.slice.call(arguments);
var self = arguments.callee;
setTimeout(function(){self.apply(null,args)}, delay);
}
};
}
repeat 函數(shù)使用 arguments.callee 獲得當(dāng)前引用,保存到 self 變量后,返回個(gè)匿名函數(shù)重新運(yùn)行原本被調(diào)用的函數(shù)。最后使用 setTimeout 以及配合個(gè)匿名函數(shù)實(shí)現(xiàn)延遲執(zhí)行。
作為個(gè)簡(jiǎn)單的說(shuō)明,比如會(huì)在通常的腳本中,編寫下面的提供個(gè)字符串并彈出個(gè)警告框的簡(jiǎn)單函數(shù):
function comms(s) {
alert(s);
}
好了,后來(lái)我改變了我的想法。我想編寫個(gè)“特殊版本”的函數(shù),它會(huì)重復(fù)三次運(yùn)行每次間隔兩秒。那么使用我的 repeat 函數(shù),就可以像這樣做到:
var somethingWrong = repeat(comms, 3, 2000);
somethingWrong("Can you hear me, major tom?");
結(jié)果就猶如預(yù)期的那樣,彈出了三次警告框每次延時(shí)兩秒。
最后,arguments 即便不會(huì)經(jīng)常被用到,甚至顯得有些詭異,但是它上述的那些驚艷的功能(不僅僅是這些!)值得你去了解它。
編寫靈活的函數(shù)
雖看起來(lái)名不經(jīng)傳,但的確 arguments 是非常有用的對(duì)象。比如,你可以讓函數(shù)處理不定數(shù)目的參數(shù)。在 Dean Edwards 寫的 base2 庫(kù)中,有個(gè)叫 format 的函數(shù)充分發(fā)揮了這一特性:
復(fù)制代碼 代碼如下:
function format(string) {
var args = arguments;
var pattern = new RegExp("%([1-" + arguments.length + "])", "g");
return String(string).replace(pattern, function(match, index) {
return args[index];
});
};
這個(gè)函數(shù)實(shí)現(xiàn)了模板替換,你可以在要?jiǎng)討B(tài)替換的地方使用 %1 到 %9 標(biāo)記,然后其余的參數(shù)就會(huì)依次替換這些地方。例如:
format("And the %1 want to know whose %2 you %3", "papers", "shirt", "wear");上面的腳本就會(huì)返回
"And the papers want to know whose shirt you wear" 。在這里需要注意的是,即便在 format 函數(shù)定義中,我們僅定義了個(gè)名為 string 的參數(shù)。而 Javascript 不管函數(shù)自身定義的參數(shù)數(shù)量,它都允許我們向一個(gè)函數(shù)傳遞任意數(shù)量的參數(shù),并將這些參數(shù)值保存到被調(diào)用函數(shù)的 arguments 對(duì)象中。
轉(zhuǎn)換成實(shí)際數(shù)組
雖然 arguments 對(duì)象并不是真正意義上的 Javascript 數(shù)組,但是我們可以使用數(shù)組的 slice 方法將其轉(zhuǎn)換成數(shù)組,類似下面的代碼
復(fù)制代碼 代碼如下:
var args = Array.prototype.slice.call(arguments);
這樣,數(shù)組變量 args 包含了所有 arguments 對(duì)象包含的值。
創(chuàng)建預(yù)置參數(shù)的函數(shù)
使用 arguments 對(duì)象能夠簡(jiǎn)短我們編寫的 Javascript 代碼量。下面有個(gè)名為 makeFunc 的函數(shù),它根據(jù)你提供的函數(shù)名稱以及其他任意數(shù)目的參數(shù),然后返回個(gè)匿名函數(shù)。此匿名函數(shù)被調(diào)用時(shí),合并的原先被調(diào)用的參數(shù),并交給指定的函數(shù)運(yùn)行然后返回其返回值。
復(fù)制代碼 代碼如下:
function makeFunc() {
var args = Array.prototype.slice.call(arguments);
var func = args.shift();
return function() {
return func.apply(null, args.concat(Array.prototype.slice.call(arguments)));
};
}
makeFunc 的第一個(gè)參數(shù)指定需要調(diào)用的函數(shù)名稱(是的,在這個(gè)簡(jiǎn)單的例子中沒有錯(cuò)誤檢查),獲取以后從 args 中刪除。makeFunc 返回一個(gè)匿名函數(shù),它使用函數(shù)對(duì)象的(Function Object)apply 方法調(diào)用指定的函數(shù)。
apply 方法的第一個(gè)參數(shù)指定了作用域,基本上的作用域是被調(diào)用的函數(shù)。不過(guò)這樣在這個(gè)例子中看起來(lái)會(huì)有點(diǎn)復(fù)雜,所以我們將其設(shè)定成 null ;其第二個(gè)參數(shù)是個(gè)數(shù)組,它指定了其調(diào)用函數(shù)的參數(shù)。makeFunc 轉(zhuǎn)換其自身的 arguments 并連接匿名函數(shù)的 arguments,然后傳遞到被調(diào)用的函數(shù)。
有種情況就是總是要有個(gè)輸出的模板是相同的,為了節(jié)省每次是使用上面提到的 format 函數(shù)并指定重復(fù)的參數(shù),我們可以使用 makeFunc 這個(gè)工具。它將返回一個(gè)匿名函數(shù),并自動(dòng)生成已經(jīng)指定模板后的內(nèi)容:
復(fù)制代碼 代碼如下:
var majorTom = makeFunc(format, "This is Major Tom to ground control. I'm %1.");
你可以像這樣重復(fù)指定 majorTom 函數(shù):
復(fù)制代碼 代碼如下:
majorTom("stepping through the door");
majorTom("floating in a most peculiar way");
那么當(dāng)每次調(diào)用 majorTom 函數(shù)時(shí),它都會(huì)使用第一個(gè)指定的參數(shù)填寫已經(jīng)指定的模板。例如上述的代碼返回:
復(fù)制代碼 代碼如下:
"This is Major Tom to ground control. I'm stepping through the door."
"This is Major Tom to ground control. I'm floating in a most peculiar way."
自引用的函數(shù)
您可能會(huì)認(rèn)為這很酷,先別急著高興,后面還有個(gè)更大的驚喜。它(arguments)還有個(gè)其他非常有用的屬性:callee 。arguments.callee 包含了當(dāng)前調(diào)用函數(shù)的被引用對(duì)象。那么我們?nèi)绾问褂眠@玩意做些的事情?arguments.callee 是個(gè)非常有用的調(diào)用自身的匿名函數(shù)。
下面有個(gè)名為 repeat 的函數(shù),它的參數(shù)需要個(gè)函數(shù)引用和兩個(gè)數(shù)字。第一個(gè)數(shù)字表示運(yùn)行的次數(shù),而第二個(gè)函數(shù)定義運(yùn)行的間隔時(shí)間(毫秒為單位)。下面是相關(guān)的代碼:
復(fù)制代碼 代碼如下:
function repeat(fn, times, delay) {
return function() {
if(times-- > 0) {
fn.apply(null, arguments);
var args = Array.prototype.slice.call(arguments);
var self = arguments.callee;
setTimeout(function(){self.apply(null,args)}, delay);
}
};
}
repeat 函數(shù)使用 arguments.callee 獲得當(dāng)前引用,保存到 self 變量后,返回個(gè)匿名函數(shù)重新運(yùn)行原本被調(diào)用的函數(shù)。最后使用 setTimeout 以及配合個(gè)匿名函數(shù)實(shí)現(xiàn)延遲執(zhí)行。
作為個(gè)簡(jiǎn)單的說(shuō)明,比如會(huì)在通常的腳本中,編寫下面的提供個(gè)字符串并彈出個(gè)警告框的簡(jiǎn)單函數(shù):
復(fù)制代碼 代碼如下:
function comms(s) {
alert(s);
}
好了,后來(lái)我改變了我的想法。我想編寫個(gè)“特殊版本”的函數(shù),它會(huì)重復(fù)三次運(yùn)行每次間隔兩秒。那么使用我的 repeat 函數(shù),就可以像這樣做到:
復(fù)制代碼 代碼如下:
var somethingWrong = repeat(comms, 3, 2000);
somethingWrong("Can you hear me, major tom?");
結(jié)果就猶如預(yù)期的那樣,彈出了三次警告框每次延時(shí)兩秒。
最后,arguments 即便不會(huì)經(jīng)常被用到,甚至顯得有些詭異,但是它上述的那些驚艷的功能(不僅僅是這些!)值得你去了解它。
您可能感興趣的文章:
- js的隱含參數(shù)(arguments,callee,caller)使用方法
- js中arguments的用法(實(shí)例講解)
- javascript arguments 傳遞給函數(shù)的隱含參數(shù)
- javascript下arguments,caller,callee,call,apply示例及理解
- js arguments.callee的應(yīng)用代碼
- js arguments對(duì)象應(yīng)用介紹
- javascript arguments使用示例
- javascript 瀏覽器判斷 綁定事件 arguments 轉(zhuǎn)換數(shù)組 數(shù)組遍歷
- js中arguments,caller,callee,apply的用法小結(jié)
- js arguments,jcallee caller用法總結(jié)
- 深入解析JavaScript中的arguments對(duì)象
相關(guān)文章
JS實(shí)現(xiàn)獲取GIF總幀數(shù)的方法詳解
如何通過(guò)js在上傳前就拿到它的總幀數(shù)來(lái)判斷呢?本文就跟大家分享一種解決方案,并將其封裝成插件發(fā)布至npm倉(cāng)庫(kù),快跟隨小編一起學(xué)習(xí)一下吧2022-05-05關(guān)于自定義Egg.js的請(qǐng)求級(jí)別日志詳解
這篇文章主要給大家介紹了關(guān)于自定義Egg.js的請(qǐng)求級(jí)別日志的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12JS特效實(shí)現(xiàn)圖片自動(dòng)播放并可控的效果
這篇文章主要介紹了JS代碼實(shí)現(xiàn)圖片自動(dòng)播放并可控的效果,需要的朋友可以參考下2015-07-07javascript獲取以及設(shè)置光標(biāo)位置
本文介紹了javascript獲取以及設(shè)置光標(biāo)位置的方法,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02