call函数的正常调用
function.call(thisArg) //修改this绑定指向thisArg
let foo = {
value :1
}
function bar(){
console.log(this.value)
}
bar.call(foo); // 输出结果为1
call方法原理
1.将函数临时设置为对象的属性
2.使用该对象调用函数
3.删除临时添加的属性
4.返回函数执行的结果
注意事项:
thisArg为null或undefined时,this指向全局对象
需要处理参数传递
函数可能会有返回值
ES5版本call函数方法模拟
//1.通过Function.prototype添加myCall方法,使所有函数可用
Function.prototype.myCall = function (context){
//2.处理上下文参数,如果context为null或undefined,则指向全局对象
var context = context || window;
//3.将当前函数(this)设置为context的临时属性fn
// 这里的this可用理解为调用myCall的函数对象
context.fn = this;
//4.获取传入的参数,除了第一个context参数
const args = [];
//arguments 是函数内部的一个类数组对象,包含调用函数时传入的所有参数
for(let i = 1;i<arguments.length;i++){
args.push('arguments[' + i + ']');
}
//5.执行函数,使用eval函数拼接参数
const result = eval('context.fn('+ args + ')');
//6.删除临时添加的属性
delete context.fn;
//7.返回指向的结果
return result;
}
示例解析ES5版本call函数方法模拟
function greet(name){
console.log(`hello,${name}! I am ${this.title}`);
}
const person = {
title: 'LiHua'
}
greet.myCall(person,'John'); //hello,John! I am LiHua
当调用greet.myCall(person,'John');时
myCall内部的this指向 当调用greet函数
context指向 person 对象
context.fn = this; ===> person.fn = greet; ===> person.fn('John');
此时fn中的this指向person
ES6版本call函数模拟
//1..通过Function.prototype添加myCallES6方法,使所有函数可用
Function.prototype.myCallES6 = function (context,...args){
//2.处理上下文参数,如果 context 为 null 或 undefined,默认指向全局对象
context = context || window;
// 3.根据环境选择属性名策略
const useSymbol = typeof Symbol !== 'undefined';
/*
*4.检测当前环境是否支持 Symbol
* 现代浏览器/Node.js: Symbol 已定义 → useSymbol = true,支持 Symbol: 创建唯一Symbol → Symbol()
* 老旧环境(如IE): Symbol 未定义 → useSymbol = false,不支持 Symbol: 生成随机字符串 → `__fn_${时间戳}_${随机数}`
* */
const propName = useSymbol ? Symbol():`_fn_${Date.now()}_${Math.random()}`;
/*
* 5.将当前函数绑定到上下文,同ES5版本一样即设置当前函数(this)为context的临时属性propName
* 这里的this可用理解为调用myCallES6的函数对象
* */
context[propName] = this;
//6.直接执行函数
const result = context[propName](...args);
//7.清理临时属性
delete context[propName];
//8.返回结果
return result;
}
相同示例解析ES6版本call函数模拟
greet.myCallES6(person,'John'); //hello,John! I am LH
person ===> context
args ===> ['John']
propName = Symbol() 或 随机字符串
this ===> greet函数
person[propName] ===> greet函数
执行
person[propName]('John')
此时propName中的this指向person
result = 'hello,John! I am LH'