js函數(shù)的調(diào)用方式以及apply, call, bind用法總結

一携狭、函數(shù)4種調(diào)用的方式

  • 1.函數(shù)模式
  • 2.方法模式
  • 3.構造函數(shù)模式
  • 4.上下文模式(也有叫apply模式)

apply, call, bind用法

在JavaScript 中砰识,call、apply 和 bind 是 Function 對象自帶的三個方法泡一,這三個方法的主要作用是改變函數(shù)調(diào)用過程中的 this 指向

1. apply(thisArgs[,args[]])

  • 第一個參數(shù)指定函數(shù)體內(nèi)this對象的指向
    thisArgs 的取值有以下4種情況:
    • 不傳留潦,或者傳null,undefined鸭叙, 非嚴格模式下 函數(shù)中的 this 指向 window 對象闯第。 嚴格模式不傳undefined 函數(shù)中this指向undefined旺聚。傳入null函數(shù)中this指向null
    • 傳遞另一個函數(shù)的函數(shù)名织阳,函數(shù)中的 this 指向這個函數(shù)的引用
    • 傳遞字符串、數(shù)值或布爾類型等基礎類型砰粹,非嚴格模式函數(shù)中的 this 指向其對應的包裝對象唧躲,如 StringNumberBoolean惊窖。嚴格模式刽宪,指向傳入的值
    • 傳遞一個對象,函數(shù)中的 this 指向這個對象
  • 第二個參數(shù)為一個帶下標的集合界酒,可以是數(shù)組或類數(shù)組,apply方法把這個集合中的元素作為參數(shù)傳遞給被調(diào)用的函數(shù)
var func = function(a, b, c) {
  console.log([a, b, c]); // [1,2,3]
}
func.apply(null, [1,2,3])

apply 和 call 的唯一區(qū)別是第二個參數(shù)的傳遞方式不同圣拄,apply 的第二個參數(shù)必須是一個數(shù)組,而 call 允許傳遞一個參數(shù)列表毁欣。值得你注意的是庇谆,雖然 apply 接收的是一個參數(shù)數(shù)組,但在傳遞給調(diào)用函數(shù)時凭疮,卻是以參數(shù)列表的形式傳遞饭耳,我們看個簡單的例子:

function b(x,y,z){
    console.log(x,y,z);
}
 
b.apply(null,[1,2,3]); // 1 2 3

2. call(thisArgs [,args...])

該方法可以傳遞一個thisArgs參數(shù)和一個參數(shù)列表,thisArgs 指定了函數(shù)在運行期的調(diào)用者执解,也就是函數(shù)中的 this 對象寞肖,而參數(shù)列表會被傳入調(diào)用函數(shù)中。
thisArgs 的取值有以下4種情況:

  • 不傳衰腌,或者傳null,undefined新蟆, 非嚴格模式下 函數(shù)中的 this 指向 window 對象。 嚴格模式不傳右蕊、undefined 函數(shù)中this指向undefined琼稻。傳入null函數(shù)中this指向null
  • 傳遞另一個函數(shù)的函數(shù)名,函數(shù)中的 this 指向這個函數(shù)的引用
  • 傳遞字符串饶囚、數(shù)值或布爾類型等基礎類型帕翻,非嚴格模式函數(shù)中的 this 指向其對應的包裝對象,如 String萝风、Number嘀掸、Boolean嚴格模式规惰,指向傳入的值
  • 傳遞一個對象横殴,函數(shù)中的 this 指向這個對象
function a(){
    console.log(this); //輸出函數(shù)a中的this對象
}
function b(){} //定義函數(shù)b
 
var obj = {name:'onepixel'}; //定義對象obj
// 嚴格模式
a.call(); //undefined
a.call(null); //null
a.call(undefined);//undefined
a.call(1); //1
a.call(''); // ''
a.call(true); //true
a.call(b);// function b(){}
a.call(obj); //Object
 // 非嚴格模式
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

當使用call或則apply的時候,如果我們傳入的第一個參數(shù)是null.函數(shù)體內(nèi)的this會指向默認的宿主對象卿拴,在游覽器中則是window

var func = function( a, b, c ){
  alert ( this === window );    // 輸出true
};
func.apply( null, [ 1, 2, 3 ] );

但如果是在嚴格模式下,函數(shù)體內(nèi)的this還是為null:

var func = function( a, b, c ){    
  "use strict";    
  alert ( this === null );     // 輸出true
}
func.apply( null, [ 1, 2, 3 ] );

有時候我們使用call或者apply的目的不在于指定this指向梨与,而是另有用途堕花,比如借用其他對象的方法。
那么我們可以傳入null來代替某個具體的對象:
Math.max.apply( null, [ 1, 2, 5, 3, 4 ] ) // 輸出:5

call和apply的用途

確定函數(shù)內(nèi)部this指向
var obj1={
  name: '李小龍'
}
var obj2={
  name: '蕭薰'
}
window.name = 'window'
var getName = function(){
  console.log(this.name)
};
getName(); //輸出:window
getName.call(obj1); //輸出:李小龍
getName.call(obj2); //輸出:蕭薰

當執(zhí)行getName.call( obj1 )這句代碼時粥鞋,getName函數(shù)體內(nèi)的this就指向obj1對象

  • this 錯誤的情況
document.getElementById( 'div1' ).onclick = function(){    
  alert( this.id );            // 輸出:div1    
  var func = function(){       
    alert ( this.id );        // 輸出:undefined    
  }    
  func();
};
  • 修正this
document.getElementById( 'div1' ).onclick = function(){    
  var func = function(){        
    alert ( this.id );        // 輸出:div1    
  }    
  func.call( this );
};

3. bind(thisArgs [,args...])

bind是ES5 新增的一個方法缘挽,它的傳參和call類似,但又和 call/apply 有著顯著的不同,即調(diào)用 call 或 apply 都會自動執(zhí)行對應的函數(shù)壕曼,而 bind 不會執(zhí)行對應的函數(shù)苏研,只是返回了對函數(shù)的引用。粗略一看腮郊,bind 似乎比call/apply 要落后一些摹蘑,那ES5為什么還要引入bind 呢?

其實轧飞,ES5引入 bind 的真正目的是為了彌補 call/apply 的不足衅鹿,由于 call/apply 會對目標函數(shù)自動執(zhí)行,從而導致它無法在事件綁定函數(shù)中使用过咬,因為事件綁定函數(shù)不需要我們手動執(zhí)行大渤,它是在事件被觸發(fā)時由JS 內(nèi)部自動執(zhí)行的。而 bind 在實現(xiàn)改變函數(shù) this 的同時又不會自動執(zhí)行目標函數(shù)掸绞,因此可以完美的解決上述問題泵三,看一個例子就能明白:

var obj = {name:'onepixel'};
/**
 * 給document添加click事件監(jiān)聽,并綁定onClick函數(shù)
 * 通過bind方法設置onClick的this為obj衔掸,并傳遞參數(shù)p1,p2
 */
document.addEventListener('click',onClick.bind(obj,'p1','p2'),false);
 
//當點擊網(wǎng)頁時觸發(fā)并執(zhí)行
function onClick(a,b){
    console.log(
            this.name, //onepixel
            a, //p1
            b  //p2
    )
}

參考JavaScript設計模式與開發(fā)實踐 烫幕、 一像素 博客園

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市具篇,隨后出現(xiàn)的幾起案子纬霞,更是在濱河造成了極大的恐慌,老刑警劉巖驱显,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诗芜,死亡現(xiàn)場離奇詭異,居然都是意外死亡埃疫,警方通過查閱死者的電腦和手機伏恐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栓霜,“玉大人翠桦,你說我怎么就攤上這事「炻” “怎么了销凑?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長仅炊。 經(jīng)常有香客問我斗幼,道長,這世上最難降的妖魔是什么抚垄? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任蜕窿,我火速辦了婚禮谋逻,結果婚禮上,老公的妹妹穿的比我還像新娘桐经。我一直安慰自己毁兆,他們只是感情好,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布阴挣。 她就那樣靜靜地躺著气堕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪屯吊。 梳的紋絲不亂的頭發(fā)上送巡,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音盒卸,去河邊找鬼骗爆。 笑死,一個胖子當著我的面吹牛蔽介,可吹牛的內(nèi)容都是我干的摘投。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼虹蓄,長吁一口氣:“原來是場噩夢啊……” “哼犀呼!你這毒婦竟也來了?” 一聲冷哼從身側響起薇组,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤外臂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后律胀,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宋光,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年炭菌,在試婚紗的時候發(fā)現(xiàn)自己被綠了罪佳。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡黑低,死狀恐怖赘艳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情克握,我是刑警寧澤蕾管,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布芯咧,位于F島的核電站古劲,受9級特大地震影響,放射性物質發(fā)生泄漏空执。R本人自食惡果不足惜勋眯,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一婴梧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧客蹋,春花似錦塞蹭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至辆琅,卻和暖如春漱办,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背婉烟。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工娩井, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人似袁。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓洞辣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親昙衅。 傳聞我的和親對象是個殘疾皇子扬霜,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

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