call()和apply()

一. call()

語法定義

fun.call(thisArg[, arg1[, arg2[, ...]]])
  • thisArg
    在fun函數運行時指定的是this值。在非嚴格模式下,thisArg爲null和undefined的this值會指向全局對象(瀏覽器中就是window對象),同時值爲原始值(數字,字符串,布爾值)的this會指向該原始值的自動包裝對象segmentfault

  • arg1,arg2,……
    指定的對象的參數列表數組

方法描述

  • 在運行的函數中調用另外一個Object的this瀏覽器

  • 經過 call 方法,你能夠在一個對象上繼承另外一個對象上的方法app

應用

1.使用call鏈接對象的構造器(實現繼承)

繼承某個對象的方法,對於一些公用的方法能夠採起這樣的方式Object.apply(this,arguments),不必重複聲明相同的方法。ide

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和undefinedoop

方法描述

與call()相似,只是傳入參數的方式不一樣。this

實際應用

1. 求出數組的中的最大值

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

2. 實現繼承

與call() 相似prototype

3.確保this指向

能夠看一下hoverdelay.js的源碼(這段代碼是解決hover事件重複觸發的bug),setTimeout會改變this的指向(具體能夠看一下這篇文章),可用that=this,保存以前的this指向,再用apply或者call重定向爲原來的this環境。code

(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?

相關文章
相關標籤/搜索