从实现原理更深入了解call和apply
一、原理的粗糙实现
1. call
Function.prototype.call = function(x){
x = x || '{}';
x.fn = this;
var i;
var args = [];
for(i = 1; i < arguments.length; i++){
args.push(arguments[i]);
}
var func = function(thisArg, args){
var str = args.join(',');
return thisArg.fn(str);
}
var result = func(x, args);
delete x.fn;
return result;
}
2. apply
Function.prototype.apply = function(){
x = x || '{}';
x.fn = this;
var i;
var args = [];
for(i = 0; i < arguments[1].length; i++){
args.push(arguments[1][i]);
}
var func = function(thisArg, args){
var str = args.join(',');
return thisArg.fn(str);
}
var result = func(x, args);
delete x.fn;
return result;
}
二、以apply为例讲解实现的过程
假设现在有cat和dog两个对象:
var cat = {
name: 'cat',
printName: function(){
console.log(this.name);
}
}
var dog = {
name: 'dog'
}
使用上面的apply:
cat.printName.apply(dog); // dog
现在分析代码的执行过程:
- 调用apply函数进入apply函数内部
- x.fn = this 就是 dog.fn = cat.printName
- 执行x.fn(); 输出this.name,而此时this为dog,所以代码输出dog
三、重新看之前的Function.prototype.call.apply(null, arguments)
那么它的执行过程就是:
- 调用apply函数进入apply函数内部
- x = null || {} 将 x变成{}
- x.fn = this 就是 {}.fn = Function.prototype.call
- 执行x.fn(arguments); 就是{}.call(arguments);
- 进入call内部
- x.fn = this 就是 arguments[0].fn = {}
- 执行x.fn(arguments[1-n]) 由于fn={}不是函数,所以报错
总结:call和apply需要由函数来调用,不能使用对象调用call和apply
参考文章:
https://blog.csdn.net/THEANARKH/article/details/54393176