模擬實現call、apply以及bind

作用.

apply.call.bind 都是爲了改變函數運行時上下文(this指向)而存在的。

區別:

  • 三者的第一個參數都是this的指向
  • apply的第二個參數是個數組,而call與bind的第二個以及之後的參數都是函數的入參
  • bind不是立即執行,而call和apply會

call的簡單模擬實現

思路:

  1. 函數定義在哪裏?
    因爲是對全局有效的,所以定義至Function的原型對象中
  2. 參數接收參數?
    綁定函數被調用接收第二個以及之後的參數
  3. 如何顯式綁定this
    如果被調用的函數,被指定對象所擁有,那麼函數內部的this,應該指向的是該對象

代碼上一盤:

      Function.prototype.bind = function(context) {
           let ctx = context || window
           // 讓函數的this指向context
           ctx.func = this
           console.log(this, '------this')
           // 獲取參數
           let args = Array.from(arguments).slice(1)
           // 爲什麼下面的還要判斷傳入的數組長度?
           // const res = args.length ? ctx.func(...args) : ctx.func()
           const res = ctx.func(...args)
           delete ctx.func
           //爲什麼返回?不返回也是OK的
           return res
       }
       let name = '全局的'
       function sayName() {
           console.log(this.name)
       }
       let obj = {
           name: '我是某個對象的'
       }
       sayName.bind(obj)

apply的簡單模擬實現

apply的實現和call是一樣的,只不過是改變傳參的方式而已

       Function.prototype.apply = function(context) {
            let ctx = context || window
            ctx.func = this
            let args = arguments[1]
            let isArray = Array.isArray(args)
            if (!isArray) {
                alert('-------第二個傳參不是數組喲')
                return
            }
            let res = args ? ctx.func(...args) : ctx.func()
            delete ctx.func
            return res
        }

        let name = '全局的'
        function sayName() {
            console.log(this.name)
        }
        let obj = {
            name: '我是某個對象的'
        }
        sayName.apply(obj, [12])

bind的模擬實現

思路:

  1. 函數定義在哪裏?
    因爲是對全局有效的,所以定義至Function的原型對象中
  2. 參數接收參數?
    bind函數返回一個綁定函數,最終調用需要傳入函數實參和綁定函數的實參!!
  3. 如何顯式綁定this
    如果被調用的函數,被指定對象所擁有,那麼函數內部的this,應該指向的是該對象
      Function.prototype.bind = function(context) {
            // 對對象進行深拷貝,防止污染原有對象
            let ctx = JSON.parse(JSON.stringify(context)) || window
            ctx.func = this
            let args = Array.from(arguments).slice(1)

            return function() {
                return args.length ? ctx.func(...args) : ctx.func()
            }
        }

        let name = '全局的'
        function sayName() {
            console.log(this.name)
        }
        let obj = {
            name: '我是某個對象的'
        }
        // sayName.bind(obj)
        // sayName.apply(obj, [12])
        sayName.bind(obj)()

參考文檔

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