call()、apply()、bind() 对比与应用

62 阅读3分钟

一、apply 和 call

对比
1、用于改变this的指向
2、用于借用其他对象的方法
可以只写一次B方法,然后在A对象中继承它,而不用在新对象中重复写该方法。
3、第一个参数都是一样的,表示this所要指向的那个对象。
4、第二个参数,是函数调用时所需的参数。apply是数组,而call则是arg1,arg2...参数列表的形式。
5、apply,call方法会使函数立即执行
例:B.apply(A, arguments);即A对象应用B对象的方法。
例:B.call(A, args1,args2);即A对象调用B对象的方法。
6、call 方法比 apply 快,call 的性能更好。
因为call传入参数的格式正是内部方法所需要的格式。 详见 为什么 call 比 apply 快?

常见适用场景
1、参数数量 / 顺序确定就用call,不确定则用apply。
2、考虑可读性:参数数量不多就用call,数量比较则应该把参数整合成数组,使用apply。
在参数为3个(包含3)以内时,优先使用 call 方法进行事件的处理。而当参数过多(多余3个)时,考虑使用 apply 方法。

代码示例

call

例1:将伪数组转换成真正的数组
拓展:伪数组(NodeList ), 又称类数组,是一个含有length属性的json对象
① 拥有length属性,索引是非负整数。
② 不具有数组的方法,但仍可以使用对标准数组遍历的方法来遍历它

var element = { 
    0: 'div', 
    1: 'p', 
    2: 'span', 
    length: 3 
} //数据结构必须是以数字为下标,且必须有number类型的length属性**
var arr = Array.prototype.slice.call(element); 
console.log(arr);  // ["div","p","span"]

apply

例1:将数组2追加到现有数组1(数组1已被改变)

let arr1 = [1,2,3] 
let arr2 = [4,5,6] 
[].push.apply(arr1, arr2) // [1,2,3,4,5,6]

例2:找出数组最大元素

//JavaScript 不提供找出数组最大元素的函数。结合使用apply方法和Math.max方法,可返回数组最大元素。
var a = [10, 2, 4, 15, 9];
Math.max.apply(null, a) // 15

二、bind

bind()方法用于将函数体内的this绑定到某个对象,然后返回一个新函数。
参数和call一样,但返回一个新的函数,这个函数不会马上执行。
bind()只是创建一个函数,而不是立即执行函数。
bind() 生成的函数还可以继续接收参数。

常见适用场景
1、bind() 最简单的用法是创建一个函数,不论怎么调用,这个函数都有同样的 this 值。
2、当使用setTimeout或者setInterval的时候,回调方法中的this值会指向window对象。可以通过bind方法,显式绑定this

代码示例

例1:创建一个新函数,把 'this' 绑定到 module 对象

this.x = 9; 
var module = {
  x: 81,
  getX: function() { return this.x; }
};
module.getX(); // 81

var retrieveX = module.getX;
retrieveX(); // 返回 9 - 因为函数是在全局作用域中调用的

var boundGetX = retrieveX.bind(module);
boundGetX(); // 81

例2:配合setTimeout使用,显式绑定this

function LateBloomer() {
  this.petalCount = Math.ceil(Math.random() * 12) + 1;
}

// 在 1 秒钟后声明 bloom
LateBloomer.prototype.bloom = function() {
  window.setTimeout(this.declare.bind(this), 1000);
};

LateBloomer.prototype.declare = function() {
  console.log('I am a beautiful flower with ' +
    this.petalCount + ' petals!');
};

var flower = new LateBloomer();
flower.bloom();  // 一秒钟后,调用 'declare' 方法

如想了解更多,详见阮一峰老师JS教程 第6章第2节wangdoc.com/javascript/…

1658744574263.png