文章目录
一、ES6模拟实现apply()
apply和call的作用是一样的,区别在于apply是将参数作为一个数组传入,而call是将参数一个一个传入的ES6模拟实现call()
先驱知识(ES6扩展操作符):
let arr = ['北京','上海','杭州'];
console.log(...arr); // 北京 上海 杭州
function myFun(from, to) {
console.log(...arguments); // 北京 上海
let array = [...arguments];
console.log(array); // ['北京','上海']
}
myFun('北京','上海');
代码如下:
Function.prototype.myApply = function (context, arr) {
context = context ? Object(context) : window; // Object()返回一个和给定的值相对应的类型的对象
context.fn = this; // 给context对象一个属性fn(称作执行函数),用来保存this值(也就是调用myApply的函数)
let result; // 定义result接收执行函数
if (!arr) {
result = context.fn();
} else {
result = context.fn(...arr); // 通过拓展运算符将传入的数组参数的元素取出并与执行函数的参数一一对应
}
delete context.fn; // 删除context对象属性fn
return result; // 返回执行函数
}
let obj = {
myFun(from, to) {
console.log(this.name + '来自' + from + '去往' + to);
}
}
let db = {
name: "Jim"
}
obj.myFun.myApply(db, ['北京', '上海', '杭州']); // Jim来自北京去往上海
解析:通过函数myFun调用myApply时,也就是obj.myFun.myApply(db, ['北京', '上海']),先将db作为临时的context对象 。myCall的this值为函数myFun,即:context.fn = myFun,也就是context对象属性fn保存函数myFun,此时输出context对象有:
{
fn: myFun(from, to) {
console.log(this.name + '来自' + from + '去往' + to);
},
name: 'Jim'
};
随后通过拓展运算符将传入的第二个数组参数[ '北京', '上海' ]的元素取出并与执行函数的参数一一对应:context.fn(...arr),即:myFun('北京', '上海'){...},并通过result接收执行函数,最后删除context对象属性fn,返回result,从而实现将函数myFun()的this指向改变为对象db