文章目录
一、模拟实现call()
先驱知识(ES6扩展操作符):
let arr = ['北京','上海','杭州'];
console.log(...arr); // 北京 上海 杭州
function myFun(from, to) {
console.log(...arguments); // 北京 上海
let array = [...arguments];
console.log(array); // ['北京','上海']
}
myFun('北京','上海');
代码如下:
Function.prototype.myCall = function (context) {
context = context ? Object(context) : window; // Object()返回一个和给定的值相对应的类型的对象。
context.fn = this; // 给context对象一个属性fn(称作执行函数),用来保存this值
let args = [...arguments].slice(1); // 选取传入的第二个及以外参数组成的新数组
let result = context.fn(...args); // 通过扩展运算符将选取的参数作为执行函数fn的参数,并通过变量result接收执行函数
delete context.fn // 删除context对象属性fn
return result; // 返回执行函数
}
var obj = {
myFun(from, to) {
console.log(this.name + '来自' + from + '去往' + to);
}
}
var db = {
name: "Jim"
}
obj.myFun.myCall(db, '北京', '上海'); // Jim来自北京去往上海
运行结果:Jim来自北京去往上海
解析:通过函数myFun调用myCall时,也就是obj.myFun.myCall(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对象db以外的参数作为执行函数fn的参数,并将该执行函数存入变量result,即:result = context.fn('北京','上海'),删除context对象属性fn,最后返回result,从而实现将函数myFun()的this指向改变为对象db