javascript中call和apply的区别与联系

    xiaoxiao2022-07-05  173

    apply接收两个参数:

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

    call接收一个或多个参数:

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

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

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

    apply和call使用注意点:

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

    在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]

    最新回复(0)