关于call
笔者之前在JS中THIS
相关问题梳理这篇文章中已经讲过,但笔者觉得之前写的call
方法不够惊艳😺,还有很多问题没有考虑到,这次重新整理一下,希望对您有帮助;
let func = function (x, y) {
console.log(this);
return x + y;
};
window.name = "HELLO~";
let obj = {
name: '小芝麻'
};
func(10, 20); //=>this:window 'HELLO~' 30
obj.func(10, 20); //=>Uncaught TypeError: obj.func is not a function
复制代码
需求:让func
执行,需要让方法中的this
变为obj
(func
和obj
本身还没啥关联)
// 实现思路:让func和obj关联在一起
// 1.给obj设置一个属性$func,让其属性值是函数func
// 2.obj.$func() 相当于把func执行了,此时方法中的this就是obj
// 3.这种操作方式会存在一些安全隐患:如果原有obj对象中就有$func的属性,我们设置的这个属性会覆盖原有的属性值[真实操作中,我们尽可能保证这个属性名的唯一性];我们设置的属性,在用完后,还要把它移除掉,因为人家对象原本是没有这个属性的;
// obj.$func = func;
// obj.$func(10, 20); //=>this:obj '小芝麻' 30
// delete obj.$func;
// console.log(obj);
复制代码
代码实现
// 为了让每一个函数都可以调取这个方法了
Function.prototype.changeThis = function changeThis(context, ...args) {
// THIS:当前要执行并且改变THIS指向的函数
// CONTEXT特殊情况的处理:不传递是window,传递null/undefined也让其是window,传递非对象或者函数类型值,我们需要让其变为对象或者函数
context == null ? context = window : null;
//=> 为了过滤出传入参数是基本类型的情况
if (typeof context !== "object" && typeof context !== "function") {
//=> 运用构造函数常见一个基本数据类型的实例;
//=> 目的是为了在下面context[uniqueKey] 时,由于基本数据类型不能运用对象的“点”或者“[]”存储属性时报错的问题
context = new context.constructor(context);
}
//=> 利用模版字符串和时间戳生成一个唯一的属性名
let uniqueKey = `?${new Date().getTime()}`;
//=> 给参数中新增个uniqueKey属性与调用的函数关联
context[uniqueKey] = this;
//=> 让调用的函数执行
let result = context[uniqueKey](...args);
//=> 删除新增的属性
delete context[uniqueKey];
//=> 把函数执行的结果 return 出去
return result;
};
let result = func.changeThis(obj, 10, 20);
let result = func.changeThis();
let result = func.changeThis(null/undefined);
let result = func.changeThis(10, 20); //=>方法执行,方法中的THIS是10,给方法传递了20(第一个参数是我们要改变的THIS指向问题)
复制代码
去除注释后的完整代码
Function.prototype.changeThis = function changeThis(context, ...args) {
context == null ? context = window : null;
if (typeof context !== "object" && typeof context !== "function") {
context = new context.constructor(context);
}
let uniqueKey = `?${new Date().getTime()}`;
context[uniqueKey] = this;
let result = context[uniqueKey](...args);
delete context[uniqueKey];
return result;
};
let result = func.changeThis(obj, 10, 20);
let result = func.changeThis();
let result = func.changeThis(null/undefined);
let result = func.changeThis(10, 20); //=>方法执行,方法中的THIS是10,给方法传递了20(第一个参数是我们