揭祕 JS 之 apply、call、bind模擬實現

前言

applycallbind均可以用來改變函數中this對象的指向,可是它們原理是如何實現的呢?數組

解析 apply

先看一個例子:app

var value = 'window'

function func(a, b) {
    console.log(this.value, a, b)
}

var obj = {
    value: 'obj'
}

func(1, 2) // window,1,2

func.apply(obj, [1, 2]) // obj,1,2
複製代碼

函數func使用apply方法將內部的this對象指向了obj對象。下面讓咱們模擬實現一下吧:函數

先在 Functionprototype原型對象上定義一個MyApply方法:Function.prototype.MyApply = function (){}ui

原生apply接受參數方式以下:Func.apply(this, [arguments])。因此咱們第一個參數接受指定的對象,第二個參數接受一個數組。this

Function.prototype.myApply = function (context, array){
    var newContext = context || window  // 缺省指向window
    newContext.fn = this // this 是func函數
    var result
    if (!array) {
        result = newContext.fn(...array);
    } else {
         result = newContext.fn();
    }
    delete newContext.fn;
    return result;
}
複製代碼

看看實例:spa

var obj = {
    value: 'obj'
}

function func (a, b) {
    console.log(this.value, a, b)
}

func.myApply(obj, [1, 2]) // obj,1,2
複製代碼

解析 call

實現模擬了apply,call也能夠順着上面的邏輯修改完成。prototype

原生call傳參方式與原生apply傳參方式有些區別。它能夠接受多個參數:Func.call(obj, agrs, agrs, ...agrs)code

Function.prototype.myCall = function (context){
    var newContext = context || window  // 缺省指向window
    newContext.fn = this // this 是func函數
    var args = [...arguments].slice(1) // 截取除去第一個對象之外的參數
    var result = newContext.fn(...args) // 執行函數方法
    delete newContext.fn;
    return result;
}
複製代碼

看看實例:對象

var obj = {
    value: 'obj'
}

function func (a, b) {
    console.log(this.value, a, b)
}

func.myCall(obj, 1, 2) // obj,1,2
複製代碼

解析bind

bind與上面二者最大的不一樣:applycall都是直接調用執行,而bind是返回一個新的函數,須要咱們從新調用纔會被執行。它傳參的方式跟call相似,都是能夠接收多個參數。Func.bind(this,1, 2, 3)()文檔

Function.prototype.MyBind = function (context) {
  context.fn = this
  var args = [...arguments].slice(1)
  return function () {
    var result = context.fn(...args)
    delete context.fn
    return result
  }
}
複製代碼

看看實例:

var obj = {
    value: 'obj'
}

function func (a, b) {
    console.log(this.value, a, b)
}

func.MyBind(obj, 1, 2)() // obj,1,2
複製代碼

總結

以上,只是簡單的實現了applycallbind。正確的實現方式請查閱官方文檔。

相關文章
相關標籤/搜索