1. 程式人生 > 實用技巧 >js實現call、aplly、bind

js實現call、aplly、bind

首先定義一下測試資料

const test = function(age, sex) {
    console.log(this.name, age, sex, 'test')
}

const person = {
    name: '毛小星'
}
  • 實現call方法
    下面將自定義的call方法寫在Function的原型物件上
Function.prototype.my_call = function(context) {
    if (typeof this !== "function") {
        throw new Error(`${this} is not a function`)
    }

    const args = [...arguments].slice(1) // 獲取除了context的所有引數
    
    context = context || window

    context.fn = this // 將函式賦值給 call 傳入物件的屬性

    const result = context.fn(...args) // 執行函式並把結果存起來

    delete context.fn // 刪除屬性
    return result // 返回函式執行結果
}

test(24, 'man', 'call')
test.my_call(person, 24, 'man', 'call')

測試一下

可以看到繫結成功了

  • 實現apply方法
Function.prototype.my_apply = function(context) {
    if (typeof this !== "function") {
        throw new Error(`${this} is not a function`)
    }

    let result

    context = context || window

    context.fn = this

    result = arguments[1] ? context.fn(...arguments[1]) : context.fn() // 如果傳入陣列引數就帶參執行,否則直接執行函式

    delete context.fn // 刪除屬性
    return result // 返回函式執行結果
}

test(24, 'man', 'apply')
test.my_apply(person, [24, 'man', 'apply'])

  • 實現bind方法
Function.prototype.my_bind = function(context) {
    if (typeof this !== "function") {
        throw new Error(`${this} is not a function`)
    }

    let args = [...arguments].slice(1) // 獲取實際引數

    const me = this

    return function fn() { // 返回閉包函式
        return me.apply(
            this instanceof fn ? this : context, // 判斷上下文
            args.concat(...arguments) // 拼接引數
        )
    }
}
test(24, 'man', 'bind')
test.my_bind(person, 24)('man', 'bind')