使用模擬實(shí)現(xiàn)的方式探究call 和 apply 的原理

使用模擬實(shí)現(xiàn)的方式探究call 和 apply 的原理

call

作用:

call() 方法就是在使用一個(gè)指定 this 值和若干個(gè)指定的參數(shù)值的前提下調(diào)用某個(gè)函數(shù)或者方法。

var foo = {
    value : 1
}
function bar() {
    console.log(this.value)
}
// 如果不對(duì)this進(jìn)行綁定執(zhí)行bar() 會(huì)返回undefined
bar.call(foo) // 1

也就是說(shuō)call()改變了 this 的指向到了 foo 。

下面進(jìn)行一下模擬實(shí)現(xiàn)

試想當(dāng)調(diào)用 call 的時(shí)候,也就是類似于

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

這樣就把 this 指向到了 foo 上,但是這樣給 foo 對(duì)象加了一個(gè)屬性,有些瑕疵,不過(guò)不要緊,執(zhí)行完刪除這個(gè)屬性就可以完美實(shí)現(xiàn)了。

也就是說(shuō)步驟可以是這樣:

  1. 將函數(shù)設(shè)為對(duì)象的屬性
  2. 執(zhí)行這個(gè)函數(shù)
  3. 刪除這個(gè)函數(shù)

下面就試著去實(shí)現(xiàn)一下:

Function.prototype.call2 = function(context) {
    context.fn = this // this 也就是調(diào)用call的函數(shù)
    var result = context.fn()
    delete context.fn()
    return result
}

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

但是這樣有一個(gè)小缺陷就是call() 不僅能指定this到函數(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, 'black', '18')
// black
// 18
// 1

特別要注意的一點(diǎn)是,傳入的參數(shù)的數(shù)量是不確定的,所以我們要使用arguments 對(duì)象,取出除去第一個(gè)之外的參數(shù),放到一個(gè)數(shù)組里:

Function.prototype.call2 = function(context) {
    context.fn = this // this 也就是調(diào)用call的函數(shù)
    var args = [...arguments].slice(1)
    var result = context.fn(...args)
    delete context.fn()
    return result
}

var foo = {
    value: 1
}
function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}
bar.call2(foo, 'black', '18') // black 18 1

還有一點(diǎn)需要注意的是,如果不傳入?yún)?shù),默認(rèn)指向?yàn)?window,所以最終版代碼:

Function.prototype.call2 = function(context) {
    var context = context || window
    context.fn = this // this 也就是調(diào)用call的函數(shù)
    var args = [...arguments].slice(1)
    var result = context.fn(...args)
    delete context.fn()
    return result
}
var value = 1
function bar() {
    console.log(this.value)
}
bar.call2()

apply

apply的方法和 call 方法的實(shí)現(xiàn)類似,只不過(guò)是如果有參數(shù),以數(shù)組形式進(jìn)行傳遞,直接上代碼:

Function.prototype.apply2 = function(context) {
    var context = context || window
    context.fn = this // this 也就是調(diào)用apply的函數(shù)
    var result
    // 判斷是否有第二個(gè)參數(shù)
    if(arguments[1]) {
        result = context.fn(...arguments[1])
    } else {
        result = context.fn()
    }
    delete context.fn()
    return result
}

var foo = {
    value: 1
}
function bar(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value);
}
bar.apply2(foo, ['black', '18']) // black 18 1
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • 函數(shù)和對(duì)象 1、函數(shù) 1.1 函數(shù)概述 函數(shù)對(duì)于任何一門(mén)語(yǔ)言來(lái)說(shuō)都是核心的概念。通過(guò)函數(shù)可以封裝任意多條語(yǔ)句,而且...
    道無(wú)虛閱讀 4,926評(píng)論 0 5
  • 本文首發(fā)我的個(gè)人博客:前端小密圈,評(píng)論交流送1024邀請(qǐng)碼,嘿嘿嘿??。 來(lái)自朋友去某信用卡管家的做的一道面試題,用...
    微醺歲月閱讀 3,352評(píng)論 4 32
  • 朱大大發(fā)來(lái)的照片,讓我又回想起在北京的日子。人只有不停地去做,不要停下來(lái)才能無(wú)限接近目標(biāo)。接下來(lái)的兩個(gè)星期公司強(qiáng)行...
    葉子卷閱讀 342評(píng)論 0 2
  • 書(shū)桌 放滿 想給你的 信箋 電臺(tái) 播放著 那首 你最喜歡 的旋律 想你 若隱若現(xiàn) 的笑臉 恨不能 每天 都能夠 看...
    簡(jiǎn)言筆下閱讀 198評(píng)論 0 0

友情鏈接更多精彩內(nèi)容