JavaScript中的call和apply的用途以及區(qū)別
apply 接受兩個(gè)參數(shù),第一個(gè)參數(shù)指定了函數(shù)體內(nèi)this 對(duì)象的指向,第二個(gè)參數(shù)為一個(gè)帶下標(biāo)的集合,這個(gè)集合可以為數(shù)組,也可以為類數(shù)組,apply 方法把這個(gè)集合中的元素作為參數(shù)傳遞給被調(diào)用的函數(shù):
var func = function( a, b, c ){
alert ( [ a, b, c ] ); // 輸出 [ 1, 2, 3 ]
};
func.apply( null, [ 1, 2, 3 ] );
在這段代碼中,參數(shù) 1、2、3 被放在數(shù)組中一起傳入func函數(shù),它們分別對(duì)應(yīng)func參數(shù)列表中的a、b、c。
call 傳入的參數(shù)數(shù)量不固定,跟apply 相同的是,第一個(gè)參數(shù)也是代表函數(shù)體內(nèi)的this 指向,從第二個(gè)參數(shù)開始往后,每個(gè)參數(shù)被依次傳入函數(shù):
var func = function( a, b, c ){
alert ( [ a, b, c ] ); // 輸出 [ 1, 2, 3 ]
};
func.call( null, 1, 2, 3 );
當(dāng)調(diào)用一個(gè)函數(shù)時(shí),JavaScript 的解釋器并不會(huì)計(jì)較形參和實(shí)參在數(shù)量、類型以及順序上的區(qū)別,JavaScript 的參數(shù)在內(nèi)部就是用一個(gè)數(shù)組來表示的。從這個(gè)意義上說,apply比call的使用率更高,我們不必關(guān)心具體有多少參數(shù)被傳入函數(shù),只要用apply 一股腦地推過去就可以了。call是包裝在apply上面的一顆語法糖,如果我們明確地知道函數(shù)接受多少個(gè)參數(shù),而且想一目了然地表達(dá)形參和實(shí)參的對(duì)應(yīng)關(guān)系,那么也可以用call 來傳送參數(shù)。
call和apply的用途
1. 改變this 指向
call 和apply 最常見的用途是改變函數(shù)內(nèi)部的this 指向,我們來看個(gè)例子:
var obj1 = {
name: 'sven'
};
var obj2 = {
name: 'anne'
};
window.name = 'window';
var getName = function(){
alert ( this.name );
};
getName(); // 輸出: window
getName.call( obj1 ); // 輸出: sven
getName.call( obj2 ); // 輸出: anne
當(dāng)執(zhí)行g(shù)etName.call( obj1 )這句代碼時(shí),getName 函數(shù)體內(nèi)的this 就指向obj1 對(duì)象,所以此處的
var getName = function(){
alert ( this.name );
};
實(shí)際上相當(dāng)于:
var getName = function(){
alert ( obj1.name ); // 輸出: sven
};
在實(shí)際開發(fā)中,經(jīng)常會(huì)遇到this指向被不經(jīng)意改變的場(chǎng)景,比如有一個(gè)div節(jié)點(diǎn),div節(jié)點(diǎn)的onclick 事件中的this 本來是指向這個(gè)div的:
document.getElementById( 'div1' ).onclick = function(){
alert( this.id ); // 輸出:div1
};
假如該事件函數(shù)中有一個(gè)內(nèi)部函數(shù)func,在事件內(nèi)部調(diào)用func 函數(shù)時(shí),func 函數(shù)體內(nèi)的this就指向了window,而不是我們預(yù)期的div,見如下代碼:
document.getElementById( 'div1' ).onclick = function(){
alert( this.id ); // 輸出:div1
var func = function(){
alert ( this.id ); // 輸出:undefined
}
func();
};
這時(shí)候我們用call 來修正func 函數(shù)內(nèi)的this,使其依然指向div:
document.getElementById( 'div1' ).onclick = function(){
var func = function(){
alert ( this.id ); // 輸出:div1
}
func.call( this );
};
2. Function.prototype.bind
大部分高級(jí)瀏覽器都實(shí)現(xiàn)了內(nèi)置的Function.prototype.bind,用來指定函數(shù)內(nèi)部的this 指向,即使沒有原生的Function.prototype.bind 實(shí)現(xiàn),我們來模擬一個(gè)也不是難事,代碼如下:
Function.prototype.bind = function( context ){
var self = this; // 保存原函數(shù)
return function(){ // 返回一個(gè)新的函數(shù)
return self.apply( context, arguments ); // 執(zhí)行新的函數(shù)的時(shí)候,會(huì) 把之前傳入的context
// 當(dāng)作新函數(shù)體內(nèi)的this
}
};
var obj = {
name: 'sven'
};
var func = function(){
alert ( this.name ); // 輸出:sven
}.bind( obj);
func();
我們通過Function.prototype.bind 來“包裝”func 函數(shù),并且傳入一個(gè)對(duì)象context 當(dāng)作參數(shù),這個(gè)context 對(duì)象就是我們想修正的this 對(duì)象。
在Function.prototype.bind 的內(nèi)部實(shí)現(xiàn)中,我們先把func 函數(shù)的引用保存起來,然后返回一個(gè)新的函數(shù)。當(dāng)我們?cè)趯韴?zhí)行func 函數(shù)時(shí),實(shí)際上先執(zhí)行的是這個(gè)剛剛返回的新函數(shù)。在新函數(shù)內(nèi)部,self.apply( context, arguments )這句代碼才是執(zhí)行原來的func 函數(shù),并且指定context對(duì)象為func 函數(shù)體內(nèi)的this。
這是一個(gè)簡(jiǎn)化版的Function.prototype.bind 實(shí)現(xiàn),通常我們還會(huì)把它實(shí)現(xiàn)得稍微復(fù)雜一點(diǎn),
使得可以往func 函數(shù)中預(yù)先填入一些參數(shù):
Function.prototype.bind = function(){
var self = this, // 保存原函數(shù)
context = [].shift.call( arguments ), // 需要綁定的this 上下文
args = [].slice.call( arguments ); // 剩余的參數(shù)轉(zhuǎn)成數(shù)組
return function(){ // 返回一個(gè)新的函數(shù)
return self.apply( context, [].concat.call( args, [].slice.call( arguments ) ) );
// 執(zhí)行新的函數(shù)的時(shí)候,會(huì)把之前傳入的context 當(dāng)作新函數(shù)體內(nèi)的this
// 并且組合兩次分別傳入的參數(shù),作為新函數(shù)的參數(shù)
}
};
var obj = {
name: 'sven'
};
var func = function( a, b, c, d ){
alert ( this.name ); // 輸出:sven
alert ( [ a, b, c, d ] ) // 輸出:[ 1, 2, 3, 4 ]
}.bind( obj, 1, 2 );
func( 3, 4 );
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!
- javascript中apply和call方法的作用及區(qū)別說明
- js apply/call/caller/callee/bind使用方法與區(qū)別分析
- JavaScript學(xué)習(xí)點(diǎn)滴 call、apply的區(qū)別
- JavaScript中apply與call的用法意義及區(qū)別說明
- 在JavaScript中call()與apply()區(qū)別
- JavaScript中的this,call,apply使用及區(qū)別詳解
- 理解Javascript的caller,callee,call,apply區(qū)別
- 深入理解JavaScript中的call、apply、bind方法的區(qū)別
- javascript中apply、call和bind的使用區(qū)別
- Javascript call和apply區(qū)別及使用方法
- 深入理解關(guān)于javascript中apply()和call()方法的區(qū)別
- JavaScript中call和apply方法的區(qū)別實(shí)例分析
相關(guān)文章
JavaScript?邏輯或?||?的妙用及相關(guān)知識(shí)普及
本文給大家介紹了JavaScript中的邏輯或運(yùn)算符||的用法,包括其基本概念、真值和假值、常見應(yīng)用以及與其他邏輯運(yùn)算符的對(duì)比,感興趣的朋友跟隨小編一起看看吧2024-12-12
JavaScript使用replace函數(shù)替換字符串的方法
這篇文章主要介紹了JavaScript使用replace函數(shù)替換字符串的方法,涉及javascript中replace函數(shù)的使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04
js實(shí)現(xiàn)固定區(qū)域內(nèi)的不重疊隨機(jī)圓
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)固定區(qū)域內(nèi)的不重疊隨機(jī)圓,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10
前端知識(shí)點(diǎn)之Javascript選擇輸入框confirm用法
這篇文章主要介紹了JavaScript中的confirm方法的基本用法、功能特點(diǎn)、注意事項(xiàng)及常見用途,文中通過代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用js具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2025-02-02
easyui-combobox 實(shí)現(xiàn)簡(jiǎn)單的自動(dòng)補(bǔ)全功能示例
下面小編就為大家?guī)硪黄猠asyui-combobox 實(shí)現(xiàn)簡(jiǎn)單的自動(dòng)補(bǔ)全功能示例。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,2016-11-11
解讀請(qǐng)求方式Method和請(qǐng)求類型Content-Type
HTTP請(qǐng)求中,Content-Type頭部用于指定請(qǐng)求體或響應(yīng)體的類型,常見的有application/x-www-form-urlencoded、multipart/form-data、application/json、text/plain、application/xml等,常用請(qǐng)求方式包括Get、Post、Put、Delete2024-09-09
js實(shí)現(xiàn)彈出框的拖拽效果實(shí)例代碼詳解
本文通過實(shí)例代碼給大家介紹了js實(shí)現(xiàn)彈出框的拖拽效果,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值 ,需要的朋友可以參考下2019-04-04
js實(shí)現(xiàn)iGoogleDivDrag模塊拖動(dòng)層拖動(dòng)特效的方法
這篇文章主要介紹了js實(shí)現(xiàn)iGoogleDivDrag模塊拖動(dòng)層拖動(dòng)特效的方法,實(shí)例分析了javascript操作拖動(dòng)層的技巧,需要的朋友可以參考下2015-03-03
JS中判斷JSON數(shù)據(jù)是否存在某字段的方法
這篇文章主要介紹了JS中如何判斷JSON數(shù)據(jù)是否存在某字段,需要的朋友可以參考下2014-03-03
微信小程序?qū)崿F(xiàn)Timeline時(shí)間線效果
這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)Timeline時(shí)間線效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05

