Js:模擬實現(xiàn)call函數(shù)

call

call() 方法在使用一個指定的 this 值和若干個指定的參數(shù)值的前提下調(diào)用某個函數(shù)或方法。
舉個栗子:

var foo ={
  value:1
}
function bar(){
  console.log(this.value)
}
bar.call(foo);//1

需要注意兩點:

  • call改變了this的指向肾胯,指向到foo;
  • 調(diào)用了bar函數(shù)

模擬實現(xiàn)第一步

試想當調(diào)用 call 的時候毕荐,把 foo 對象改造成如下:

//我們希望把bar里的this指向foo艳馒;那我們把bar放進foo里面能實現(xiàn)這個效果
var foo = {
    value: 1,
    bar: function() {
        console.log(this.value)
    }
};
foo.bar(); // 1

這樣我們就實現(xiàn)了this指向foo员寇;
但是我們給foo添加了一個屬性才實現(xiàn)了這個效果蝶锋,那我們用完可以刪除掉這個屬性扳缕。
模擬步驟可分為:

// 第一步
foo.fn = bar
// 第二步
foo.fn()
// 第三步
delete foo.fn
//fn 是對象的屬性名别威,反正最后也要刪除它,所以起成什么都無所謂庸毫。

根據(jù)這個思路衫樊,我們可以嘗試著去寫第一版的 call2 函數(shù):

Function.Prototype.call2 = function(context){
  //獲取調(diào)用call2的函數(shù)利花,用this
  context.fn = this;
  context.fn();
  delete context.fn;

}
// 測試一下
var foo = {
    value: 1
};

function bar() {
    console.log(this.value);
}

bar.call2(foo); // 1

這樣我們就輕松模擬了call指定this指向的功能;

模擬實現(xiàn)第二步

call 函數(shù)還能給定參數(shù)執(zhí)行函數(shù)臀栈。
舉個例子:

var foo = {
    value: 1
};

function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}

bar.call(foo, 'Cherry', 18);
// Cherry
// 18
// 1

注意:傳入的參數(shù)并不確定挠乳,這可咋辦?

不急盟蚣,我們可以從 Arguments 對象中取值,取出第二個到最后一個參數(shù)屎开,然后放到一個數(shù)組里马靠。

比如這樣:

// 以上個例子為例,此時的arguments為:
// arguments = {
//      0: foo,
//      1: 'Cherry',
//      2: 18,
//      length: 3
// }
// 因為arguments是類數(shù)組對象逞度,所以可以用for循環(huán)
var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
    args.push('arguments[' + i + ']');
}

// 執(zhí)行后 args為 ["arguments[1]", "arguments[2]", "arguments[3]"]

不定長的參數(shù)問題解決了妙啃,我們接著要把這個參數(shù)數(shù)組放到要執(zhí)行的函數(shù)的參數(shù)里面去。

eval('context.fn(' + args +')')

所以我們的第二版克服了兩個大問題茁瘦,代碼如下:

// 第二版
Function.prototype.call2 = function(context) {
    context.fn = this;
    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }
    eval('context.fn(' + args +')');
    delete context.fn;
}

// 測試一下
var foo = {
    value: 1
};

function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}

bar.call2(foo, 'Cherry', 18); 
// Cherry
// 18
// 1

模擬實現(xiàn)第三步

模擬代碼已經(jīng)完成 80%甜熔,還有兩個小點要注意:

1.this 參數(shù)可以傳 null,當為 null 的時候腔稀,視為指向 window
2.函數(shù)是可以有返回值的!
解決方法:

// 第三版
Function.prototype.call2 = function (context) {
    var context = context || window;
    context.fn = this;

    var args = [];
    for(var i = 1, len = arguments.length; i < len; i++) {
        args.push('arguments[' + i + ']');
    }

    var result = eval('context.fn(' + args +')');

    delete context.fn
    return result;
}

// 測試一下
var value = 2;

var obj = {
    value: 1
}

function bar(name, age) {
    console.log(this.value);
    return {
        value: this.value,
        name: name,
        age: age
    }
}

bar.call(null); // 2

console.log(bar.call2(obj, 'Cherry', 18));
// 1
// Object {
//    value: 1,
//    name: 'Cherry',
//    age: 18
// }

到此淡喜,我們完成了 call 的模擬實現(xiàn)炼团。

文章非原創(chuàng)疏尿,有侵權(quán)請告知,文章出處:
https://github.com/mqyqingfeng/Blog/issues/11

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锌俱,一起剝皮案震驚了整個濱河市敌呈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吭练,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件线脚,死亡現(xiàn)場離奇詭異浑侥,居然都是意外死亡晰绎,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門伶选,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人仰税,你說我怎么就攤上這事⊥旅啵” “怎么了河绽?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長纹笼。 經(jīng)常有香客問我苟跪,道長,這世上最難降的妖魔是什么削咆? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任蠢笋,我火速辦了婚禮,結(jié)果婚禮上昨寞,老公的妹妹穿的比我還像新娘。我一直安慰自己援岩,他們只是感情好,可當我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布羽峰。 她就那樣靜靜地躺著梅屉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪坯汤。 梳的紋絲不亂的頭發(fā)上搀愧,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天,我揣著相機與錄音搓幌,去河邊找鬼。 笑死溉愁,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的叉钥。 我是一名探鬼主播,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼枫疆,長吁一口氣:“原來是場噩夢啊……” “哼敷鸦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起值依,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤愿险,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辆亏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鳖目,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡领迈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了衷蜓。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片薪贫。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡瞧省,死狀恐怖鳍贾,靈堂內(nèi)的尸體忽然破棺而出交洗,到底是詐尸還是另有隱情,我是刑警寧澤咆爽,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布斗埂,位于F島的核電站凫海,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏行贪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一崭捍、第九天 我趴在偏房一處隱蔽的房頂上張望啰脚。 院中可真熱鬧,春花似錦晾咪、人聲如沸贮配。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至圆存,卻和暖如春仇哆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背油讯。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工陌兑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人饿凛。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓软驰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親杀狡。 傳聞我的和親對象是個殘疾皇子贰镣,可洞房花燭夜當晚...
    茶點故事閱讀 43,554評論 2 349

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