call()apply()bind()办法的作用都是扭转函数运行时this的指向。 bind() 是返回对应的函数,便于稍后调用;call()apply()则是立刻调用。

相同点

  1. 都是用来扭转函数执行时this的指向,即函数运行时的上下文;
  2. 第一个参数都是this要指向的对象;
  3. 都能够利用后续参数传参。

1、apply、call

二者作用完全相同,只是接管参数上的不同。如果不传入第一个参数,则默认上下文是 window

1)call
语法
  • fun.call(context, arg1,arg2...)
  • context: 在fun函数中运行时指定的this值
  • arg1,arg2:指定的参数列表
实现原理
Function.prototype.myCall = function(context, ...args) {    if( typeof this !== 'function') {        throw new TypeError('Error') // 判断是否是函数调用    }    context = context ? Object(context) : window // 原始值的this会指向该原始值的实例对象 因而须要Object转换成对象类型    context.fn = this // 函数的this指向隐式绑定到context上    const result = context.fn(...args) // 通过隐式绑定函数并传递参数    delete context.fn // 删除上下文对象的属性    return result // 返回函数执行后果}

示例

let test = {    name: "test"}let  fun = {    fn: function () {          console.log(this.name)    }}fun.fn.myCall(test) // test
2)apply
语法
  • fun.apply(context, [argsArr])
  • context:在fun 函数运行时指定的this值
  • argsArr:一个数组或者是类数组对象,其中数组中元素会作为独自参数传给fun。当参数值为null 或者undefined时,示意不须要传入任何参数。
留神: 上述指定的this值(thisArg)并不一定是该函数执行时真正的this值,如果该函数处于非严格模式下,则指定为null或者undefined时会主动指向全局对象(浏览中就是window对象),同时值为原始值(number、string、boolean)的this会指向该原始值的主动包装对象。
实现原理
Function.prototype.myApply = function(context) {    if( typeof this !== 'function' ) {        throw new TypeError('Error')    }    context = context ? Object(context) : window    context.fn = this    let result    if(arguments[1]) { // 解决参数上和call有区别        result = context.fn(...arguments[1])    } else {        result = context.fn()    }        delete context.fn    return result}

示例

function fn() {    console.log(this.age)}let person = {    age: 12}fn.myApply(person) // 12

2、bind

bind办法会创立一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创立它时传入bind()的第一个参数作为this,传入bind办法的 其余参数以及和绑定函数运行时自身的参数 ,将依照程序作为原函数的参数来调用原函数。

语法
  • fun.bind(context, arg1, arg2, ...)
  • context:当绑定函数被调用时,该参数会作为原函数运行时的this指向;当应用new操作符调用绑定函数时,该参数有效。
  • arg1,arg2...:绑定函数被调用时,这些参数将位于实参之前传递给绑定的办法。
实现原理
Function.prototype.myBind = function(context) {    if( typeof this  !== 'function' ) {        throw new TypeError('Error')    }        let args = [...arguments].slice(1) // bind 函数中的参数    let self = this // 保留原函数    return function() {        return self.apply(context, args.concat(...arguments)) // arguments 是内部函数传入的    }}

示例

let obj = {    a: 'a'};function f(b, c, d) {    console.log(this.a, b, c, d)}f.myBind(obj, 'b')('e') // a b e undefinedf.myBind(obj, 'b', 'c')('e') // a b c ef.myBind(obj, 'b', 'c', 'd')('e') //a b c d