JS中apply(), call()和bind()的使用和比较

版权声明:wuyujin1997 reserve all rights. https://blog.csdn.net/wuyujin1997/article/details/88775921

JS中的call(), apply()和bind()

intro

在函数内部,根据是否是严格模式(strict mode)this指向undefinedwindow
但是,可以手动指定this的绑定|指向。

调用函数时,要指定函数的this指向那个对象,可以用Function函数对象的apply(),他接收两个参数:需要绑定的this变量,函数参数列表的数组形式argArray

demo

  • 换绑定Function对象内部的this指向。
// 用于返回Person对象。
function getPerson(name, age) {
  let obj = new Object();
  obj.name = name;
  obj.age = age;
  obj.show =  function() {
    console.log(this.name + "\t" + this.age);
  }
  return obj;
}

// 实例化p1和p2
var p1 = getPerson("aaa", 11);
var p2 = getPerson("bbb", 22);

// 两个对象各自调用show()
p1.show();
p2.show();

// 用p1调用show()方法,但换绑定内部的this为p2。
p1.show.apply(p2);

输出:

// 用于返回Person对象。
function getPerson(name, age) {
  let obj = new Object();
  obj.name = name;
  obj.age = age;
  obj.show =  function() {
    console.log(this.name + "\t" + this.age);
  }
  return obj;
}
undefined
// 实例化p1和p2
var p1 = getPerson("aaa", 11);
var p2 = getPerson("bbb", 22);
undefined
// 两个对象各自调用show()
p1.show();
p2.show();
aaa	11
bbb	22
undefined
// 用p1调用show()方法,但换绑定内部的this为p2。
p1.show.apply(p2);
bbb	22
undefined

换绑函数内部this的指向

  • 不换绑Function对象内部的this
Math.max(2, 5, 3);
5
Math.max.apply(null, 2, 5, 3);  // thisArg处传入null。
5

另有func.call()func.bind()方法。

Math.max.call(null, 2, 5)
5
Math.max.bind(null)(2, 5);  // func.bind()返回一个新的Function对象。Function对象的调用:函数名(...args)。
5

函数声明

func.apply(thisArg, ?argArray) 在一个对象的上下文中应用另一个对象的方法。参数以Array数组格式传入。
func.call(thisArg, ...argsList)call(),参数以列表形式传入。
func.bind(thisArg, ...argsList) - Function
thisArg 要换绑定的this新值(不换可传入null)。
argArray 向函数传入的参数数组(Array格式)。
...argsList 向函数传入的参数列表(用到了ES6...rest参数(展开运算符))。

bind()方法会创建一个新函数,称为绑定函数
当调用这个绑定函数时,绑定函数会以创建它时传入的第一个参数thisArg作为this
以传入bind()中的其余参数再加上绑定函数运行时本身传入的参数按照顺序作为原型函数的参数来调用原函数。

比较

  • 第一个参数
    三个方法的第一个参数都是要换绑定的this参数thisArg
    如果不需要换绑定则传入null

  • 第二个参数
    apply()的第二个参数是?argArray,是参数列表的数组格式(一个Array对象)。
    call()bind()的第二个参数都是...argsList(用到了ES6的新特性...rest参数(展开运算符))。

  • 函数返回值。
    apply()call()的函数返回值都是根据其caller函数的返回值决定的。
    bind()返回一个Function对象(经过修改后的新的方法)。
    调用Function对象funcName(...argsList)

应用

动态修改函数内部this绑定的对象

  • 查看object的具体类型
arr = [1,2,3];  // Array类型也是object类型。用typeof检测不够精细。
// 换绑定 Object.prototype.toString() 函数内部的this。
Object.prototype.toString.apply(arr);
Object.prototype.toString.call(arr);
Object.prototyupe.toString.bind(arr)();
  • 装饰器(动态修改函数功能)
    利用apply()动态改变函数的行为(以及call()bind())。
    JS中所有对象都是动态的,即使内置的函数,也可以重新指向新的函数。
    如:统计代码中调用了多少次 window.parseInt()
var invokeCount = 0;  // 初始化调用次数
var tmpParseInt = window.parseInt; // 暂存原函数

// 覆盖同名的全局变量`parseInt`
window.parseInt = function() {
  invokeCount += 1;   // 调用次数+1
  return tmpParseInt.apply(null, arguments);  // 调用原函数
}

// 测试
console.log(invokeCount); // 0
window.parseInt("10");
window.parseInt("2.22");
window.parseInt(false);
console.log(invokeCount); // 3

window.parseInt = tmpParseInt;  // 还原
  • 其他(需要动态修改函数内部this绑定的对象)。

猜你喜欢

转载自blog.csdn.net/wuyujin1997/article/details/88775921
今日推荐