简单实现apply、bind、call方法

55 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第十三天,点击查看活动详情

题引:

在我们日常的开发中,我们都会经常使用this这个关键字,该关键字关联了当下的作用域。但随着日常业务的开发,我们有时候会丢失对this的追踪,就需要确保this的指向是正确的,就会使用像apply、call、bind进行显示绑定,今天我们将主要来实现它们内部的实现。

正文:

其实它们三者是很相似的,实现一个就可以举一反三。 我们首先实现apply

apply方法第一个参数为this指向,第二个参数为数组

Function.prototype.myApply = function (thisArg, argArray) {
    //1.判断this是不是函数
    if (typeof this !== "function") {
        throw new TypeError("Error");
    }
    //1.获取要执行的函数
    var fn = this;
    //2.获取需要改变的this指向
    thisArg =(thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window;
    //3.执行改变后的this的函数
    thisArg.fn = fn;
    //4.判断是不是传参
    argArray ? thisArg.fn(...argArray) : thisArg.fn();
    delete thisArg.fn;
};

function foo(a, b) {
console.log("我被调用了", this, a, b);
}
foo.myApply(123, [1, 2]);

function bar(n) {
console.log("我被调用", n);
}
bar.myApply(123, [1]);

function bar1() {
console.log("我被调用");
}
bar1.myApply(123);

call跟apply极其相像,只在参数判断有所不同

Function.prototype.myApply = function (thisArg, ...args) {
    //1.判断this是不是函数
    if (typeof this !== "function") {
        throw new TypeError("Error");
    }
    //1.获取要执行的函数
    var fn = this;
    //2.获取需要改变的this指向
    thisArg =(thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window;
    //3.执行改变后的this的函数
    thisArg.fn = fn;
    //4.不管有没有传参都解构
    thisArg.fn(...args)
    delete thisArg.fn;
};

function foo(a, b) {
    console.log("我被调用了", this, a, b);
}
foo.myApply(123, [1, 2]);

function bar(n) {
    console.log("我被调用", n);
}
bar.myApply(123, [1]);

function bar1() {
    console.log("我被调用");
}
bar1.myApply(123);

bind的方法跟call的参数方式是一样的,区别在于bind返回一个函数变量

Function.prototype.myBind = function(thisArg,...args1){ 
    //1.判断this是不是函数
    if (typeof this !== "function") {
        throw new TypeError("Error");
    }
    thisArg =thisArg !== null && thisArg !== undefined ? Object(thisArg) : window;
    thisArg.fn = this
    
    //区别在这,这里要使用闭包返回一个函数,该函数会执行已经指定好this的函数。   
    return function(...args2){
        thisArg.fn(...args1,...args2)
        delete thisArg.fn
    }
}

function foo(a, b, c, d) {
    console.log("我被调用了", this, a, b, c, d);
}

var result1 = foo.myBind(123, 1, 2, 3, 4);
result1();
var result2 = foo.myBind(123, 1);
result2(2, 3, 4);

以上就是三种显示绑定内部的实现。