`apply`,`bind`,`call`解析?

267 阅读1分钟

callapply代码

    // myApply
    Function.prototype.myApply = function(context) {
        if (typeof this !== 'function') {
            throw new Error('type error');
        }
        context.fn = this;
        let args = [...arguments][1];
        let result;
        if(args) {
            result = context.fn(args);
        } else {
            result = context.fn();
        }
        delete context.fn;
        return result;
    }
    // myCall
    Function.prototype.myCall = function(context) {
        if (typeof this !== 'function') {
            throw new Error('type error');
        }
        context.fn = this;
        let result = context.fn([...arguments].slice(1));
        delete context.fn;
        return result;
    }
    var cat = {
        name: "cat",
        speak: function () {
          console.log(this.name);
          console.log(arguments);
        },
    };
    var dog = {
        name: "dog",
        speak: function (arr) {
          console.log(this.name);
          console.log(arguments);
        },
    };
    cat.speak.myCall(dog, 1, 2, 3);
    cat.speak.myApply(dog, [2, 3]);

callapply共同点

callapply函数都能改变指针,其实内部就是为传入的上下文赋值一个新的函数fn,然后调用这个函数

callapply不同点

callapply参数不同,apply(context, arr)第一个参数是上下文,第二个参数是数组或者类数组;call(context, obj1,obj2,...)第一个参数是上下文,剩下的参数可以有多个,两者最后都是把传入的参数转化为数组调用

bind代码

    // myBind
    Function.prototype.myBind = function (context) {
        if (typeof this !== "function") {
          throw new Error("type error");
        }
        let self = this;
        let args = [...arguments].slice(1);
        return function () {
          self.apply(context, args.concat([...arguments]));
        };
    };
    function foo() {
        console.log("arguments : ", arguments);
        console.log(this.a);
    }
    var obj = { a: 2 };
    var bar = foo.myBind(obj,123);
    bar(23); // 2

bind,call,apply共同点

三者都能改变函数的指针

bind,call,apply不同点

bind(context,obj1,obj2,...)返回的是一个新的函数,bind函数可以实现多次传参,bind函数改变指针,其实也是通过apply函数