JS中的this

參考書籍:《JavaScript設(shè)計模式與開發(fā)實踐》;
《JavaScript高級程序設(shè)計(第3版)》(以下簡稱《高級程序設(shè)計》)

JS的this對象是在運行時基于函數(shù)的執(zhí)行環(huán)境綁定的:在全局函數(shù)中,this等于window媒楼,而當(dāng)函數(shù)被某個對象的方法調(diào)用時,this等于那個對象深纲。
除去不常用的with和eval的情況,具體到實際應(yīng)用中 劲妙,this的指向大致可以分為以下4種(其中還包含一些特殊情況需要被提及)湃鹊。

1、作為對象的方法調(diào)用
//作為對象調(diào)用時镣奋,this指向這個對象
var obj = {
    getA : function(){
          alert ( this === obj );  
    }
}

obj.getA();  // true 
2币呵、作為普通函數(shù)調(diào)用

當(dāng)函數(shù)不作為對象的屬性調(diào)用時,也就是常說的用普通函數(shù)方式調(diào)用,此時的this總是指向全局對象余赢。在瀏覽器中芯义,這個全局對象是window對象。

window.name = 'globalName';

var getName = function(){
       return this.name;
}
console.log( getName() ); // globalName

上面這個例子直接創(chuàng)建了一個函數(shù)并在全局調(diào)用妻柒,事實上扛拨,還可以將對象中的函數(shù)賦值給全局中的函數(shù),請看如下代碼:

//與上一段代碼效果相同
window.name = 'globalName';
var obj = {
      name : 'sven',
      getName : function(){
              return this.name;
      }
}
var getName = obj.getName;
console.log( getName() ); // globalName

神奇的是举塔,如果將對象中的函數(shù)賦值給對象中的函數(shù)绑警,this還是會指向全局:

var name = "globalName";
var obj = {
    name: "sven",
    getName: function() {
        return this.name;
    }
};
console.log((obj.getName = obj.getName)()); // globalName (非嚴(yán)格模式下)

這是在《高級程序設(shè)計》第183頁的一個例子。書本中的解釋為:(函數(shù)調(diào)用時的)這行代碼先執(zhí)行了一條賦值語句央渣,然后再調(diào)用賦值后的結(jié)果计盒。因為這個賦值表達(dá)式的值是函數(shù)本身,所以this的值不能得到維持芽丹,結(jié)果就返回了"globalName"北启。要詳細(xì)解釋這個問題,網(wǎng)上有一篇文章可以參考:《 this在方法賦值過程中無法保持(隱式丟失)

簡單點想拔第,以上這些都可看作普通函數(shù)在全局中調(diào)用暖庄,this自然是指向全局的。這也充分說明了之前提到的:JS的this對象是在運行時基于函數(shù)的執(zhí)行環(huán)境綁定的楼肪,與函數(shù)聲明時的環(huán)境無關(guān)。

除此之外惹悄,常常會出現(xiàn)函數(shù)內(nèi)部嵌套函數(shù)的情況春叫,匿名函數(shù)作為內(nèi)部函數(shù)很常見。
關(guān)于匿名函數(shù)泣港,《高級程序設(shè)計》中說暂殖,“匿名函數(shù)的執(zhí)行環(huán)境具有全局性,因此其this對象通常指向window”当纱。然而經(jīng)過測試發(fā)現(xiàn)呛每,函數(shù)內(nèi)部的非匿名函數(shù)也是指向window的:

var name ="Window";
var obj={};
      
obj.Outer = function(){
    function Inner(){
        console.log(this.name);  //"Window" (非嚴(yán)格模式);"undefined"(嚴(yán)格模式)
    }
    Inner();  
 }
      
obj.Outer(); 

內(nèi)部函數(shù)在搜索this時,只會搜索到其活動對象為止坡氯,而其活動對象位于作用域鏈的前端晨横,因此永遠(yuǎn)不能直接訪問外部函數(shù)中的this,而是將它指向了全局對象箫柳。若是內(nèi)部函數(shù)需要訪問外部this手形,通常會這樣處理:

var name ="Window";
var obj={
     name : "outerName"
};
      
obj.Outer = function(){
     var that = this;
     function Inner(){
      console.log(that.name);  // outerName
     }
     Inner();
}
obj.Outer(); 
3、構(gòu)造器調(diào)用

在js中悯恍,可以使用new運算符調(diào)用函數(shù)库糠,此時的函數(shù)被當(dāng)作一個構(gòu)造函數(shù),而構(gòu)造器中的this就指向返回的對象:

var MyClass = function(){
      this.name =  'sven';
 }

var obj = new MyClass();
console.log( obj.name );   // 輸出:sven

如果構(gòu)造器顯式地返回一個object類型對象涮毫,則運算結(jié)果為最終返回的對象:

var MyClass = function(){
      this.name =  'sven';
      return {
          name: 'anne'
       }
 }

var obj = new MyClass();
console.log( obj.name );   // 輸出:anne

若是返回非對象類型的數(shù)據(jù)瞬欧,就不會造成上述問題:

var MyClass = function(){
      this.name =  'sven' ;
      return 'anne' ;
 }

var obj = new MyClass();
console.log( obj.name );   // 輸出:sven
4贷屎、call、apply調(diào)用

call艘虎、apply可以動態(tài)改變傳入函數(shù)的this:

var obj1 = {
     name: 'sven',
     getName: function(){
           return this.name;
     }
};

var obj2 = {
      name: 'anne'
}
console.log( obj1.getName.call(obj2) );  // 輸出:anne

call唉侄、apply這兩個函數(shù)很強大,它擴(kuò)充了函數(shù)賴以運行的作用域顷帖,實現(xiàn)了對象和方法的解耦美旧。call 和 apply 方法能很好地體現(xiàn) JavsScript 的函數(shù)式語言特性,在 JavsScript 中贬墩,幾乎每一次編寫函數(shù)式語言語言風(fēng)格的代碼都離不開call和apply榴嗅。常用的js原型繼承模式,以及js諸多版本的設(shè)計模式中陶舞,都用到了它們嗽测。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市肿孵,隨后出現(xiàn)的幾起案子唠粥,更是在濱河造成了極大的恐慌,老刑警劉巖停做,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晤愧,死亡現(xiàn)場離奇詭異,居然都是意外死亡蛉腌,警方通過查閱死者的電腦和手機(jī)官份,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烙丛,“玉大人舅巷,你說我怎么就攤上這事『友剩” “怎么了钠右?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長忘蟹。 經(jīng)常有香客問我飒房,道長,這世上最難降的妖魔是什么寒瓦? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任情屹,我火速辦了婚禮,結(jié)果婚禮上杂腰,老公的妹妹穿的比我還像新娘垃你。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布惜颇。 她就那樣靜靜地躺著皆刺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪凌摄。 梳的紋絲不亂的頭發(fā)上羡蛾,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機(jī)與錄音锨亏,去河邊找鬼痴怨。 笑死,一個胖子當(dāng)著我的面吹牛器予,可吹牛的內(nèi)容都是我干的浪藻。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼乾翔,長吁一口氣:“原來是場噩夢啊……” “哼爱葵!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起反浓,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤萌丈,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后雷则,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辆雾,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年月劈,在試婚紗的時候發(fā)現(xiàn)自己被綠了乾颁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡艺栈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出湾盒,到底是詐尸還是另有隱情湿右,我是刑警寧澤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布罚勾,位于F島的核電站毅人,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏尖殃。R本人自食惡果不足惜丈莺,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望送丰。 院中可真熱鬧缔俄,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至遏佣,卻和暖如春挖炬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背状婶。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工意敛, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人膛虫。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓草姻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親走敌。 傳聞我的和親對象是個殘疾皇子碴倾,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

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

  • 沒搞錯吧!js寫了那么多年掉丽,this還是會搞錯跌榔!沒搞錯,javascript就是回搞錯捶障! ………… 在寫java的...
    zhoulujun閱讀 1,445評論 0 11
  • 前言 近期對this很感興趣僧须,于是乎簡單整理了一些關(guān)于this的技術(shù)點,加深一下對this的理解项炼。 非箭頭函數(shù) 在...
    little_short閱讀 419評論 0 0
  • JS 里的 this 1担平、在 function 內(nèi)部被創(chuàng)建2、指向調(diào)用時所在函數(shù)所綁定的對象3锭部、this 不能被賦...
    Cherry丶小丸子閱讀 196評論 0 0
  • 注:本文案例環(huán)境為非嚴(yán)格模式拌禾,嚴(yán)格模式下禁止關(guān)鍵字this指向全局對象 一取胎、方法是怎么執(zhí)行的? 首先說一下js中方...
    就那ck閱讀 1,153評論 5 17
  • this是什么湃窍? this是包含它的函數(shù)作為方法被調(diào)用時所屬的對象闻蛀。 首先必須要說的是,this的指向在函數(shù)定義的...
    指尖跳動閱讀 211評論 0 0