js手动实现call,apply,bind

原文https://www.jianshu.com/p/3b69fb0d4c2f 

我也不知道为什么只能显示一部分  好气哦  看原文吧 

先分析下3个方法的作用

  • 改变this的指向。
  • 传入参数。
  • call apply返回函数结果, bind 返回新函数

call

改变this的指向 

首先我们知道,对象上的方法,在调用时,this是指向对象的。

let o = {
    fn:function(){
        console.log(this);
    }
}
o.fn() //  Object {fn: function}  
// 函数原型上添加 myCall方法 来模拟call
Function.prototype.myCall = function(obj){
    //我们要让传入的obj成为, 函数调用时的this值.
    obj._fn_ = this;  //在obj上添加_fn_属性,值是this(要调用此方法的那个函数对象)。
    obj._fn_();       //在obj上调用函数,那函数的this值就是obj.
    delete obj._fn_; // 再删除obj的_fn_属性,去除影响.
    //_fn_ 只是个属性名 你可以随意起名,但是要注意可能会覆盖obj上本来就有的属性
}

下面测试一下

let test = {
    name:'test'
}
let o = {
    name:'o',
    fn:function(){
        console.log(this.name);
    }
}
o.fn() // "o"
o.fn.call(test) // "test"
o.fn.myCall(test) // "test"

传入参数

  • 最简单实现,用ES6
// 只需要在原来的基础上 用下拓展运算符 剩余运算符即可
Function.prototype.myCall = function(obj,...arg){
    obj._fn_ = this;
    obj._fn_(...arg);
    delete obj._fn_;
}
//测试
let test = {
    name:'test'
}
let o = {
    name:'o',
    fn:function(){
        console.log(this.name, ...arguments);  //这里把参数显示一下
    }
}
o.fn(1,2,3) // "o" 1 2 3
o.fn.call(test,1,2,3) // "test" 1 2 3
o.fn.myCall(test,1,2,3) // "test" 1 2 3
// 没问题
  • 用eval 方法
    eval方法,会对传入的字符串,当做JS代码进行解析,执行。
Function.prototype.myCall = function(obj){
    let arg = [];
    for(let i = 1 ; i<arguments.length ; i++){
        arg.push( 'arguments[' + i + ']' ) ;
        // 这里要push 这行字符串  而不是直接push 值
        // 因为直接push值会导致一些问题
        // 例如: push一个数组 [1,2,3]
        // 在下面

猜你喜欢

转载自blog.csdn.net/weixin_41910848/article/details/82145112
今日推荐