重拾JavaScript基础-手写call/apply/bind

92 阅读1分钟

坎坎坷坷一路走来,js基础知识大部分停留在了会用阶段,其中实现原理反而似懂非懂的了,加上近几年大环境特别差,危机感特别强,故重新整理学习一遍js基础知识,本篇文章记录js显示绑定this的三种方式,就是call,apply以及bind函数。

我们先先说下三个函数的区别:

  • call: call 函数第一个参数是新this的对象,后面跟着的是参数列表, call(this, arg1,arg2,arg3,..);

  • apply: applycall 相同,不同点在于 call 第一个参数后面跟着的是参数列表,而 apply 第一个参数后是参数数组,apply(this, [arg1,arg2,...]);

  • bind: bind 函数接受参数方式与 call 相同,不同于 callapply 的点在于, callapply 会立即执行函数,而 bind 会返回一个新函数,需要手动调用。let newFun = fn.bind(this, arg1, arg2, ...);

下面我们手动模拟一下这三个函数的实现:

1. call 模拟

Function.prototype.myCall = function() {
    if(typeof this !== 'function' ) throw TypeError('not a function');
    const [context, ...args] = [...arguments]
    context = context || window;
    context.fn = this;
    let res = context.fn(...args);
    delete context.fn;
    return res;
}

2. apply 模拟

Function.prototype.myApply = function(context) {
    if(typeof this !== 'function' ) throw TypeError('not a function');
    context = context || window;
    context.fn = this;
    let args = [].prototype.slice.call(arguments ,1);
    let res = context.fn(args);
    delete context.fn;
    return res;
}

3. bind 模拟

Function.prototype.myBind = function(context) {
    if(typeof this !== 'function' ) throw TypeError('not a function');
    let _this = this;
    let args = [].prototype.slice.call(arguments, 1);
    function TempFun () {};
    let bindFun = function() {
        let bindArgs = [].prototype.slice.call(arguments);
        return _this.apply(this instanceof bindFun ? this : context, args.concat(bindArgs));
    }
    TempFun.prototype = this.prototype;
    bindFun.prototype = new TempFun();
    return bindFun;
}

OK,今天的基础复习结束。有问题欢迎大家指出,谢谢~