apply方法
定义
call()方法,在mdn中的定义:
apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。(它的作用和使用和call方法一致,唯一的区别就是call方法传递的是一个个参数的列表,apply方法传递的是参数的数组集合。Call方法详细请看call方法解析)
语法
func.apply(thisArg, [argsArray])
apply方法传递两个参数,第一个参数传递的是所要改变指向的值(当该函数处于非严格模式下,则指定为 null 或 undefined 时会自动替换为指向全局对象,原始值会被包装。),第二个参数是所要传递的参数(参数是一个数组集合)。
返回值
返回调用函数的返回值。若该函数没有返回值,则返回 undefined。
使用
let myName = {
nameStr: 'dahua'
}
function sayName(res, res2) {
console.log(this);
console.log(this.nameStr);
console.log(res);
console.log(res2);
}
sayName.apply(myName, [1,3,'a']);
// {nameStr: "dahua"}
// dahua
// 1
// 3
上述代码改变this指向指向myName对象,并传入了一个数组参数,在sayName函数执行的时候会把传入的数组展开进行参数传递。还可以像下方这样子使用:
let array = ['a', 'b'];
let elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
上述代码是调用了数组的push方法。并通过apply方法直接传入了数组参数,实现数组的合并。
模拟实现自己的apply方法
第一个参数具体指向的值,在call方法中已经详细验证不在赘述,可以直接查看call方法解析(call方法实现),直接实现自己的apply方法和验证。
思路:
核心就是根据this的指向规则。(this详细指向规则可参考this解析)
步骤:
1、 因为是所有函数的方法,所以直接在原型上创建一个方法
2、 先判断传入的第一个参数thisArg的类型,进行分别处理
3、给thisArg添加一个属性,并把this赋值给它
4、调用该方法,并将参数传入进去并展开
5、删除改thisArg创建的属性
6、返回函数调用的返回值
代码如下:
// 挂在Function的原型上
Function.prototype.myApply = function(thisArg, res) {
// 判断第一个参数thisArg是否是undefined或者null,是的话就赋值给window
if (typeof thisArg === 'undefined' || thisArg === null) {
thisArg = window;
}
// 对传入的值thisArg就行包装
thisArg = Object(thisArg);
// 给传入的值thisArg创建属性,为防止thisArg已经有对应的对应进行覆盖,所以使用Symbol创建唯一值
const keyFn = Symbol('__myKeyFn__');
// 此时的this指向调用myCall方法的函数,将它指向thisArg[keyFn]。
// 这里也就是利用了this的指向规则
thisArg[keyFn] = this;
// 调用该方法传入参数,并展开
const reasult = thisArg[keyFn](...res);
// 删除thisArg创建的属性
delete thisArg[keyFn];
// 返回函数的返回值
return reasult;
}
测试
上面模拟实现了自己的apply方法,下面就测试一下功能是否正常:
let myName = {
nameStr: 'dahua'
}
function sayName(res, res2) {
console.log(this);
console.log(this.nameStr);
console.log(res);
console.log(res2);
}
sayName.myApply(myName, [1,3,'a']);
// {nameStr: "dahua", Symbol(__myKeyFn__): ƒ}
// dahua
// 1
// 3
let array = ['a', 'b'];
let elements = [0, 1, 2];
array.push.myApply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
测试结果和自带apply方法一致。
使用call方法实现apply方法
当我们实现了call方法的时候可以直接使用实现的call方法实现apply方法。如:
Function.prototype.myApply = function (thisArg, res) {
return this.myCall(thisArg, ...res);
}
测试
let myName = {
nameStr: 'dahua'
}
function sayName(res, res2) {
console.log(this);
console.log(this.nameStr);
console.log(res);
console.log(res2);
}
sayName.myApply(myName, [1,3,'a']);
// {nameStr: "dahua", Symbol(__myKeyFn__): ƒ}
// dahua
// 1
// 3
let array = ['a', 'b'];
let elements = [0, 1, 2];
array.push.myApply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
测试结果与自己实现的apply方法一致。