完全理解JS--arguments

什么是arguments?

它是JS的一個內(nèi)置對象沿后,常被人們所忽略,但實際上確很重要镊尺,JS不像JAVA是顯示傳遞參數(shù)朦佩,JS傳的是形參,可以傳也可以不傳庐氮,若方法里沒有寫參數(shù)卻傳入了參數(shù)语稠,該如何拿到參數(shù)呢,答案就是arguments了弄砍,在一些插件里通常這樣使用仙畦。

每一個函數(shù)都有一個arguments對象,它包括了函數(shù)所要調(diào)的參數(shù)输枯,通常我們把它當(dāng)作數(shù)組使用议泵,用它的length得到參數(shù)數(shù)量,但它卻不是數(shù)組桃熄,使用instanceof查看下先口,若使用push添加數(shù)據(jù)將報錯型奥,代碼如下:

(function(){
    console.log([] instanceof Array)
    console.log(arguments instanceof Array)
    if(arguments.push) arguments.push('test')
})()

創(chuàng)建一個靈活的格式化函數(shù)

上面說了arguments可以使用函數(shù)使用數(shù)量不定的參數(shù),下面看看它的一個實際應(yīng)用:

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];
  });   
};
format("And the %1 want to know whose %2 you %3", "papers", "shirt", "wear");

這里我借用了別人的一個例子碉京,一個模板字符串厢汹,可以使用%1到%9等9個占位符,然后提供9個參數(shù)給這些占位符谐宙,最后替換生成真正的字符串烫葬。
上面的代碼返回:“And the papers want to know whose shirt you wear”

把a(bǔ)rguments轉(zhuǎn)換成一個真正的數(shù)組

有時我們希望將它轉(zhuǎn)換成真正的數(shù)組使用,可以使用下面的代碼:

var args = Array.prototype.slice.call(arguments);

現(xiàn)在args就是一個標(biāo)準(zhǔn)的js數(shù)組了凡蜻,可以使用數(shù)組的標(biāo)準(zhǔn)方法了搭综。

通過arguments對象封裝format函數(shù)

arguments允許我們?nèi)?zhí)行所有類型的js方法,下面通過一個makeFunc函數(shù)划栓,展示了函數(shù)允許我們?nèi)ヌ峁┮粋€函數(shù)引用和這個函數(shù)的所有參數(shù)兑巾,它將返回一個匿名函數(shù)去調(diào)用你規(guī)定的函數(shù)(就是閉包),也提供了匿名函數(shù)調(diào)用時所附帶的參數(shù)忠荞。

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)));
  };
}

第一個arguments給makeFunc提供了你調(diào)用的函數(shù)的引用蒋歌,它將第一個參數(shù)從arguments數(shù)組里移除,然后makeFunc返回了一個匿名函數(shù)去運(yùn)行規(guī)定的方法委煤。
apply的第一個參數(shù)是函數(shù)調(diào)用的范圍堂油,主要是函數(shù)內(nèi)部關(guān)聯(lián)部分所指向的,這里設(shè)為null碧绞,它的arguments是一個數(shù)組府框,即匿名函數(shù)調(diào)用時傳入的參數(shù),匿名函數(shù)將傳入的參數(shù)串聯(lián)到原參數(shù)對象args里組成完整的匿名函數(shù)所需要參數(shù)头遭。

你需要輸出一個模板寓免,總是相同位置的字符發(fā)生改變癣诱,這樣就可以使用makeFunc去生成一個模板函數(shù)计维,傳入不同的參數(shù)多次調(diào)用生成不同的內(nèi)容了。

var func = makeFunc(format, "I like %1 not %2.");
func("js", "java");   
func("java", "python");

每一次調(diào)用func撕予,它會同時調(diào)用format函數(shù)和第一個arguments鲫惶,然后填充已有的模板。
執(zhí)行結(jié)果如下:

"I like js not java."
"I like java not python."

這樣封裝format是不是很酷实抡,不過arguments還有更多驚喜欠母。

ES6重構(gòu)makeFunc

es6中不推薦使用arguments,那就要使用es6中提供的語法...rest
Rest就是為解決傳入的參數(shù)數(shù)量不一定吆寨, rest parameter(Rest 參數(shù)) 本身就是數(shù)組赏淌,數(shù)組的相關(guān)的方法都可以用。
下面是重構(gòu)后的代碼:

function format(string, ...args) {
    var pattern = new RegExp("%([1-" + args.length + "])", "g");
    return String(string).replace(pattern, function(match, index) {
      return args[index-1];
    });   
};
format("And the %1 want to know whose %2 you %3", "papers", "shirt", "wear");

function makeFunc(...args) {
    var func = args.shift();
    return function(...rest) {
      return func.apply(null, args.concat(rest));
    };
}

var func = makeFunc(format, "I like %1 not %2.");
func("js", "java");
func("java", "python");

創(chuàng)建引用自身的函數(shù)

arguments.callee包括了一個函數(shù)的引用去創(chuàng)建一個arguments對象啄清,它能讓一個匿名函數(shù)很方便的指向本身六水。
下面的Repeat是一個承載了一個函數(shù)引用和兩個數(shù)字的函數(shù),第一個數(shù)字是調(diào)用次數(shù),第二個是間隔時間掷贾,單位毫秒睛榄。

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方法從變量self獲取一個引用,指向運(yùn)行原始指令的函數(shù)想帅。這樣场靴,匿名函數(shù)就可以再次調(diào)用自身,看看下面的調(diào)用:

var somethingWrong = repeat(function(s){console.log(s)}, 3, 2000);
somethingWrong("Can you hear me, major tom?");

ES6重構(gòu)repeat

現(xiàn)在已經(jīng)不推薦使用arguments.callee()港准;
原因:訪問 arguments 是個很昂貴的操作旨剥,因為它是個很大的對象,每次遞歸調(diào)用時都需要重新創(chuàng)建浅缸。影響現(xiàn)代瀏覽器的性能泞边,還會影響閉包。
其實很簡單疗杉,給內(nèi)部函數(shù)一個名字即可:

function repeat(fn, times, delay) {
    return function _fn(...args) {
      if(times-- > 0) {
        fn.apply(null, args);
        // 現(xiàn)在arguments.callee被棄用了, 給內(nèi)部函數(shù)一個名字即可:
        setTimeout(function(){_fn.apply(null, args)}, delay);
      }
    };
  }

var somethingWrong = repeat((s)=>{console.log(s)}, 3, 2000);
somethingWrong("Can you hear me, major tom?");

可以看到somethingWrong函數(shù)的結(jié)果被打印了3次阵谚,每隔2秒。
arguments還有很多驚喜烟具,非常值得我們?nèi)チ私馍沂玻瑲g迎加入前端交流群。
學(xué)習(xí)交流朝聋,請加群:867541922

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嗡午,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子冀痕,更是在濱河造成了極大的恐慌荔睹,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件言蛇,死亡現(xiàn)場離奇詭異僻他,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)腊尚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進(jìn)店門吨拗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人婿斥,你說我怎么就攤上這事劝篷。” “怎么了民宿?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵娇妓,是天一觀的道長。 經(jīng)常有香客問我活鹰,道長哈恰,這世上最難降的妖魔是什么坟桅? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮蕊蝗,結(jié)果婚禮上仅乓,老公的妹妹穿的比我還像新娘。我一直安慰自己蓬戚,他們只是感情好夸楣,可當(dāng)我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著子漩,像睡著了一般豫喧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上幢泼,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天紧显,我揣著相機(jī)與錄音,去河邊找鬼缕棵。 笑死孵班,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的招驴。 我是一名探鬼主播篙程,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼别厘!你這毒婦竟也來了虱饿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤触趴,失蹤者是張志新(化名)和其女友劉穎氮发,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冗懦,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡爽冕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了批狐。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扇售。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡前塔,死狀恐怖嚣艇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情华弓,我是刑警寧澤食零,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站寂屏,受9級特大地震影響贰谣,放射性物質(zhì)發(fā)生泄漏娜搂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一吱抚、第九天 我趴在偏房一處隱蔽的房頂上張望百宇。 院中可真熱鬧,春花似錦秘豹、人聲如沸携御。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽啄刹。三九已至,卻和暖如春凄贩,著一層夾襖步出監(jiān)牢的瞬間誓军,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工疲扎, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留昵时,地道東北人。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓椒丧,卻偏偏與公主長得像债查,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子瓜挽,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容