【 JavaScript 基礎(chǔ)】之this關(guān)鍵字

前言

JS 是一種腳本語言雷滋,因此被很多人認(rèn)為是簡單易學(xué)的。然而情況可能與之相悖臼勉,JS 遵從函數(shù)式編程邻吭、閉包、基于原型的繼承等高級(jí)功能宴霸。本文介紹一下JS中的 this 關(guān)鍵字囱晴,可以這樣說,正確掌握了 JS 中的 this 關(guān)鍵字瓢谢,才算邁入了 JS 這門語言的門檻畸写。

注: 本文采用部分 es6 進(jìn)行代碼分析


Java工程師所熟識(shí)的this

在 Java 中定義類經(jīng)常會(huì)使用 this 關(guān)鍵字,多數(shù)情況下是為了避免命名沖突氓扛,比如在下面例子的中枯芬,定義一個(gè) Image 類,很自然的采郎,大家會(huì)使用 width千所、height 為其屬性或成員變量命名,在構(gòu)造函數(shù)中蒜埋,使用 width淫痰、height 為參數(shù)命名。無論哪種情況理茎,this 的含義是一樣的黑界,均指當(dāng)前類對(duì)象管嬉,當(dāng)調(diào)用構(gòu)造方法時(shí)全局變量width、height的值會(huì)被修改朗鸠。

    public class Image {
        private int width = 0;
        private int height = 0;

        public Image(int width, int height) {
            this.width = width;
            this.height = height;
        }

        public void println() {
            System.out.println("width = " + this.width);
            System.out.println("height = " + this.height);
        }

    }

調(diào)用方式如下:

        Image image = new Image(10, 10);
        image.println();

輸出結(jié)果:

width = 10
height = 10

Process finished with exit code 0

可以看得出來this.x 與 this.y 直接修改的全局變量的值蚯撩,也證明了我們上面的觀點(diǎn)~

JS語言中的 this

由于JS等腳本語言運(yùn)行期進(jìn)行解釋的特性,JS 中的 this 含義要豐富得多烛占,它可以是全局對(duì)象胎挎、當(dāng)前對(duì)象或者任意對(duì)象,這完全取決于函數(shù)的調(diào)用方式忆家。

JS 中函數(shù)的調(diào)用有以下幾種方式:

1犹菇、作為對(duì)象方法調(diào)用
2、作為函數(shù)調(diào)用
3芽卿、作為構(gòu)造函數(shù)調(diào)用
4揭芍、使用 apply 或 call 調(diào)用

接下來我們按照調(diào)用方式的不同,分別討論 this 的含義卸例。

作為對(duì)象方法調(diào)用

var image = { 
   width : 0, 
   height : 0, 
   update : function(width, height) { 
     this.width = this.width + width
     this.height = this.height + height
   } 
 }

 // this 綁定到當(dāng)前對(duì)象称杨,即 image 對(duì)象
 // 執(zhí)行此方法后image的width與Height屬性值變?yōu)?
 image.update(1, 1) 

作為函數(shù)調(diào)用

當(dāng)調(diào)用函數(shù)時(shí),此時(shí) this 綁定到全局對(duì)象筷转,在瀏覽器中姑原,window 就是該全局對(duì)象,例如下面:setLocalValue 函數(shù)被調(diào)用時(shí)呜舒,this 被綁定到全局對(duì)象锭汛,接下來執(zhí)行賦值語句,相當(dāng)于隱式的聲明了一個(gè)全局變量袭蝗,這顯然不是調(diào)用者希望的效果~

 function setLocalValue(value) { 
   this.localValue = value
 } 

 setLocalValue(5)
 
 // localValue 已經(jīng)聲明成一個(gè)值為 5 的全局變量
 console.log(localValue) // ==> 5

對(duì)于內(nèi)部函數(shù)唤殴,即聲明在一個(gè)函數(shù)體內(nèi)的函數(shù),這種綁定到全局對(duì)象的方式會(huì)衍生出一個(gè)新的問題呻袭,我們?nèi)匀灰郧懊嫣岬降?image 對(duì)象為例眨八,這次我們希望在 update 方法內(nèi)定義兩個(gè)函數(shù)腺兴,分別將 width左电、height 屬性進(jìn)行修改。結(jié)果可能出乎大家意料页响,不僅 image 對(duì)象沒有移動(dòng)篓足,反而多出兩個(gè)全局變量 width、height闰蚕。

var image = { 
  width : 0, 
  height : 0, 
  update : function(width, height) { 
    // 內(nèi)部函數(shù)
    var updateWidth = function(width) { 
      //this 綁定到了哪里栈拖?
      this.width = width;
    } 
    // 內(nèi)部函數(shù)
    var updateHeight = function(height) { 
      //this 綁定到了哪里?
      this.height = height;
    }
    
    updateWidth(width) 
    updateHeight(height) 
  } 
}
 
 image.update(1, 1)
 
 console.log(image.width) // ==> 0
 console.log(image.height) // ==> 0
 console.log(width) // ==> 1
 console.log(height) // ==> 1

這屬于 JS 語言的設(shè)計(jì)缺陷没陡,正確的設(shè)計(jì)方式是內(nèi)部函數(shù)的 this 應(yīng)該綁定到其外層函數(shù)對(duì)應(yīng)的對(duì)象上涩哟,為了規(guī)避這一設(shè)計(jì)缺陷索赏,我們一般采用變量替換的方法,該變量草民習(xí)慣命名為成 self~

var image = { 
  width : 0, 
  height : 0, 
  update : function(width, height) { 
    var self = this
    // 內(nèi)部函數(shù)
    var updateWidth = function(width) { 
      self.width = width;
    } 
    // 內(nèi)部函數(shù)
    var updateHeight = function(height) { 
      self.height = height;
    }
    
    updateWidth(width) 
    updateHeight(height) 
  } 
}
 
 image.update(1, 1)
 
 console.log(image.width) // ==> 1
 console.log(image.height) // ==> 1

這樣就達(dá)到了我們想要的效果~

作為構(gòu)造函數(shù)調(diào)用

JS 支持面向?qū)ο缶幊烫耍c主流的面向?qū)ο笫骄幊陶Z言不同潜腻。

:es6之前JS 并沒有類(class)的概念,而是使用基于原型(prototype)的繼承方式器仗,JS 中的構(gòu)造函數(shù)也很特殊融涣,如果不使用 new 調(diào)用,則和普通函數(shù)一樣精钮,作為又一項(xiàng)約定俗成的準(zhǔn)則威鹿,構(gòu)造函數(shù)以大寫字母開頭,提醒調(diào)用者使用正確的方式調(diào)用轨香,如下es5示例忽你。

:es6之后支持了class的概念,重寫constructor方法臂容,this 綁定到新創(chuàng)建的對(duì)象上檀夹。

es5示例 :

function Image(width, height){ 
    this.width = width
    this.height = height
}

var img1 = new Image(10, 10)

es6 示例 :

class Image {

  constructor(width, height) {
    this.width = width
    this.height = height
  }

}

 let img1 = new Image(10, 10)

使用 apply 或 call 調(diào)用

此次著重強(qiáng)調(diào)一下,在 JS 語言中函數(shù)也是對(duì)象策橘,對(duì)象則有行為(方法)炸渡,apply 和 call 就是函數(shù)對(duì)象的方法。這兩個(gè)方法功能超級(jí)強(qiáng)大丽已,它們?cè)试S切換函數(shù)執(zhí)行的上下文環(huán)境(context)蚌堵,即 this 指向的對(duì)象,在很多JS庫中也得到了廣泛應(yīng)用~

class Image {

  constructor(width, height) {
    this.width = width
    this.height = height
  }

  update(width, height) { 
     this.width = width
     this.height = height
  } 

}

 let img1 = new Image(0, 0)
 let img2 = {width: 0, height: 0}
 img1.update(10, 10)
 
 // img2 width沛婴、height ==> 20
 img1.update.apply(img2, [20, 20]) 
 
 // img2 width吼畏、height ==> 20
 img1.update.call(img2, 20, 20)

在上面的例子中,我們使用構(gòu)造函數(shù)生成了一個(gè)對(duì)象 img1嘁灯,該對(duì)象同時(shí)具有 update 方法泻蚊,同時(shí)定義了另一個(gè)對(duì)象 img2,使用 apply 可以將 img1 的方法應(yīng)用到 img2 上丑婿,這時(shí)候 this 也被綁定到對(duì)象 img2 上性雄。

結(jié)語:

JS之this關(guān)鍵字就介紹到這里,謝謝大家的觀看羹奉,希望對(duì)大家有所幫助~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末秒旋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子诀拭,更是在濱河造成了極大的恐慌迁筛,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耕挨,死亡現(xiàn)場離奇詭異细卧,居然都是意外死亡尉桩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門贪庙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來魄健,“玉大人,你說我怎么就攤上這事插勤」潦荩” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵农尖,是天一觀的道長析恋。 經(jīng)常有香客問我,道長盛卡,這世上最難降的妖魔是什么助隧? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮滑沧,結(jié)果婚禮上并村,老公的妹妹穿的比我還像新娘。我一直安慰自己滓技,他們只是感情好哩牍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著令漂,像睡著了一般膝昆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叠必,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天荚孵,我揣著相機(jī)與錄音,去河邊找鬼纬朝。 笑死收叶,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的共苛。 我是一名探鬼主播判没,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼俄讹!你這毒婦竟也來了哆致?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤患膛,失蹤者是張志新(化名)和其女友劉穎撞秋,沒想到半個(gè)月后涝滴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纤子,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恶迈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了跃捣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漱牵。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖疚漆,靈堂內(nèi)的尸體忽然破棺而出酣胀,到底是詐尸還是另有隱情,我是刑警寧澤娶聘,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布闻镶,位于F島的核電站,受9級(jí)特大地震影響丸升,放射性物質(zhì)發(fā)生泄漏铆农。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一狡耻、第九天 我趴在偏房一處隱蔽的房頂上張望墩剖。 院中可真熱鬧,春花似錦夷狰、人聲如沸岭皂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蒲障。三九已至,卻和暖如春瘫证,著一層夾襖步出監(jiān)牢的瞬間揉阎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國打工背捌, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留毙籽,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓毡庆,卻偏偏與公主長得像坑赡,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子么抗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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