手写 call()方法

call

我们先看个例子:

var obj = {
  value: "贝小米",
};

function fn() {
  console.log(this.value);
}

fn.call(obj); // 贝小米

call主要做了两件事:

  • 改变 this 指向,由原来的window改为obj
  • 执行 fn 函数

如果要自己写的话,先考虑改造 obj 对象:

var obj={
    value:'贝小米',
    fn:function() {
        console.log( this.value );
    }
}

obj.fn();  // '贝小米'

 这里同样实现了 this 指向 obj 对象、执行 fn 函数两件事,但是在 obj 对象身上平白多了一个函数,这肯定不行,那就在函数调用完之后把它删除掉,用 delete obj.fn 实现。

obj.fn = fn;
obj.fn();
delete obj.fn;

按照这个思路我们就写出来了:

// 手写call(),根据原型链,每个函数都可以访问到这个我们自定义的方法啦,直接写function让别的函数的调用的话会报错。
Function.prototype.myCall = function ( context ) {
     // 判断调用对象是不是函数,不是就直接抛出错误
     if ( typeof this !== 'function' ) {
         throw new Error("Type error");
     }

     // 获取参数,除了第一个参数(context中可枚举的属性)
     let args = [...arguments].slice(1);
     let result = null;

     // 判断context是否有传值,没有则默认为window
     context = context || window;
            
     // 将被调用的方法设置为context的属性(修改this指向为context)
     context.fn = this;

     // 执行要被调用的方法(参数为传入的参数)
     result = context.fn(...args);
            
     // 删除手动增加的属性方法
     delete context.fn;

     // 返回执行结果
        return result;
}

function testFun () {
     console.log(this.name);
}

var name = '王五';
var obj = {
     name: '贝小米',
};

testFun.myCall(obj);   //'贝小米'

注意点:

         1、我们手写的 myCall 方法要添加到构造函数 Function 的原型对象上,这个其他的函数才能使用这个方法,否则会报错,也就是第一句 Function.prototype.myCall = function () { };        


bind

bind 有如下特性:

  • 1、指定 this
  • 2、传入参数
  • 3、返回一个函数
  • 4、柯里化【是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术,是闭包的一个应用

       例:fn(a,b,c) = > fn(a)(b)(c)

猜你喜欢

转载自blog.csdn.net/m0_48571414/article/details/127282721
今日推荐