this關鍵字揭秘

相信大家在學習JavaScript的時候思劳,this關鍵字總是會讓大家感到很困惑,下面就來給大家詳細的介紹有關this的一些知識點忍捡。

this

在JavaScript中this總是指向一個對象,而具體指向的那個對象是在運行代碼時基于函數(shù)的執(zhí)行環(huán)境動態(tài)綁定的,而不是函數(shù)在聲明時的環(huán)境怀骤。

this的指向問題

在JavaScript中出去特殊的with和eval之外,具體到實際運用中一般包括以下四種情況:
1焕妙、作為對象的方法調用蒋伦;
2、作為普通函數(shù)調用焚鹊;
3痕届、作為構造函數(shù)調用;
4末患、Function.prototype.call和Function.prototype.apply的調用爷抓。

1. 作為對象的方法調用

當一個函數(shù)當作一個對象的方法調用時,this指向該對象

var obj = {
    name :  'iFuhang',
    getName : function(){
        console.log(this);        // obj
        console.log(this.name);   // iFuhang
    }
}
obj.getName();

2. 作為普通函數(shù)調用

當一個函數(shù)不被當作對象的方法調用時阻塑,而是當作普通的函數(shù)被調用時蓝撇,此時的this指向全局對象,在瀏覽器中也就是指的window對象陈莽。

window.name = 'smile';
var getName = function(){
    var name = 'iFuhang';
    return this.name;
}
console.log(getName());   // smile

還有一種情況

window.name = 'smile';
var myObject= {
    name : 'iFuhang',
    getName : function(){
        return this.name;
    }
}
var getName = myObject.getName;
console.log(getName());

這種情況下渤昌,雖然getName是myObject.getName()賦值給它的,但是此時的getName仍然是當作普通函數(shù)來調用的走搁,所以此時this還是指向window的独柑。在這種情況下,有的時候會帶給我們一些不必要的麻煩私植,比如下面的示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <script>
        document.getElementById('app').onclick = function(){
            console.log(this.id);          // app
        var getId = function(){
            console.log(this.id);     // undefined
        }
        getId();
    }
    </script>
</body>
</html>

大家可以看到忌栅,最后getId()函數(shù)中打印出來的是undefined,這個結果我想大家并不意外了曲稼,是的索绪,getId()仍然是作為一個普通函數(shù)的調用。其是我們最后想要的結果是打印出div的id瑞驱,那么要怎樣解決呢娘摔?
其實很簡單,我們可以在執(zhí)行getId()函數(shù)之前唤反,先將div的引用保存起來,然后調用它就可以了。還是來看代碼吧!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <div id="app"></div>
    <script>
        document.getElementById('app').onclick = function(){
            var self = this;     // 提前將this保存起來楞卡,這里的this是指向div的
            console.log(this.id);          // app
        var getId = function(){
            console.log(this.id);     // app
        }
        getId();
    }
    </script>
</body>
</html>

好了,問題解決了,是不是很簡單池摧。其實這里可以還可以通過call方法來改變this的指向创葡,關于call方法的應用我們在后面將會講述。

需要注意的是在ECMAScript5中的嚴格模式下骚露,普通函數(shù)的this指向并不是window了。

function getThis(){
    "use strict";
    console.log(this);     // undefined
}
getThis();

3. 作為構造函數(shù)的調用

構造函數(shù)看起來其實和普通函數(shù)沒啥區(qū)別女嘲,只是在調用方式上不一樣,當使用new運算符調用函數(shù)時菇晃,此時此函數(shù)就稱為構造函數(shù),并且總是返回一個對象缤剧,通常情況下,構造函數(shù)中的this指向返回的這個對象兄纺。

var MyName = function(){
    this.name = 'iFuhang';
}
var obj= new MyName();
console.log(obj.name);    // iFuhang

使用構造函數(shù)的時候钦奋,需要注意一個問題厌衔,如果構造函數(shù)顯式的返回了一個對象睬隶,此時的this指向的是返回的這個對象了苏潜。如果返回的不是一個對象,就不會存在下面這種情況了变勇。

var MyName = function(){
    this.name = 'iFuhang';
    return {
        name : 'smile';
    }
}
var obj= new MyName();
console.log(obj.name);    // smile

4. Function.prototype.call和Function.prototype.apply的調用

通過Function.prototype.call和Function.prototype.apply這兩種方法可以動態(tài)的修改this的指向恤左。

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

var obj2 = {
    name : 'smile'
}

console.log(obj1.getName());    // iFuhang
console.log(obj1.getName.call(obj2));   // smile

點擊了解更多關于call和apply的知識點。

以上就是關于this的四種指向問題了搀绣,下面講解一下this丟失的問題飞袋。

this丟失

在開發(fā)中經常會遇到this丟失的問題,就比如下面這個示例:

var obj = {
    name : 'iFuhang',
    getName : function(){
        return this.name;
    }
}
console.log(obj.getName());   // iFuhang
var getName = obj.getName();
console.log(getName());    //undefined

出現(xiàn)這種情況的原因其實之前講到過的链患,在調用getName時授嘀,其實時普通函數(shù)的調用方式,所以此時的this指向window锣险,但是window中并沒有name這是屬性蹄皱,所以會返回undefined,如果在嚴格模式下芯肤,則會報錯巷折。再來看看下面這個例子:

一般我們用JavaScript獲取DOM節(jié)點時都會用到document.getElementById等之類的方法,但是為了使用簡單我們一般會封裝一個函數(shù)來簡化操崖咨。

var getId = function(id){
    return document.getElementById(id);
}
getId(id);

還有人思考為什么不能使用下面的方法呢锻拘?不是顯得更加簡單些嗎?

var getId = document.getElementById;
getId(id);

此段代碼運行時會拋出一個錯誤击蹲。(Uncaught TypeError: Illegal invocation)

這是因為在許多瀏覽器的引擎中實現(xiàn)document.getElementById時都會用到this署拟,而且this都被期望指向的是document,在getElementById被document調用的時候歌豺,this確實時指向document的推穷,但是當用getId來引用document.getElementById調用時,此時的getId是作為普通函數(shù)調用的类咧,this會指向window馒铃,而不再是document蟹腾。此時我們可以通過apply來改變this指向document。

document.getElementById = (function(func) {
    return function(){
        return func.apply(document, arguments);
    }
})(document.getElementById );

var getId = document.getElementById;
getId(id);

這段代碼中最后執(zhí)行的其實 func.apply(document, arguments)這個函數(shù)区宇,我們將document.getElementById作為參數(shù)傳遞娃殖,也就是func,最后在調用func時议谷,利用apply將this指向了document炉爆,所以最后可以輸出正確結果了。

閱讀原文

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末卧晓,一起剝皮案震驚了整個濱河市芬首,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌禀崖,老刑警劉巖衩辟,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件螟炫,死亡現(xiàn)場離奇詭異波附,居然都是意外死亡,警方通過查閱死者的電腦和手機昼钻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進店門掸屡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人然评,你說我怎么就攤上這事仅财。” “怎么了碗淌?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵盏求,是天一觀的道長。 經常有香客問我亿眠,道長碎罚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任纳像,我火速辦了婚禮荆烈,結果婚禮上,老公的妹妹穿的比我還像新娘竟趾。我一直安慰自己憔购,他們只是感情好,可當我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布岔帽。 她就那樣靜靜地躺著玫鸟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪犀勒。 梳的紋絲不亂的頭發(fā)上鞋邑,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天诵次,我揣著相機與錄音,去河邊找鬼枚碗。 笑死逾一,一個胖子當著我的面吹牛,可吹牛的內容都是我干的肮雨。 我是一名探鬼主播遵堵,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼怨规!你這毒婦竟也來了陌宿?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤波丰,失蹤者是張志新(化名)和其女友劉穎壳坪,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掰烟,經...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡爽蝴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了纫骑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蝎亚。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖先馆,靈堂內的尸體忽然破棺而出发框,到底是詐尸還是另有隱情,我是刑警寧澤煤墙,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布梅惯,位于F島的核電站,受9級特大地震影響仿野,放射性物質發(fā)生泄漏铣减。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一设预、第九天 我趴在偏房一處隱蔽的房頂上張望徙歼。 院中可真熱鬧,春花似錦鳖枕、人聲如沸魄梯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酿秸。三九已至,卻和暖如春魏烫,著一層夾襖步出監(jiān)牢的瞬間辣苏,已是汗流浹背肝箱。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留稀蟋,地道東北人煌张。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像退客,于是被迫代替她去往敵國和親骏融。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內容

  • 工廠模式類似于現(xiàn)實生活中的工廠可以產生大量相似的商品萌狂,去做同樣的事情档玻,實現(xiàn)同樣的效果;這時候需要使用工廠模式。簡單...
    舟漁行舟閱讀 7,777評論 2 17
  • 在JavaScript編程中凉当,this關鍵字總是讓初學者感到迷惑,F(xiàn)unction.prototype.call和...
    白小蟲閱讀 409評論 0 1
  • 第一部分 準入訓練 第1章 進入忍者世界 js開發(fā)人員通常使用js庫來實現(xiàn)通用和可重用的功能树灶。這些庫需要簡單易用纤怒,...
    如201608閱讀 1,354評論 1 2
  • 單例模式 適用場景:可能會在場景中使用到對象糯而,但只有一個實例天通,加載時并不主動創(chuàng)建,需要時才創(chuàng)建 最常見的單例模式熄驼,...
    Obeing閱讀 2,076評論 1 10
  • 陽光明媚獨品味像寒, 一盅兩件慰勞胃。 飲歌慢調陶醉人瓜贾, 有情無伴亦無謂诺祸。
    康真閱讀 218評論 0 0