JavaScript笔记 | 浅析call、apply、bind

332 阅读2分钟

这是我参与8月更文挑战的第21天,活动详情查看:8月更文挑战

基本介绍

call、apply、bind是Function上的三个方法,他们都是在给定的作用域中调用函数。先来看一下他们的基本语法。如下:

function.call(thisArg, arg1, arg2, ...)

function.apply(thisArg, [param1,param2,...])

function.bind(thisArg, param1, param2, ...)

相同点和不同点

  • 相同点

    • 都可以改变函数function的this指向
  • 不同点

    • call和apply的区别是,他们的传参写法不同。

      • call的第2个参数是第2个至第N个都是给function的传参。

      • apply的第二个参数只能是数组

    • bind和他们的区别是,他在改变this指向时不是立即执行,call和apply是立刻执行的

call

  • call()使用示例:
let a = {

  name: '芒果A',

  getName: function(msg) {

    return msg + this.name;

  } 

}

let b = {

  name: '芒果B'

}

console.log(a.getName('hello~'));  // hello~芒果A

// 这里我们是 让b对象直接使用a对象里的getName函数方法
console.log(a.getName.call(b, 'hi~'));  // hi~芒果B

  • 手动实现
Function.prototype.call = function (context, ...args) {
    // 第一步:context这是可选的参数,不传默认window
    var context = context || window;
    // 第二步:给context创建一个fn属性,来指定上下文
    context.fn = this;
    // 第三步:通过执行 eval 来执行 context.fn 这个函数
    var result = eval('context.fn(...args)');
    delete context.fn
    // 第四步:返回result
    return result;
}

这段代码实现可以结合上边实例简单理解一下,加深印象。

apply

apply()使用示例:

const numbers = [15, 16, 12, 13, 17];

// 这里是通过apply来获取数组中的最大值。
const max = Math.max.apply(null, numbers);
console.log(max);  // 最大值:17

// 这里是通过apply来获取数组中的最小值。
const min = Math.min.apply(null, numbers);
console.log(min); // 最大值:12

关于apply()手动实现,通过文章开头介绍的基本理解,我们知道apply的手动实现和call的手动实现是基本一致的,只不过是传参不同罢了。

所以小伙伴们可以仿照上边的call的手动实现,自己实现一个apply()方法。

bind

  • bind()使用示例
this.name = '🥭'    
let obj = {
  name: '中文名-芒果',
  getName: function() { 
      return this.name;
  }
}

obj.getName()  // 中文名-芒果

let obj1 = obj.getName;
obj1();  // 🥭

// 这里obj1 借用了 obj的getName函数方法
obj1.bind(obj)(); // 中文名-芒果
  • 手动实现 关于bind手动实现,我们要明确一点

他是需要通过返回一个函数的方式将结果返回,之后再通过执行这个结果,得到想要的执行效果。

Function.prototype.bind = function (context, ...args) {
    if (typeof this !== "function") {
         throw new Error("this must be a function");
     }
     var self = this;
     var fbound = function () {
            self.apply(this instanceof self ? this : context, args.concat(Array.prototype.slice.call(arguments)));
  }
  // 将 this.prototype 上面的属性挂到 fbound 的原型上面
    if(this.prototype) {
     fbound.prototype = Object.create(this.prototype);
      }
  return fbound;1  
}

MDN关于bind讲解,感觉这里介绍的很详细,不明白的小伙伴可以来这里再学习一番。

总结

前端漫漫长途,我们都在路上,希望可以和小伙伴们一起交流,一起进步。持续更新ing.....