学习分析call , apply , bind 源码,及分析。。
在学习call,apply,bind 这三个API时,他们对context的指向有修改。
那么就带着一个疑问来学习这代码吧!(需要有JS 原型基础)。
我们先实现下call 能做什么。
function say(){
console.log('my name is ' + this.name + ' , it is ' + this.age);
}
var me = {
name: 'LiaoXiang',
age: 12
}
say(); //my name is , it is undefined
say.call(me); //my name is LiaoXiang , it is 12
看上面的方法,我们来思考一下 是不是在me 这个方法中拥有say 这个方法就能实现?
var me = {
name: 'liaoxiang',
age: 12,
say(){
console.log('my name is ' + this.name + ' , it is ' + this.age);
}
}
me.say(); // my name is liaoxiang , it is 12
根据上面的思想,我们是需要在上面注入一个方法这样就解决了我们想要处理的问题。
//先实现这个
Object.prototype.myCall = function(context){
context = context || window ; // 没传指向window
context.fun = this; // this 指向的是调用myCall的函数
/**
*这里如果不删除context.fun 那么在调用的时候永久性的放入的函数中加入了一个方法(浪费内存);
*解决 delete context.fun
**/
var result = context.fun();
delete context.fun ;
return result;
}
say.myCall(me); //my name is LiaoXiang , it is 12 this指向完成!
call apply 的后面的参数怎么用忘记了 想不忙着写,先实现bind方法!
已知bind 方法直接改变一个方法的this 指向
Function.prototype.myBind = function(context){
if(typeof this === 'function'){ //this 调用myBind的对象
throw new TypeError(this + 'is function');
}
var self = this;
return self.myCall(context)
}
下面我们是先call和apply 的参数方法。 从上面的myCall 我们可以联想到apply 的指向方法是完全一样的,只是在参数的处理不一样,call(obj,arg1,arg2.....), apply(obj,[ ]) 第二个参数接受的一个数组。
例如: 求一个数组中的最大值
Math.max.apply(null, [6,4,8,3,9]);
apply 和 call的用法基本完全一致,不过他们接受的参数不一样。
Object.prototype.myCall = function(context){
context = context || window;
context.fn = this;
let args = Array.from(arguments).slice(1);
let result = context.fn(...args);
delete context.fn;
return result;
}
Object.prototype.myApply = function(context){
context = context || window;
context.fn = this;
if(arguments[1] instanceof Array){
throw new TypeError(arguments[1] + 'is Array');
}else{
let result = context.fn(arguments[1]);
delete context.fn;
return result;
}
}
网友评论