javascript中call和apply的区别与联系

apply接收两个参数:

  1. 指定了函数体内this对象的指向;
  2. 一个带下标的集合(可以是数组或类数组)
var func = function(a, b, c){
    console.log([a, b, c]);  // 输出[1, 2, 3]
}

func.apply(null, [1, 2, 3]);

call接收一个或多个参数:

  1. 指定了函数体内this对象的指向;
  2. 从第二个参数往后,每个参数被依次传入函数;
var func = function(a, b, c){
    console.log([a, b, c]);  // 输出[1, 2, 3]
}

func.call(null, 1, 2, 3);

从上面的两个例子我们可以看出apply和call的唯一的区别就是:传入参数的数量是否固定。通常call在以下情况使用:

  1. 函数传入的参数数量确定;
  2. 需要清晰地表达形参和实参之间的对应关系

apply和call使用注意点:

  1. 如果传入的第一个参数是null,this就会指向全局对象,在浏览器上面是window,在nodejs上是global;

  2. 在1的条件下,如果使用严格模式,函数体内的this还是为null;
    var func = function(a, b, c){
        "use strict";
        console.log(this === null);  // 输出true
    }
    
    func.apply(null, [1, 2, 3]);

     

apply和call的用途:

  • 借用其他对象的方法:

    // 例一
    Math.max.apply(null, [1, 2, 5, 3, 4]);  // 输出5
    
    // 例二
    var A = function(name){
        this.name = name;
    };
    
    var B = function(){
        A.apply(this, arguments);
    };
    
    B.prototype.getName = function(){
        return this.name;
    };
    
    var b = new B('sven');
    console.log(b.getName());  // 输出:'sven'

     

  • 改变this的指向:

    var obj1 = {
        name: 'sven',
    };
    
    var obj2 = {
        name: 'anne',
    };
    
    global.name = 'global';
    
    var getName = function(){
        console.log(this.name);
    }
    
    getName();  // 输出:global
    getName.call(obj1);  // 输出:sven
    getName.call(obj2);  // 输出: anne

     

  •  Function.prototype.bind的模拟实现:

    // 简单实现
    Function.prototype.bind = function(context){
        var self = this;
        return function(){
            return self.apply(context, arguments);
        }
    }
    
    var obj = {
        name: 'sven',
    }
    
    var func = function(){
        console.log(this.name);  // 输出:sevn
    }.bind(obj);
    
    func();
    
    // 复杂实现
    Function.prototype.bind = function(){
        var self = this,
            context = [].shift.call(arguments),
            args = [].slice.call(arguments);
        return function(){
            return self.apply(context, [].concat.call(args, [].slice.call(arguments)));
        }
    }
    
    var obj = {
        name: 'sven',
    };
    
    var func = function(a, b, c, d){
        console.log(this.name);  // 输出:sven
        console.log([a, b, c, d]);  // 输出:[1, 2, 3, 4]
    }.bind(obj, 1, 2);
    
    func(3, 4);

    本篇博客参考自JavaScript设计模式与开发实践,[p29-p33]

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mannuandeyangguang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值