手寫call、apply、bind函數


手寫call、apply、bind函數

一、總結

一句話總結:

其實都不用記,用腦子去推就好了:核心點是為傳進來的對象context添加fn這個函數屬性,然后context就可以執行fn這個函數,也就是改變了fn的this指向

 

Function.prototype.myCall = function(context) {
    if (typeof context === "undefined" || context === null) {
        context = window
    }
   //context=context||window  和上面的代碼一樣
    context.fn = this
    const args = [...arguments].slice(1)
    const result = context.fn(...args)
    delete context.fn
    return result
}

 

 

二、手寫call,apply,bind函數

轉自或參考:手寫call,apply,bind函數_Java_白天不懂夜的黑-CSDN博客
https://blog.csdn.net/qq_37288477/article/details/87884518

涉及面試題

call,apply,bind函數內部實現是怎樣的?

考慮兩點:

  • 第一個參數為undefined或null的時候,那么會轉變為window
  • 改變了this執行,讓新的對象可以執行該函數。

call

Function.prototype.myCall = function(context) {
    if (typeof context === "undefined" || context === null) {
        context = window
    }
   //context=context||window  和上面的代碼一樣
    context.fn = this
    const args = [...arguments].slice(1)
    const result = context.fn(...args)
    delete context.fn
    return result
}

實現分析

  • 首先context為可選參數,如果不傳的話默認上下文是window
  • 接下來給content創建一個fn屬性,並將值設置為需要調用的函數
  • 因為call可以傳入多個參數作為調用函數的參數,所有需要將參數剝離出來
  • 然后調用函數並將對象上的函數刪除

apply

apply和call實現類似,不同的就是參數的處理


Function.prototype.myApply = function(context) {
    if (typeof this !== 'function') {
        throw new TypeError('Error')
    }
    context = context || window
    context.fn = this
    let result
    if (arguments[1]) {
        result = context.fn(...arguments[1])
    } else {
        result = context.fn()
    }
    delete context.fn
    return result
}

bind

因為bind轉換后的函數可以作為構造函數使用,此時this應該指向構造出的實例,而不是bind綁定的第一個參數


Function.prototype.myBind = function(context) {
    if (typeof this !== 'function') {
        throw new TypeError('Error')
    }
    //返回一個綁定this的函數,這里我們需要保存this
    const _this = this
    const args = [...arguments].slice(1)
        //返回一個函數
    return function F() {
        //因為返回一個函數,我們可以new F()需要判斷能當做構造函數嗎
        if (this instanceof F) {
            return new _this(...args, ...arguments)
        }
        return _this.apply(context, args.concat(...arguments))
    }
}

  • bind返回一個函數,對於函數來說有兩種方式調用,一種是直接調用,一種是通過new的方式,我們先來說直接調用的方式
  • 對於直接調用來說,這里選擇了apply的方式,但是對於參數需要注意以下情況:因為bind可以實現類似這樣的代碼 f.bind(obj,1)(2),所以我們需要將兩邊的參數拼接起來,於是就有了這樣的實現args.concat(…arguments)
  • new的方式,我們先判斷this,對於new的情況,不會被任何方式改變this,所以對於這種情況我們需要忽略傳入的this
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM