js函數(shù)中的this

前兩篇文章“執(zhí)行環(huán)境和作用域”“js中的閉包”行剂,我對談了執(zhí)行環(huán)境、作用域钳降、作用域鏈和閉包的理解厚宰。但當(dāng)牽涉到對象中的方法時(shí),前面談的東西就不那么適用了遂填。先來看一個(gè)例子:

var name = 'a';
function getName(){
  console.log(name);
}
var o1 ={
  name: 'a1',
  getName: getName
}
var o2 ={
  name: 'a2',
  getName: getName
}
o1.getName()    // 'a'
o2.getName()    // 'a'

上面的代碼中铲觉,o1.getName()和o2.getName()都輸出‘a(chǎn)’澈蝙,根據(jù)"作用域的規(guī)則"很好解釋。但問題是:我們既然使用了這種方式調(diào)用函數(shù)撵幽,肯定更希望gentName方法訪問的是對象內(nèi)部的‘name’屬性灯荧。這時(shí),就需要修改外部定義的getName方法了并齐。前面談過在函數(shù)執(zhí)行時(shí)漏麦,會(huì)動(dòng)態(tài)的創(chuàng)建一個(gè)活動(dòng)對象,這個(gè)活動(dòng)對象况褪,被作為變量對象撕贞,推進(jìn)執(zhí)行環(huán)境棧中。同時(shí)测垛,還會(huì)創(chuàng)建“arguments”對象和綁定this對象捏膨,arguments對象最為變量對象的第一個(gè)屬性,保存著傳入函數(shù)中的參數(shù)食侮;this對象根據(jù)函數(shù)的執(zhí)行環(huán)境動(dòng)態(tài)地綁定号涯。有句很經(jīng)典的判斷this指向的話:誰調(diào)用了函數(shù),this就指向誰锯七。

這樣链快,只要把getName函數(shù)修改成下面的代碼,就可以實(shí)現(xiàn)訪問對象中name屬性的效果:

function getName(){
  console.log(this.name)
}

依靠上面經(jīng)典的話眉尸,可以在很多情況下判斷this的指向域蜗,但還有一些情況不使用。下面就分類來說下this噪猾。

1霉祸、純粹的函數(shù)調(diào)用

這是函數(shù)最通常的用法。這時(shí)袱蜡,不論函數(shù)是在全局作用域下執(zhí)行丝蹭,還是在函數(shù)中執(zhí)行,this都是指向全局對象坪蚁,也就是window對象奔穿。例如:

var person = 'xiaoming'
function f1(){
  var person = 'xiaohong'
  function f2(){
    console.log(this.person)
  }
  f2()
}
f1();  // 'xiaoming'

2、作為對對象的方法調(diào)用

在函數(shù)作為對象的方法調(diào)用時(shí)迅细,上面的那句經(jīng)典的話巫橄,就很適用了。這里來看一個(gè)很典型的例子:

var age = 18;
var obj = {
  age : 21,
  fn: functoin(){
    console.log(this.age)
  }
}
(false || obj.fn)()   //  18

在上面的代碼中茵典,在對象中的fn方法執(zhí)行之前湘换,會(huì)先執(zhí)行‘||’運(yùn)算,相當(dāng)于:

(false || function(){
  console.log(this.age)
})()

實(shí)際上,也就是fn方法在全局作用域中執(zhí)行彩倚。所以筹我,結(jié)果是18。

3帆离、構(gòu)造函數(shù)

構(gòu)造函數(shù)中的this蔬蕊,指向?qū)ο蟮膶?shí)例。例如:

function People(name){
  this.name = name
}
People.prototyope.sayName() = function(){
  console.log(this.name)
}
var p = new People('張三');

p.name  //‘張三’l
p.sayName  //'張三'

4哥谷、call岸夯、apply和bind

call、apply和bind方法都是函數(shù)對象中的方法们妥,用來動(dòng)態(tài)地改變函數(shù)中this的指向猜扮,只是用法不同。call和apply被調(diào)用時(shí)监婶,不僅改變函數(shù)中this指向旅赢,而且執(zhí)行該函數(shù),但bind僅僅是改變函數(shù)中this的指向惑惶,并不執(zhí)行煮盼。如下:

var x = 2;
var y = 3;
function getY(){
  console.log(this.y)
} 
var o = {
  x: 1,
  y: 4,
  getX: function(){
    console.log(this.x)
  }
}
o.getX.call()    //2
getY.bind(o)()    // 4

call、apply和bind方法在未傳入指定對象時(shí)带污,默認(rèn)傳入window 對象僵控,因此,o.getX.call() 輸出結(jié)果是2鱼冀。使用bind方法時(shí)喉祭,僅僅改變函數(shù)中this指針的指向,而要執(zhí)行需要在后面添加'()'雷绢。call 和 apply方法在使用時(shí),除了第一個(gè)指定this對象的參數(shù)外理卑,后面還可以添加原油函數(shù)的其他參數(shù)翘紊,call方法接受單個(gè)參數(shù)的羅列,而apply方法接受數(shù)組格式的參數(shù)(arguments對象也可以)藐唠。如下:

fn.call(o, param1,param2)
fn.call(o,[param1,param2])

注意點(diǎn)

  • this的指向是不確定的帆疟,不要在函數(shù)中包含多層的this。在必要時(shí)宇立,可以將this賦值給其他的變量踪宠,再使用。例如:self妈嘹,that等柳琢。例如:
var o = {
  f1:  function() {
        console.log(this);
        var that = this;
        var f2 = function() {
          console.log(that);
        }();
    }
}
o.f1()
// Object
// Object
  • 避免回調(diào)函數(shù)中的this:回調(diào)函數(shù)中的this往往會(huì)改變指向,最好避免使用。例如:
var o = new Object();
o.f = function () {
  console.log(this === o);
}
o.f() // true

上面的代碼是沒什么問題的柬脸,但當(dāng)把 o.f 作為事件處理的回調(diào)函數(shù)就不一樣了他去。例如:

$('#button').on('click', o.f);

寫在結(jié)尾:
如果覺得我寫的文章對你有幫助,歡迎掃碼關(guān)注我的公眾號(hào):海痕筆記
微信號(hào):haihenbiji


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末倒堕,一起剝皮案震驚了整個(gè)濱河市灾测,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌垦巴,老刑警劉巖媳搪,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異骤宣,居然都是意外死亡秦爆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進(jìn)店門涯雅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鲜结,“玉大人,你說我怎么就攤上這事活逆【ⅲ” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵蔗候,是天一觀的道長怒允。 經(jīng)常有香客問我,道長锈遥,這世上最難降的妖魔是什么纫事? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮所灸,結(jié)果婚禮上丽惶,老公的妹妹穿的比我還像新娘。我一直安慰自己爬立,他們只是感情好钾唬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著侠驯,像睡著了一般抡秆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吟策,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天儒士,我揣著相機(jī)與錄音,去河邊找鬼檩坚。 笑死着撩,一個(gè)胖子當(dāng)著我的面吹牛诅福,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播睹酌,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼权谁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了憋沿?” 一聲冷哼從身側(cè)響起旺芽,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辐啄,沒想到半個(gè)月后采章,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡壶辜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年悯舟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片砸民。...
    茶點(diǎn)故事閱讀 40,013評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡抵怎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出岭参,到底是詐尸還是另有隱情反惕,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布演侯,位于F島的核電站姿染,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏秒际。R本人自食惡果不足惜悬赏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望娄徊。 院中可真熱鬧闽颇,春花似錦、人聲如沸寄锐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽锐峭。三九已至,卻和暖如春可婶,著一層夾襖步出監(jiān)牢的瞬間沿癞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工矛渴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留椎扬,地道東北人惫搏。 一個(gè)月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像蚕涤,于是被迫代替她去往敵國和親筐赔。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評論 2 355

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