淺談javascript-this關(guān)鍵字

前言

JavaScript中this變量是一個令人難以摸清的關(guān)鍵字抹估,當初學習javascript的時候被這個this指向問題折騰的我是慘不忍睹琅轧,漏洞百出衷戈。一度想在后面的代碼過程中放棄對this的使用,但是this在javascript當中用處太廣泛了酱讶。
充分了解this的相關(guān)知識有助于我們在編寫面向?qū)ο蟮腏avaScript程序時能夠游刃有余围苫,沒辦法只能硬著頭皮上呀裤园。被虐多次再結(jié)合自己查閱相關(guān)文檔資料,總算有一點小小心得剂府。特分享出來拧揽,供大家參考!

this簡述

關(guān)于this的清this所引用的對象到底是哪一個腺占,也許很多資料上都有自己的解釋淤袜。例如我鐘愛的《高三》對this也是簡單幾頁翻過。最后翻閱到MDN上面的wen技術(shù)文檔湾笛,上面解釋深得我意饮怯。

在絕大多數(shù)情況下,函數(shù)的調(diào)用方式?jīng)Q定了this的值嚎研。this不能在執(zhí)行期間被賦值,在每次函數(shù)被調(diào)用時this的值也可能會不同库倘。
--MDN社區(qū)web技術(shù)文檔

由此可以推出this的在不同的情況下临扮,this的指向各不相同。簡單來說就分為5種情況

1教翩、全局環(huán)境

var a = "先制定一個小目標杆勇,下一頓飯加一個雞腿";
console.log(this);  // 這里this就指向 window
console.log(this.a);  //控制臺輸出  "先制定一個小目標,下一頓飯加一個雞腿"

這一種情況相信大家都非常好理解饱亿,在全局環(huán)境當中this默認是指向window

2蚜退、函數(shù)中調(diào)用

function foo1() {
   function bar() {
     console.log(this);
  }
    bar();
}
foo1();     // 輸出window

當foo1()執(zhí)行的時候 ,間接相當于window.foo1()執(zhí)行函數(shù)中的this是指向window彪笼,因此控制臺相應(yīng)輸出window結(jié)果钻注。(foo1() 間接也等于 window.foo1(),這樣就是相當于window在調(diào)用這個函數(shù),因此this也是指向于window配猫。)

3幅恋、對象中調(diào)用

var x = "今天交房租";
var obj = {
foo:function() {
    console.log(this.x);
},
x:"房租減免";
};
obj.foo();   //控制臺輸出 "房租減免"

這是當對象obj調(diào)用foo()函數(shù)泵肄,this指向了這個調(diào)用對象捆交,即this就等于obj淑翼,控制臺式輸出就變成了obj.最后控制臺便輸出 "房租減免",唉F纷贰玄括!這要是從房東嘴巴里面輸出該多好!肉瓦!

4惠豺、構(gòu)造函數(shù)中

var name = "hahaha";
function Obj() {
this.name = "CheDabang";
}
var person = new Obj();
console.log(person.name); //輸出 CheDabang

這里通過new運算符創(chuàng)建一個 Obj的對象實例。
變成person{this.name}风宁,因此這里this的指向也隨著指向這個新實例對象洁墙。因此控制臺輸出 CheDabang

5、apply戒财、call中調(diào)用

當一個函數(shù)的函數(shù)體中使用了this關(guān)鍵字時热监,通過所有函數(shù)都從Function對象的原型中繼承的call()方法和apply()方法調(diào)用的時候,它的值可以綁定到一個指定的對象上饮寞。

function add(c, d){
return this.a + this.b + c + d;
}
var o = {a:1, b:3};
console.log(add.call(o, 5, 7));              //1 + 3 + 5 + 7 = 16
console.log(add.apply(o, [10, 20]));        // 1 + 3 + 10 + 20 = 34

小練習

以上就是我們常常出現(xiàn)的5種情況孝扛,看到這么多情況的介紹。諸位看官幽崩,也暈了吧苦始。不要著急,讓我們再來幾個小練習感受一下這位this大爺的指向慌申。

this虐我千百遍陌选,不敢不待如大爺!L愀取咨油!
題目①
Code
var a = 10;
function test(){
  a = 5;
  console.log(a);
  console.log(this.a);
  var a ;
  console.log(this.a);
  console.log(a);
}
test(); 
new test();  

當調(diào)用test()的時候,控制臺分別輸出 5柒爵、10役电、10、5
當調(diào)用 new test()的時候棉胀,控制臺分別輸出 5法瑟、undefined、undefined唁奢、5

解析
var a = 10 ==> var window.a = 10 ;
當test()調(diào)用的時候霎挟,間接也相當于window.test()調(diào)用。因此當這個函數(shù)執(zhí)行的時候驮瞧,這里面的this指向的是window對象氓扛,因此this.a 指向的是window = 10;

當new test() 實例化,因此this指向的是這個實例的對象采郎,因此這個新對象的a千所,并沒有直接定義過。所以控制臺輸出undefined

題目②

Code
var Funllname = "john Doe";
var obj = {
  Funllname:"Colin Thrig",
  prop:{
    getFullname:function(){
      return this.Funllname;
    }
  },
};
 console.log(obj.prop.getFullname());
var test = obj.prop.getFullname;
 console.log(test());

控制臺輸出
undefined
john Doe

解析

控制臺結(jié)果1:當obj.prop.getFullname()在調(diào)用的時候蒜埋,相當于執(zhí)行了其中的函數(shù)淫痰。而由于調(diào)用這個函數(shù)的是obj.prop調(diào)用的,因此this就直接指向obj.prop整份,但是obj.prop這個對象當中并沒有定義Fullname,因此輸出undefined待错。

控制臺結(jié)果2:當var test = obj.prop.getFullname; 這個時候就間接相當于==>var test = function(){return this.Funllname;}
因此當test()調(diào)用的時候,就相當于 ==> window.test();,因此其中的this便指向了window對象烈评,所以便輸出了 john Doe

題目③
Code
var sex = "male";
var saySex = {
sex:"female",
saySex:function(){
    function getSex(){
        console.log("this.sex="+this.sex);
        }
    getSex();
    }
}
saySex.saySex(); 

控制臺輸出
this.sex = male

解析

控制臺結(jié)果:當saySex.saySex()調(diào)用的時候火俄,只是相當saySex的函數(shù)被調(diào)用。之后在函數(shù)中讲冠,函數(shù)getSex()被調(diào)用瓜客,此時this便指向getSex().而函數(shù)getSex()默認情況下是指向window的,因此這里輸出this.sex = male

題目④

Code
var name = "chedabang";
function sayName(){
var a = {
    name:"加一個雞腿",
    sayName:getName
};

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

getName(); 
a.sayName(); 
getName.call(a);
}
sayName();

控制臺輸出
chedabang
加一個雞腿
加一個雞腿

解析

當sayName()運行的時候時候竿开,先是里面的第一個函數(shù)運行谱仪,getName().因此因此其中的this,便默認指向了window否彩,因此this.name ==> chedabang
其次a.sayName()運行疯攒,因為sayName = getName。所以即當于getName再次被調(diào)用列荔,由于存在調(diào)用對象a敬尺。因此此時this又重新指向?qū)ο骯,對象 a 當中存在name屬性肌毅,因此輸出加一個雞腿筷转。
最后 getName.call(a).運行的時候,將對象a給綁定到上面悬而,因此函數(shù)里面的this就不指向window,而指向的是綁定的對象a锭汛,因此輸出 加一個雞腿

題目⑤

Code
var a = {
    name:"張三",
    sayName:function(){
    console.log("this.name="+this.name);
  }
};
var name = "李四";
function sayName1(){
  var sss = a.sayName;
  sss();
  a.sayName();
  (a.sayName)();
  (b = a.sayName)();
}
sayName1();

控制臺輸出:
this.name=李四
this.name=張三
this.name=張三
this.name=李四

解析

當sayName1()運行的時候笨奠,sayName1函數(shù)內(nèi)部首先是
控制臺結(jié)果1:var sss = a.sayName ==> var sss = function(){console.log("this.name="+=this.name);} 像前面我們總結(jié)的一樣函數(shù)中調(diào)用,因此這里的this指向window對象唤殴,因此輸出this.name=李四
控制臺結(jié)果2:a.sayName();這里a直接調(diào)用其中的匿名函數(shù)般婆,因此此時this指向a,因此a.name = "張三"朵逝,所有控制臺輸出this.name=張三

控制臺結(jié)果3:這里(a.sayName)();其實間接相當于 == a.sayName();這里指的是值立即執(zhí)行蔚袍。不管如何始終是對象a在調(diào)用sayName這個函數(shù)。因此控制臺也就跟著一起輸出this.name=張三

控制臺結(jié)果4:和控制臺結(jié)果3一樣啤咽,代表變量b立即執(zhí)行晋辆,而b和控制臺結(jié)果1中sss一樣,也屬于函數(shù)中調(diào)用宇整,因此this這里指向window瓶佳。即控制臺輸出this.name=李四

看到這里是不是豁然開朗了,相信進過this這么幾道題的磨練,大家應(yīng)該對this了解有加深了不少鳞青。如果講的有錯誤,還請大牛們給指出來,在此謝謝了.
沒有雞腿霸饲,感覺靈魂被掏空!1弁亍厚脉!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市胶惰,隨后出現(xiàn)的幾起案子傻工,更是在濱河造成了極大的恐慌,老刑警劉巖童番,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件精钮,死亡現(xiàn)場離奇詭異,居然都是意外死亡剃斧,警方通過查閱死者的電腦和手機轨香,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來幼东,“玉大人臂容,你說我怎么就攤上這事「罚” “怎么了脓杉?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長简逮。 經(jīng)常有香客問我球散,道長,這世上最難降的妖魔是什么散庶? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任蕉堰,我火速辦了婚禮,結(jié)果婚禮上悲龟,老公的妹妹穿的比我還像新娘屋讶。我一直安慰自己,他們只是感情好须教,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布皿渗。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪乐疆。 梳的紋絲不亂的頭發(fā)上划乖,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音诀拭,去河邊找鬼迁筛。 笑死,一個胖子當著我的面吹牛耕挨,可吹牛的內(nèi)容都是我干的细卧。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼筒占,長吁一口氣:“原來是場噩夢啊……” “哼贪庙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起翰苫,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤止邮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后奏窑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體导披,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年埃唯,在試婚紗的時候發(fā)現(xiàn)自己被綠了撩匕。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡墨叛,死狀恐怖止毕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情漠趁,我是刑警寧澤扁凛,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站闯传,受9級特大地震影響谨朝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜甥绿,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一叠必、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧妹窖,春花似錦、人聲如沸收叶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蜓萄,卻和暖如春隅茎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嫉沽。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工辟犀, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绸硕。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓堂竟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親玻佩。 傳聞我的和親對象是個殘疾皇子出嘹,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

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