揭秘 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。正确的实现方式请查阅官方文档。

相关文章
相关标签/搜索