手動實現call、apply和bind

如果沒有傳參,那麼this默認指向的window 

let a = {
    value: 1
}

function parent(sex, weight) {
    this.name = '1'
    this.age = 12
    this.sex = sex ? sex : null
    this.weight = weight ? weight : null
    console.log(123)
}

call的實現   call接受參數的方式  call(obj, params1, params2, ....)

Function.prototype.myCall = function (context) {
    let currentObj = context ? context : window // 這裏就是傳入的第一個參數
    currentObj.fn = this // 將parent函數存起來,parent調用的myCall,此時this指向的就是該方法
    let arg = [...arguments].slice(1) // 將參數中除了第一個之後的全部存起來,第一個就是上下文要用的這個對象
    console.log(...arg)
    currentObj.fn(...arg) // 將參數傳入,此時調用fn的是currentObj 即爲傳入的對象a,所以parent中的this會指向a
    delete context.fn // 將函數刪除
}
// 測試代碼
// parent.myCall(a, 'mingzi', 'nianling')
// console.log(a);

apply的實現  apply接受參數的方式  call(obj, [params1, params2, ....])

Function.prototype.myApply = function (context) {
    let currentObj = context ? context : window // 這裏就是傳入的第一個參數
    currentObj.fn = this // 將parent函數存起來,parent調用的myCall,此時this指向的就是該方法
    console.log(arguments) // [{value: 1}, ['張三', '12']]
    if(arguments[1]) {
        currentObj.fn(...arguments[1])
    } else {
        currentObj.fn()
    }
    delete currentObj.fn
}
// 測試代碼
// parent.myApply(a, ['boy', '50'])
// console.log(a)

 bind()實現  

// 實現bind()方法 調用bind()必須是一個函數   可以通過new修改this  new的優先級最高 bind()可以將參數分兩次傳遞進來
Function.prototype.myBind = function (context) {
    if(typeof this !== "function") { // 如果不是函數則直接拋出
        throw new TypeError('Error')
    }
    let self = this // 保存this,即爲parent
    let arg = [...arguments].slice(1) // 將參數中除了第一個之後的全部存起來
    // bind()返回的是一個函數,所以可以使用new,並且會修改this的指向
    return function F() {
        if(this instanceof F) { // 如果new執行此時即爲true
            return new self(...arg, ...arguments) // 返回new parent(第一次傳遞的參數, 第二次傳遞的參數) =》  arguments是執行返回的函數時的參數
        }
        return self.apply(context, [...arg, ...arguments]) // 如果沒有執行new  那麼直接執行parent,通過apply會將this執行最初傳進來的對象a
    }
}

// 測試代碼

let bindResult = parent.myBind(a, 'women')
let result = new bindResult('666')
console.log(result);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章