注意:不要使用 call 、apply 链式调用构造函数(例如:实现继承)。这会将构造函数作为普通函数调用,这意味着 new.target的值为undefined,而类会抛出错误,因为它们不能在没有new的情况下被调用
Function.prototype.call()
-
Function实例的 call() 方法会以给定的 this值 和 逐个提供的参数调用该函数
-
语法格式:
call (thisArg, arg1, arg2, /* …, */ argN)
- thisArg:在调用func时要使用的 this值,如果函数不在严格模式下,null和undefined将被替换成全局对象,并且原始值将被转换为对象
- arg1 ... argN(可选):函数的参数
-
返回值:
- 使用指定的 this值 和参数 调用后的结果
-
function greet() { console.log(this.animal, "的睡眠时间一般在", this.sleepDuration, "之间"); } const obj = { animal: "猫", sleepDuration: "12 到 16 小时", }; greet.call(obj); // 猫 的睡眠时间一般在 12 到 16 小时 之间
应用场景
-
对象的继承
-
function superClass () { this.a = 1; this.print = function () { console.log(this.a); } } function subClass () { superClass.call(this); this.print(); } subClass(); // 1
-
-
借用方法
-
let domNodes = Array.prototype.slice.call(document.getElementsByTagName("*")); // 这样子domNode就可以应用数组下的所有方法
-
Function.prototype.apply()
-
Function实例的 apply() 方法会以给定的 this值 和 作为数组(或类数组对象)提供的 arguments 调用该函数
-
语法格式
-
apply(thisArg, argsArray) - thisArg:在调用func时要使用的 this值,如果函数不在严格模式下,null和undefined将被替换成全局对象,并且原始值将被转换为对象
- argsArray(可选):一个类数组对象,用于指定调用func时的参数,或者如果不需要向函数提供参数,则为null或undefined
-
-
返回值
使用指定的 this值 和 参数 调用函数的结果
- 将数组各项加到另一个数组 (可以使用concat方法,但是它不会将元素追加到已有数组中,而是创建并返回一个新数组)
const array = ["a", "b"];
const elements = [0, 1, 2];
// 使用 push
array.push(...elements);
// 使用 apply 隐式地将一个数组作为一系列参数展开
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
- 第二个参数会被转换成类数组
类数组:具备与数组特征类似的对象。类数组可以通过角标[]进行调用,具备length属性,也可以使用for循环遍历,但是无法使用forEach、splice、push等数组的原生方法
func.apply(obj, [1,2,3])
// func 接收到的参数实际上是 1,2,3
func.apply(obj, {
0: 1,
1: 2,
2: 3,
length: 3
}) // 这个对象就是一个类数组
// func 接收到的参数实际上是 1,2,3
apply函数和call函数几乎完全相同,只是函数参数在call中逐个作为列表传递,而在apply中它们会组合在一个对象中,通常是一个数组。例如,
func.call(this, "eat", "bananas")与func.apply(this, ["eat", "bananas"])
应用场景
-
Math.max / min
-
let max = Math.max.apply(null, array);
-
-
实现两个数组合并,以上例子中
Function.prototype.bind()
-
Function 实例的 bind() 方法创建一个新函数,当调用该新函数时,它会调用原始函数并将其
this关键字设置为给定的值,同时,还可以传入一系列指定的参数,这些参数会插入到调用新函数时传入的参数的前面 -
语法格式
-
bind(thisArg, arg1, arg2, /* …, */ argN) - thisArg:在调用绑定函数时,作为
this参数传入目标函数func的值。如果函数不在严格模式下,null 和 undefined 会被替换为全局对象,并且原始值会被转换为对象。如果使用new 运算符构造绑定函数,则忽略该值 - argsArray(可选):在调用 func时,插入到传入绑定函数的参数前的参数
-
-
返回值:
使用指定的 this 值和初始参数(如果提供)创建的给定函数的副本
const module = {
x: 42,
getX: function () {
return this.x;
},
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // undefined 此时隐式绑定丢失,this指向window 但是window不存在属性x 所以返回undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX()); // 42
总结
- call、apply主要是改变对象的执行上下文,并且是立即执行,传参的方式略有不同
- bind也能改变对象的执行上下文,但是它返回的是一个函数,需要再调用才会执行