call apply bind 学习及自己手写实现!

2019-05-22  本文已影响0人  不敢大声说话的web小萌新

学习分析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;
    }
}
上一篇下一篇

猜你喜欢

热点阅读