javascript系列之 call和apply的模拟实现 篇
call和apply异同
同: 改变函数this指向
异: 传参列表不同(call传参是逐个传递,apply传参是以数组的方式传递)
call
用法例子
var bar = {
age: 18
}
function foo(name, sex) {
console.log(name)
console.log(sex)
console.log(this.age)
}
foo.call(bar, 'Joker', 'male');//Joker,male,18
注意要点:
call改变了foo中的this指向- 函数
foo执行了
call的模拟实现
- 将函数添加为所绑定目标的属性
- 执行该属性
- 删除该属性
Function.prototype.myCall = function (target) {
target = target || window
//this 参数可以传 null,undefined,当为 null和undefined 的时候,视为指向 window
argsLen = arguments.length;
var args = [];
for(var i = 1; i < argsLen; i++)
args.push('arguments[' + i + ']')
args = args.join(',');
target.fn = this;//将函数添加为所绑定目标的属性
var result = eval('target.fn(' + args + ')')//执行该属性
delete target.fn;//删除该属性
return result;
}
foo.myCall(bar, 'Joker', 'male');//Joker,male,18
使用ES6的rest参数和扩展运算符更为简便
Function.prototype.myCall = function (target, ...args) {
target = target || window;
target.fn = this;
var result = target.fn(...args)
delete target.fn;
return result;
}
foo.myCall(bar, 'Joker', 'male');//Joker,male,18
apply
用法例子
var bar = {
age: 18
}
function foo(name, sex) {
console.log(name)
console.log(sex)
console.log(this.age)
}
foo.apply(bar, ['Joker', 'male']);//Joker,male,18
同理:
apply改变了foo中的this指向- 函数
foo执行了
apply的模拟实现
- 将函数添加为所绑定目标的属性
- 执行该属性
- 删除该属性
Function.prototype.myApply = function (target, argsArr) {
target = target || window
//this 参数可以传 null,undefined,当为 null和undefined 的时候,视为指向 window
target.fn = this;//将函数添加为所绑定目标的属性
var result;
if(!argsArr)
result = target.fn();
else{
argsLen = argsArr.length;
var args = [];
for(var i = 0; i < argsLen; i++)
args.push('argsArr[' + i + ']')
args = args.join(',');
result = eval('target.fn(' + args + ')')//执行该属性
}
delete target.fn;//删除该属性
return result;
}
foo.myApply(bar, ['Joker', 'male']);//Joker,male,18
使用ES6的扩展运算符更为简便
Function.prototype.myApply = function (target, args) {
target = target || window;
target.fn = this;
var result;
if(!args)
result = target.fn();
else
result = target.fn(...args);
delete target.fn;
return result;
}
foo.myApply(bar, ['Joker', 'male']);//Joker,male,18
call和apply的部分实现参考自冴羽的博客