JS中call众羡、apply、bind使用指南

為什么需要這些瘪贱?主要是因?yàn)閠his纱控,來看看this干的好事。

box.onclick = function(){
  function fn(){
    alert(this);
  }
  fn();
};

我們原本以為這里面的this指向的是box,然而卻是Window菜秦。一般我們這樣解決:

box.onclick = function(){
  var _this = this;
  function fn(){
    alert(_this);
  }
  fn();
};

將this保存下來甜害。

還有一些情況,有時(shí)我們想讓偽數(shù)組也能夠調(diào)用數(shù)組的一些方法球昨,這時(shí)call尔店、apply、bind就派上用場了主慰。

我們先來解決第一個(gè)問題修復(fù)this指向嚣州。

box.onclick = function(){
  function fn(){
    alert(this);
  }
  fn();
};

改成如下:

box.onclick = function(){
  function fn(){
    console.log(this);
  }
  fn.call(this);
};

很神奇吧,call的作用就是改變this的指向的共螺,第一個(gè)傳的是一個(gè)對象该肴,就是你要借用的那個(gè)對象。

fn.call(this);

這里的意思是讓this去調(diào)用fn這個(gè)函數(shù)藐不,這里的this是box匀哄,這個(gè)沒有意見吧秦效?如果這個(gè)你不清楚,很可能你是javscript的新朋友涎嚼。box調(diào)用fn阱州,這句話非常重要,我們知道this它始終指向一個(gè)對象法梯,剛好box就是一個(gè)對象苔货。那么fn里面的this就是box。

box.onclick = function(){
  function fn(){
    console.log(this);
  }
  fn.call(this);
};

這句話在某些情況下是可以簡寫的立哑,比如:

box.onclick = function(){
  var fn = function(){
    console.log(this); //box
  }.call(this);
};

或者這樣:

box.onclick = function(){
  (function(){
    console.log(this);
  }.call(this)); //box
};

又或者這樣:

var objName = {name:'JS2016'};
var obj = {
  name:'0 _ 0',
  sayHello:function(){
    console.log(this.name);
  }.bind(objName)
};
obj.sayHello();//JS2016

call和apply夜惭、bind但是用來改變this的指向的,但也有一些小小的差別铛绰。下面我們來看看它們的差別在哪滥嘴。

function fn(a,b,c,d){
  console.log(a,b,c,d);
}

//call
fn.call(null,1,2,3);

//apply
fn.apply(null,[1,2,3]);

//bind
var f = fn.bind(null,1,2,3);
f(4);

結(jié)果如下:

1 2 3 undefined
1 2 3 undefined
1 2 3 4

前面說過第一個(gè)參數(shù)傳的是一個(gè)你要借用的對象,但這么我們不需要至耻,所有就傳了一個(gè)null若皱,當(dāng)然你也可以傳其他的,反正在這里沒有用到尘颓,除了第一個(gè)參數(shù)后面的參數(shù)將作為實(shí)際參數(shù)傳入到函數(shù)中走触。

call就是挨個(gè)傳值,apply傳一個(gè)數(shù)組疤苹,bind也是挨個(gè)傳值互广,但和call和apply還有多少不同,使用call和apply會(huì)直接執(zhí)行這個(gè)函數(shù)卧土,而bind并不會(huì)而是將綁定好的this重新返回一個(gè)新函數(shù)惫皱,什么時(shí)候調(diào)用由你自己決定。

var objName = {name:'JS2016'};
var obj = {
  name:'0 _ 0',
  sayHello:function(){
    console.log(this.name);
  }.bind(objName)
};
obj.sayHello();//JS2016

這里也就是為什么我要用bind的原因尤莺,如果用call的話就會(huì)報(bào)錯(cuò)了旅敷。自己想想這個(gè)sayHello在obj都已經(jīng)執(zhí)行完了,就根本沒有sayHello這個(gè)函數(shù)了颤霎。

這幾個(gè)方法使用的好的話可以幫你解決不少問題比如:

正常情況下Math.max只能這樣用

Math.max(10,6)

但如果你想傳一個(gè)數(shù)組的話你可以用apply

var arr = [1,2,30,4,5];
console.log(Math.max.apply(null,arr));

又或者你想讓偽數(shù)組調(diào)用數(shù)組的方法

function fn(){
  [].push.call(arguments,3);
  console.log(arguments); //[1, 2, 3]
}
fn(1,2);

再者:

var arr = ['aaabc'];
console.log(''.indexOf.call(arr,'b')); //3

牛逼不媳谁,簡直偷梁換柱,當(dāng)然還有很多可以利用的友酱,自己盡情花輝去吧晴音。

簡單說一下這種偷梁換柱的原理吧,實(shí)際上瀏覽器內(nèi)部根本就不在乎你是誰缔杉,它只關(guān)心你傳給我的是不是我能夠運(yùn)行的锤躁,如下:

正常情況

var str = 'aaabc';
console.log(str.indexOf('b'));

而這種情況其實(shí)做的事情和上面一模一樣,看我來拆解或详。

var arr = ['aaabc'];
''.indexOf.call(arr);

這句話就是說讓arr調(diào)用字符串的indexOf方法系羞,前面說過了瀏覽器內(nèi)部不在乎你是誰加缘,所以誰都可以來調(diào)用,但不是100%成功觉啊,具體看如下。

''.indexOf.call(arr,'b')

這里的arr就是['aaabc']沈贝,內(nèi)部很可能拆成了'aaabc'杠人,因此就成了下面的這段代碼。

'aaabc'.indexOf('b');

這就是它們的秘密宋下。

這里得說一下bind在某些瀏覽器下不兼容嗡善。我們來模擬一個(gè)玩玩。

Function.prototype.$bind = function(obj){
    //保存當(dāng)前this
  var _this = this;
    //截取除了第一個(gè)以外的所有實(shí)際參數(shù)
  var a = [].slice.call(arguments,1);
    //返回一個(gè)新函數(shù)
  return function(){
    //讓當(dāng)前那個(gè)調(diào)用的函數(shù)的this指向obj学歧,并且把實(shí)參傳給它罩引,這里用了concat是因?yàn)椋覀兛赡茉诮壎ㄒ院筮€傳遞參數(shù)枝笨,所以才把他們合并起來袁铐。如f(4)這個(gè)是在綁定以后傳的參數(shù),a這個(gè)argument是綁定時(shí)的横浑。
    _this.apply(obj,a.concat([].slice.call(arguments)));
  };
};

function fn(a,b,c,d){
  console.log(a,b,c,d);
}

var f = fn.$bind(null,1,2,3);
f(4);

這個(gè)方法和實(shí)際上的bind還是差別很大的剔桨,如

var arr = ['JSS'];

var index = ''.indexOf.$bind(arr,'S');
console.log(index())


function fff(){
  [].push.$bind(arguments,1);
  console.log(arguments);
}

fff();

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市徙融,隨后出現(xiàn)的幾起案子洒缀,更是在濱河造成了極大的恐慌,老刑警劉巖欺冀,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件树绩,死亡現(xiàn)場離奇詭異,居然都是意外死亡隐轩,警方通過查閱死者的電腦和手機(jī)饺饭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來职车,“玉大人砰奕,你說我怎么就攤上這事√崮瘢” “怎么了军援?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長称勋。 經(jīng)常有香客問我胸哥,道長,這世上最難降的妖魔是什么赡鲜? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任空厌,我火速辦了婚禮庐船,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嘲更。我一直安慰自己筐钟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布赋朦。 她就那樣靜靜地躺著篓冲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宠哄。 梳的紋絲不亂的頭發(fā)上壹将,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天,我揣著相機(jī)與錄音毛嫉,去河邊找鬼诽俯。 笑死,一個(gè)胖子當(dāng)著我的面吹牛承粤,可吹牛的內(nèi)容都是我干的暴区。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼辛臊,長吁一口氣:“原來是場噩夢啊……” “哼颜启!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起浪讳,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤缰盏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后淹遵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體口猜,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年透揣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了济炎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡辐真,死狀恐怖须尚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情侍咱,我是刑警寧澤耐床,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站楔脯,受9級特大地震影響撩轰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一堪嫂、第九天 我趴在偏房一處隱蔽的房頂上張望偎箫。 院中可真熱鬧,春花似錦皆串、人聲如沸淹办。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽怜森。三九已至,卻和暖如春寂玲,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背梗摇。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工拓哟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伶授。 一個(gè)月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓断序,卻偏偏與公主長得像,于是被迫代替她去往敵國和親糜烹。 傳聞我的和親對象是個(gè)殘疾皇子违诗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

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

  • "use strict";function _classCallCheck(e,t){if(!(e instanc...
    久些閱讀 2,034評論 0 2
  • 為什么需要這些?主要是因?yàn)閠his疮蹦,來看看this干的好事诸迟。 box.onclick = function(){ ...
    小董兒閱讀 271評論 0 0
  • 單例模式 適用場景:可能會(huì)在場景中使用到對象,但只有一個(gè)實(shí)例愕乎,加載時(shí)并不主動(dòng)創(chuàng)建阵苇,需要時(shí)才創(chuàng)建 最常見的單例模式,...
    Obeing閱讀 2,076評論 1 10
  • 工廠模式類似于現(xiàn)實(shí)生活中的工廠可以產(chǎn)生大量相似的商品感论,去做同樣的事情绅项,實(shí)現(xiàn)同樣的效果;這時(shí)候需要使用工廠模式。簡單...
    舟漁行舟閱讀 7,777評論 2 17
  • why掀亥?call,apply,bind干什么的?為什么要學(xué)這個(gè)妥色? 寫的好哦铺浇。 原文連接:http://www.cn...
    小豆soybean閱讀 285評論 0 0