3

一. call()

语法定义

fun.call(thisArg[, arg1[, arg2[, ...]]])
  • thisArg
    在fun函数运行时指定的是this值。在非严格模式下,thisArg为null和undefined的this值会指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象

  • arg1,arg2,……
    指定的对象的参数列表

方法描述

  • 在运行的函数中调用另一个Object的this

  • 通过 call 方法,你可以在一个对象上继承另一个对象上的方法

应用

1.使用call连接对象的构造器(实现继承)

继承某个对象的方法,对于一些公用的方法可以采取这样的方式Object.apply(this,arguments),没必要重复声明相同的方法。

function People(name, age) {
  this.name = name;
  this.age= age;
  this.sayName=function(){
    console.log("my Name is "+name);
   }
}

function one(name, age) {
   People.call(this, name, age);
}

function two(name, age) {
   People.call(this, name, age);
}

var one= new one('Jim', 25);
var two= new two('Tom', 40);
one.sayName(); //my Name is Jim
two.sayName(); //my Name is Tom

2.使用call引用一个函数且指定上下文环境

function showContent(){
    var content="这篇文章的标题是"+this.title+" 作者是"+this.author;
    console.log(content);
}
var article={
title:"hello world",
author:"coder"
}
showContent.call(article) //这篇文章的标题是hello world 作者是coder

二. apply()

语法定义

fun.apply(thisArg, [argsArray]) 
  • thisArg
    在fun函数运行时指定的是this值。在非严格模式下,thisArg为null和undefined的this值会指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象

  • arg1,arg2,……
    一个数组或者类数组对象,可为null和undefined

方法描述

与call()类似,只是传入参数的方式不同。

实际应用

1. 求出数组的中的最大值

function getMax(arr){
    return Math.max.apply(null,arr)
}

2. 实现继承

与call() 类似

3.确保this指向

可以看一下hoverdelay.js的源码(这段代码是解决hover事件重复触发的bug),setTimeout会改变this的指向(具体可以看一下这篇文章),可用that=this,保存之前的this指向,再用apply或者call重定向为原来的this环境。

(function($){
    $.fn.hoverDelay = function(options){
        var defaults = {
            hoverDuring: 200,
            outDuring: 200,
            hoverEvent: function(){
                $.noop();
            },
            outEvent: function(){
                $.noop();    
            }
        };
        var sets = $.extend(defaults,options || {});
        var hoverTimer, outTimer, that = this;
        return $(this).each(function(){
            $(this).hover(function(){
                clearTimeout(outTimer);
                //使用apply()
                hoverTimer = setTimeout(function(){sets.hoverEvent.apply(that)}, sets.hoverDuring);
            },function(){
                clearTimeout(hoverTimer);
                outTimer = setTimeout(function(){sets.outEvent.apply(that)}, sets.outDuring);
            });    
        });
    }      
})(jQuery);

4. Array.prototype.shift.call(arguments)

Array.prototype.shift.call(arguments),arguments是一个类数组对象,虽然有下标,但不是真正的数组,没有shift方法,这时可以通过call或者apply方法调用Array.prototype中的shift方法。

三.区别

MDN原文:

While the syntax of this function is almost identical to that of call(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.

call()和apply()的用法几乎相同,不同之处在于call()接受的是一个参数列表,而apply()接受的是一个数组参数。(方便记忆的小技巧:Apply for array and Call for comma.)

function showContent(title,author){
    var content="这篇文章的标题是"+title+" 作者是"+author;
    console.log(content);
}
showContent.apply(undefined, ["hello", "Jim"]); //这篇文章的标题是hello 作者是Jim
showContent.call(undefined, "world", "Join"); //这篇文章的标题是world 作者是Join

四.参考资料

  1. Function.prototype.call()

  2. Function.prototype.apply()

  3. What is the difference between call and apply?


hopeCoder
560 声望47 粉丝

不忘初心,方得始终