使用模擬實現的方式探究call 和 apply 的原理

使用模擬實現的方式探究call 和 apply 的原理

call

做用:javascript

call() 方法就是在使用一個指定 this 值和若干個指定的參數值的前提下調用某個函數或者方法。
var foo = {
    value : 1
}
function bar() {
    console.log(this.value)
}
// 若是不對this進行綁定執行bar() 會返回undefined
bar.call(foo) // 1

也就是說call()改變了 this 的指向到了 foojava

下面進行一下模擬實現

試想當調用 call 的時候,也就是相似於數組

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

這樣就把 this 指向到了 foo 上,可是這樣給 foo 對象加了一個屬性,有些瑕疵,不過沒關係,執行完刪除這個屬性就能夠完美實現了。app

也就是說步驟能夠是這樣:函數

  1. 將函數設爲對象的屬性
  2. 執行這個函數
  3. 刪除這個函數

下面就試着去實現一下:this

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

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

可是這樣有一個小缺陷就是call() 不只能指定this到函數,還能傳入給定參數執行函數好比:prototype

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

特別要注意的一點是,傳入的參數的數量是不肯定的,因此咱們要使用arguments 對象,取出除去第一個以外的參數,放到一個數組裏:code

Function.prototype.call2 = function(context) {
    context.fn = this // this 也就是調用call的函數
    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

還有一點須要注意的是,若是不傳入參數,默認指向爲 window,因此最終版代碼:對象

Function.prototype.call2 = function(context) {
    var context = context || window
    context.fn = this // this 也就是調用call的函數
    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 方法的實現相似,只不過是若是有參數,以數組形式進行傳遞,直接上代碼:ip

Function.prototype.apply2 = function(context) {
    var context = context || window
    context.fn = this // this 也就是調用apply的函數
    var result
    // 判斷是否有第二個參數
    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
相關文章
相關標籤/搜索