apply
概念
概念:方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。 语法:function.call(thisArg, [argsArray]) 参数: thisArg:可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。 返回值:使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined。
原理
分析: 他们改变的this指向的原理:
- 其实就是通过在 某个对象上添加这样一个方法,
- 然后拿到参数,
- 再去调用这个对象的这个方法(符合this指向调用者。) 。
- 得到结果后,再在这个对象上删去这个属性方法。
-
实现
call
首先 context 为可选参数,
- 如果不传的话默认上下文为 window 接下来给 context 创建一个 fn 属性,并将值设置为需要调用的函数
- 因为 apply 传参是数组传参,所以取得数组,将其剥离为顺序参数进行函数调用
- 然后调用函数并将对象上的函数删除
function Animal(name,color){
this.name = name||'动物';
this.color = color||'颜色';
this.say=function(){
console.log(`Animal:${this.name},${this.color}`)
}
}
function Dog(name,color){
Animal.apply(this,[name,color]);
this.say=function(){
console.log(`Dog:${this.name},${this.color}`)
}
}
let newDog = new Dog('小狗','棕色');
let newDog2 = new Dog();
newDog.say()
newDog2.say();
Function.prototype.myApply=function(context){
// 判断调用者是否为函数
if (typeof this !== 'function') {
throw new TypeError('Error')
}
//如果不传默认window
context = context || window;
// 新增 fn 属性,将值设置为需要调用的函数
context.fn = this;
// 返回执行结果
let result;
//判断是否有参数传入
if(arguments[1]){
result = context.fn(...arguments[1])
}else{
result = context.fn();
}
// 删除函数
delete context.fn;
return result
}
function Cat(name,color){
Animal.myApply(this,[name,color]);
this.say=function(){
console.log(`Cat:${this.name},${this.color}`)
}
}
let newCat = new Cat('小猫','棕色');
let newCat2 = new Cat();
newCat.say()
newCat2.say();
示例
- 用 apply 将数组各项添加到另一个数组
- 使用apply和内置函数
- 使用apply来链接构造器