函數(shù)對象的call()方法和apply()方法

apply()和call()是ES3引入的新方法。為啥要引入這兩個方法呢泰涂?為了更優(yōu)雅的實現(xiàn)面向?qū)ο缶幊痰睦^承鲫竞。另外apply還有一個妙用。

區(qū)分apply,call就一句話:

foo.call(this,arg1,arg2,arg3)==foo.apply(this,arguments)==this.foo(arg1, arg2, arg3)

所以逼蒙,它們的作用一樣从绘,只是方法傳遞的參數(shù)不同。

call(..)和apply(..)的語法中的相同點是是牢,第一個參數(shù)都是一個對象僵井,語法中的區(qū)別是,后面?zhèn)魅氲膮?shù)的形式不同妖泄,call()方法接受的是若干個參數(shù)的列表驹沿,而apply()方法接受的是一個包含多個參數(shù)的數(shù)組。下面分別介紹:

call方法:

語法 fun.call(thisArg[, arg1[, arg2[, ...]]])

thisArg是在fun函數(shù)運行時指定的this值蹈胡。需要注意的是下面幾種情況:

(1)不傳,或者傳null朋蔫,undefined罚渐,函數(shù)中的this指向window對象
(2)傳遞另一個函數(shù)的函數(shù)名,函數(shù)中的this指向這個函數(shù)的引用驯妄,并不一定是該函數(shù)執(zhí)行時真正的this值
(3)值為原始值(數(shù)字荷并,字符串,布爾值)的this會指向該原始值的自動包裝對象青扔,如 String源织、Number、Boolean
(4)傳遞一個對象微猖,函數(shù)中的this指向這個對象

arg1, arg2, ...是指定的參數(shù)列表谈息,多余的參數(shù)將被自動忽略。

//定義函數(shù)a
function a(){
    //輸出函數(shù)a中的this對象
    console.log(this); 
}

//定義函數(shù)b
function b(){} 

//定義對象obj
var obj = {name:'這是一個屌絲'};

a.call(); //window
a.call(null); //window
a.call(undefined);//window
a.call(1); //Number
a.call(''); //String
a.call(true); //Boolean
a.call(b);// function b(){}
a.call(obj); //Object

所以凛剥,foo.call(bar, arg1, arg2, arg3...)的執(zhí)行過程如下侠仇,foo.apply(bar, [arg1, arg2, arg3...])也一樣道理:

第一步,改變foo函數(shù)的this指向;

第二步逻炊,給foo函數(shù)傳參互亮;

第三步,執(zhí)行foo函數(shù)余素。

例豹休,最簡用法:

function foo() {
    console.log( this.a );
}
var obj = {
    a: 2
};
foo.call(obj);  // 2,將call換成apply也成立

foo.call(obj);怎么理解桨吊?像上面說的慕爬,第一步,foo的this指向了obj屏积,第二步傳參略過医窿,第三步,執(zhí)行foo炊林,foo中的console.log( this.a );的this由于指向obj姥卢,所以是打印2≡郏可以再看一個例子:

function greet() {
  var reply = this.person + '是一個' + this.role + '独榴。';
  console.log(reply);
}

var i = {
    person: '我',
    role: '演員'
};

greet.call(i); 
// 我是一個演員。

例奕枝,帶參數(shù)用法:

function foo(a, b) {
    return a + '-' + b + '-' + this.c;
}

var bar = {};
bar.c = 100;

console.log( foo.call(bar, 1, 10) ); // 1-10-100
console.log( foo.apply(bar, [2, 20]) ); // 2-20-100

第一步棺榔,foo的this指向bar的引用,第二步隘道,給foo傳參1和10症歇,第三步,執(zhí)行foo谭梗,得到1-10-100忘晤。

apply方法:

語法與 call() 方法的語法幾乎完全相同,唯一的區(qū)別在于激捏,apply的第二個參數(shù)必須是一個包含多個參數(shù)的數(shù)組(或類數(shù)組對象)设塔。

語法:fun.apply(thisArg[, argsArray])

thisArg同上call的thisArg參數(shù)。

argsArray是一個數(shù)組或者類數(shù)組對象远舅,其中的數(shù)組元素將作為單獨的參數(shù)傳給 fun 函數(shù)闰蛔。如果該參數(shù)的值為null 或 undefined,則表示不需要傳入任何參數(shù)图柏。從ECMAScript 5開始可以使用類數(shù)組對象序六。需要注意:Internet Explorer 8和9不接受類數(shù)組對象。如果傳入類數(shù)組對象爆办,它們會拋出異常难咕。

例,使用apply方法調(diào)用父構(gòu)造函數(shù),實現(xiàn)繼承:

// 定義一個人構(gòu)造函數(shù)余佃,是父構(gòu)造函數(shù)
function Person(name,age)
{
    this.name = name;
    this.age = age;
}

// 定義一個學(xué)生構(gòu)造函數(shù)暮刃,是子構(gòu)造函數(shù)
function Student(name,age,grade)
{
    Person.apply(this, arguments);
    this.grade = grade;
}

// 創(chuàng)建一個學(xué)生實例
var student=new Student("Jack",7,"one");
// 測試
alert("name:" + student.name + "\n" + "age:" + student.age + "\n" + "grade:" + student.grade);
// 學(xué)生類里面并沒有給name和age屬性賦值,為什么又存在這兩個屬性的值呢爆土,這個就是apply的神奇之處

new出student的過程椭懊,我們看看發(fā)生了什么:

new操作符的操作,先復(fù)習(xí)一下:

1步势、創(chuàng)建一個隱藏連接到該函數(shù)的prototype成員的新對象氧猬。
2、將函數(shù)的作用域賦給新對象坏瘩,所以this也被綁定到那個新對象上盅抚。
3、像執(zhí)行普通函數(shù)一樣倔矾,執(zhí)行一遍函數(shù)妄均。
4、返回這個新對象哪自。

于是丰包,第一步,student對象誕生壤巷,第二步邑彪,Student的作用域賦給了student,Student的this也指向了student的引用胧华,第三步寄症,執(zhí)行函數(shù),執(zhí)行函數(shù)又分為下面步驟:

第一句撑柔,Person.apply(this,arguments);瘸爽,它的作用是:

第一步,讓Person的this綁定到Student的引用上铅忿。

第二步,將name,age,grade傳參給Person構(gòu)造函數(shù)灵汪。

第三步檀训,執(zhí)行Person函數(shù)一遍,也就是給Student new出的實例對象添加了name享言、age兩個屬性峻凫。

然后還有一句,this.grade = grade;览露,它是給new出的實例對象添加了一個grade屬性荧琼。

現(xiàn)在的student實例對象就有了三個屬性,當(dāng)然它就可以打印出三個屬性。

為內(nèi)置函數(shù)使用apply方法

聰明的apply用法允許你在某些本來需要寫成遍歷數(shù)組變量的任務(wù)中使用內(nèi)建的函數(shù)命锄。在接下里的例子中我們會使用Math.max/Math.min來找出一個數(shù)組中的最大/最小值堰乔。

我們先復(fù)習(xí)一下Math.max()的常規(guī)用法:

console.log(Math.max(7.25, 7.3, 22, 1, 35)); // 35

雖然很簡單就得到了最大值,但是脐恩,Math.max()只接受參數(shù)列表镐侯,不接受數(shù)組參數(shù)。怎么辦驶冒?你不接受苟翻,自有人接受,apply接受數(shù)組參數(shù)骗污。用apply傳遞數(shù)組參數(shù)崇猫,如下:

var numbers = [5, 6, 2, 3, 7, 11];

var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);

console.log(max);
console.log(min);

// 如果不用apply,只能是手寫需忿,參數(shù)很少的話還好诅炉,多的話會死人的:
var max = Math.max(numbers[0], numbers[1], numbers[2], numbers[3], numbers[4], numbers[5]);
console.log(max);

所以,apply的一個特殊用途就是給只接受參數(shù)列表的函數(shù)傳遞數(shù)組參數(shù)贴谎。

總結(jié)

目前面向?qū)ο缶幊痰睦^承方式汞扎,主要是call/apply方式,和原型鏈方式擅这。IE6開始支持他們所有方式澈魄,放心使用即可。

call和apply唯一區(qū)別在于call接受參數(shù)列表仲翎,apply接受數(shù)組參數(shù)或類數(shù)組參數(shù)痹扇。利用apply的這個特性,可以給任意不接受數(shù)組參數(shù)的原生函數(shù)改寫成支持接受數(shù)組參數(shù)溯香。其他時候根據(jù)實際情況選擇用call還是apply鲫构。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市玫坛,隨后出現(xiàn)的幾起案子结笨,更是在濱河造成了極大的恐慌,老刑警劉巖湿镀,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炕吸,死亡現(xiàn)場離奇詭異,居然都是意外死亡勉痴,警方通過查閱死者的電腦和手機赫模,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蒸矛,“玉大人胸嘴,你說我怎么就攤上這事≌都溃” “怎么了劣像?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長停忿。 經(jīng)常有香客問我驾讲,道長,這世上最難降的妖魔是什么席赂? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任吮铭,我火速辦了婚禮,結(jié)果婚禮上颅停,老公的妹妹穿的比我還像新娘谓晌。我一直安慰自己,他們只是感情好癞揉,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布纸肉。 她就那樣靜靜地躺著,像睡著了一般喊熟。 火紅的嫁衣襯著肌膚如雪柏肪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天芥牌,我揣著相機與錄音烦味,去河邊找鬼。 笑死壁拉,一個胖子當(dāng)著我的面吹牛谬俄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播弃理,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼溃论,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了痘昌?” 一聲冷哼從身側(cè)響起钥勋,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辆苔,沒想到半個月后笔诵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡姑子,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了测僵。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片街佑。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡谢翎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沐旨,到底是詐尸還是另有隱情森逮,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布磁携,位于F島的核電站褒侧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏谊迄。R本人自食惡果不足惜闷供,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望统诺。 院中可真熱鬧歪脏,春花似錦、人聲如沸粮呢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽啄寡。三九已至豪硅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間挺物,已是汗流浹背懒浮。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留姻乓,地道東北人嵌溢。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像蹋岩,于是被迫代替她去往敵國和親赖草。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容