JavaScript中call(),apply()和bind()的区别

150 阅读1分钟
apply()、call()和bind()都是用来重定义this这个对象的。

当我们在一个普通函数里面或者在全局作用域调用this时,this指向的是windows。而当我们创建了一个对象,在对象里面调用this时指向的是当前对象。

比如:

    let name = "王五"let zhangsan = {
        name: "张三",
        run: function () {
            console.log(`${this.name}在跑步`)
        },
    }
zhangsan.run();

输出结果:

    张三在跑步

上面的代码我在对象外创建了一个变量name,并赋值180。在创建了一个对象zhangsan,并添加了两个属性,分别是name和run,run是一个函数。在调用张三的run属性时,控制台打印的是"张三在跑步",而不是"王五在跑步"。 这说明这个时候this指向了张三这个对象。

而apply()、call()和bind()都是用来重定义this这个对象的。

看下面的代码:

    let lisi = {
        name: '李四',
    }
    zhangsan.run.apply(lisi);
    zhangsan.run.call(lisi);
    zhangsan.run.bind(lisi)();

输出结果:

    李四在跑步
    李四在跑步
    李四在跑步

我创建了一个lisi对象,同时添加了一个属性name,并赋值为'李四'。同时调用了zhangsan的run,不同的是我在后面使用了apply()、call()及bind()。输出的结果都是'李四在跑步',说明这时候run函数内部的this已经指向了lisi这个对象,而不是原本的zhangsan这个对象。

以上除了bind方法后面多了个()外 ,结果返回都一致! 因为bind 返回的是一个新的函数,你必须调用它才会被执行。

apply()、call()及bind()的区别
    let zhangsan = {
        name: "张三",
        age: 18,
        run: function () {
            console.log(`${this.name}在跑步`)
        },
        getInfo: function (from, to) {
            console.log(`我的名字叫'${this.name}',我从${from}来,要到${to}去`)
        }
    }
    let lisi = {
        name: '李四',
        age: 25,
    }
    zhangsan.getInfo.apply(lisi, ['火星', '木星']);
    zhangsan.getInfo.call(lisi, '火星', '木星');
    zhangsan.getInfo.bind(lisi, '火星', '木星')();

输出结果:

我的名字叫'李四',我从火星来,要到木星去
我的名字叫'李四',我从火星来,要到木星去
我的名字叫'李四',我从火星来,要到木星去

在zhangsan新添加了一个getInfo属性,是一个函数,分别有两个参数from和to。从上面的输出结果可以得出结论,三种方式作用是一样的,区别就在于传参方式不同。

结论:

call 、bind 、 apply这三个函数的第一个参数都是this的指向对象。
call的参数是直接放进去的,第二第三第n个参数全都用逗号分隔,直接放到后面
apply的所有参数都必须放在一个数组里面传进去
bind除了返回是函数以外,它的参数和call一样。