《JavaScript入門學(xué)習(xí)》之this問題

作為一個剛?cè)腴TJavaScript小白,看了不少博客提到this慷荔,尤其是提到this的指向是動態(tài)的笛辟,隨著函數(shù)的調(diào)用會改變烙荷,以及牽扯到了作用域的一些問題,還可以手動去指定或者更改this的指向等等阳液。霉翔。似乎沒那么簡單,就不明覺厲柒凉,感覺必須得花時間探究一下了族阅。

從最簡單的打印說起:

// 全局打印
console.log(this); // [object Window]
// 但是在嚴(yán)格模式下this會指向undefined
'use strict';
console.log(this); // undefined

為了方便,以下的討論是在非嚴(yán)格模式下的情況膝捞,即全局打印this === Window

分以下幾個專題討論:

var = {...}對象內(nèi)部的this

var person = { 
    name: 'chengxuyuan',
    age: 26,
    eat: function() {
       alert(this.name + '吃飯');
    }
};
console.log(person.eat); // chengxuyuan吃飯

eat方法是person找個對象調(diào)用的坦刀,因此函數(shù)內(nèi)部使用的this就指向了person。為了更加嚴(yán)謹(jǐn)?shù)倪M(jìn)行論證,我們把層級弄的深一些:

var person = { 
    name: 'chengxuyuan',
    age: 26,
    eat: function() {
       alert(this.name + '吃飯');
    },
    book: {
        name: 'one day left',
        show: function() {
             alert(this.name + ' Good!');
        }
     }
};
console.log(person.book.show); // one day left Good

調(diào)用了person的book屬性的show方法鲤遥,this指向了book沐寺,this.name 就等于one day left。
因此盖奈,函數(shù)內(nèi)部this的值是跟它的調(diào)用者對象相關(guān)聯(lián)的混坞。
那如果某個函數(shù)是直接調(diào)用,而非xx.fun()的情況下钢坦,內(nèi)部的this又會怎么指向呢究孕?繼續(xù)上代碼:

var person = { 
    name: 'chengxuyuan',
    age: 26,
    play: function(){
            function swim(){
               console.log(this);
               alert(this.name + '游泳');
            }
           swim();
    }
};
console.log(person.play); //  [object Window]  undefined游泳

發(fā)現(xiàn)swim函數(shù)內(nèi)部的this指向了Window對象,因而this.name是undefined的爹凹。
特殊之處就是person對象調(diào)用play函數(shù)執(zhí)行的時候厨诸,內(nèi)部定義完swim函數(shù),緊接著就主動執(zhí)行了逛万。
而就是swim這個主動執(zhí)行的函數(shù)泳猬,內(nèi)部的this已經(jīng)跳出了person對象的勢力范圍
因?yàn)閟wim函數(shù)主動執(zhí)行的時候宇植,調(diào)用它的對象是隱晦的得封,跟沒爹沒媽管似的,所以它內(nèi)部的this不指向person指郁,但也不能真讓他沒爹媽忙上,還是最后交給全局對象Window來管了

構(gòu)造函數(shù)對象內(nèi)部的this

構(gòu)造函數(shù)利用''new + 方法名''的方式創(chuàng)建對象闲坎,它內(nèi)部的this指向也是差不多的原理:

function Person() {
        console.log(this);
        this.name = 'chengxuyuan';
        this.age = 26;
        console.log(this.name);
   }
Person(); // [object Window]  undefined
var p = new Person(); //  [object Object] chengxuyuan

可以看出當(dāng)我們單純的直接調(diào)用執(zhí)行Person()函數(shù)疫粥,this指向Window
而我們通過new來創(chuàng)建出對象p的時候,this指向了person這個對象腰懂,因?yàn)榇蛴his.name為chengxuyuan梗逮。
還有一點(diǎn)要注意,通過prototype屬性定義函數(shù)的時候內(nèi)部的this也是指向Person的:

Person.prototype.getName =  function() {
    console.log(this.name);
}
var p = new Person();
p.getName(); // chengxuyuan

通過將函數(shù)賦值給其他變量,對內(nèi)部的this的指向的影響

function Person() {
        this.name = 'chengxuyuan';
        this.age = 26;
        this.eat = function() {
          alert(this.name + ' 吃飯');
        }
 }
var p = new Person();
var eatFunc = p.eat;
eatFunc();  // undefined 吃飯

看到清晰的認(rèn)識到eat原來屬于p绣溜,但是后來指向了全局對象eatFunc慷彤,因此eat內(nèi)部的this又動態(tài)的指向了Window。
學(xué)習(xí)到這里怖喻,就可以做一個小總結(jié)了底哗,函數(shù)內(nèi)部的this指向不是在定義的時候確定的,是被調(diào)用的時候锚沸,根據(jù)上下文場景跋选,動態(tài)的確定的。而且一般情況下都會指向調(diào)用它的對象哗蜈。**注意前标,是一般情況坠韩。可以接下來看看函數(shù)返回值對this的影響候生。

函數(shù)返回值對this的指向的影響

直接上代碼看幾個小例子:

function Person() {
     this.name = 'chengxuyuan';
     return {};
 }
var p = new Person();
console.log(p.name); //undefined

當(dāng)構(gòu)造函數(shù)返回值是空對象的時候同眯,this不指向Person绽昼。

function Person() {
     this.name = 'chengxuyuan';
     return function() {};
 }
var p = new Person();
console.log(p.name); //undefined

當(dāng)構(gòu)造函數(shù)返回值是空函數(shù)的時候唯鸭,this不指向Person。

function Person() {
     this.name = 'chengxuyuan';
     return undefined;
 }
var p = new Person();
console.log(p.name); //chengxuyuan

當(dāng)構(gòu)造函數(shù)返回值是undefined的時候硅确,this竟然又指向Person目溉。

function Person() {
     this.name = 'chengxuyuan';
     return 1;
 }
var p = new Person();
console.log(p.name); //chengxuyuan

當(dāng)構(gòu)造函數(shù)返回值是數(shù)值1的時候,this竟然又指向Person菱农。

function Person() {
     this.name = 'chengxuyuan';
     return null;
 }
var p = new Person();
console.log(p.name); //chengxuyuan

當(dāng)構(gòu)造函數(shù)返回值是null的時候缭付,this竟然又指向Person

總結(jié)一下吧:
當(dāng)構(gòu)造函數(shù)返回值為對象循未,函數(shù)的時候陷猫,this指向返回的具體對象函數(shù),當(dāng)為null或者其他值的時候的妖,this又會指向其所在的對象绣檬。

用call,apply,bind函數(shù)修改this的指向

有些業(yè)務(wù)場景下,有可能會涉及到想要修改this的指向嫂粟,那就可以利用call,apply,bind這三個函數(shù).
還是上面的一個通過將函數(shù)賦值給其他變量娇未,對內(nèi)部的this的指向的影響的例子:

function Person() {
        this.name = 'chengxuyuan';
        this.age = 26;
        this.eat = function() {
          alert(this.name + ' 吃飯');
        }
 }
var p = new Person();
var eatFunc = p.eat;
eatFunc();  // undefined 吃飯

已經(jīng)經(jīng)過由于eat函數(shù)賦值給了eatFunc,this指向了Window星虹。那如果非要讓this就指向p零抬。看下面怎么做:

call函數(shù):

var eatFunc = p.eat;
eatFunc.call(p);  // chengxuyuan 吃飯

這下this又重新指向了p宽涌。
如果在更改this指向的時候平夜,還能傳一些其他參數(shù)到eat函數(shù)里面,還可以

function Person() {
        this.name = 'chengxuyuan';
        this.age = 26;
        this.eat = function(a卸亮,b) {
          alert('a + b =' + a + b);
          alert(this.name + ' 吃飯');
        }
 }
var p = new Person();
var eatFunc = p.eat;
eatFunc.call(1,2);  // a+b=3  chengxuyuan 吃飯

apply函數(shù):

apply函數(shù)也玩法一樣忽妒,主不過需要傳多個參數(shù)的時候,是通過參數(shù)數(shù)組接收的:

var eatFunc = p.eat;
eatFunc.apply(p嫡良,[1,2]);  // a+b=3 chengxuyuan 吃飯

bind函數(shù):

apply函數(shù)也是用于修改this指向锰扶,但最大的不同是他的返回值是返回一個新的函數(shù)讓使用者接收:

var eatFunc = p.eat;
var bindfunc =  eatFunc.bind(p);  
bindfunc(); // chengxuyuan 吃飯

this在匿名函數(shù)以及箭頭函數(shù)中引起的作用域問題

后續(xù)補(bǔ)充。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末寝受,一起剝皮案震驚了整個濱河市坷牛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌很澄,老刑警劉巖京闰,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件颜及,死亡現(xiàn)場離奇詭異,居然都是意外死亡蹂楣,警方通過查閱死者的電腦和手機(jī)俏站,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來痊土,“玉大人肄扎,你說我怎么就攤上這事×拊停” “怎么了犯祠?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長酌呆。 經(jīng)常有香客問我衡载,道長,這世上最難降的妖魔是什么隙袁? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任痰娱,我火速辦了婚禮,結(jié)果婚禮上菩收,老公的妹妹穿的比我還像新娘梨睁。我一直安慰自己,他們只是感情好坛梁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布而姐。 她就那樣靜靜地躺著,像睡著了一般划咐。 火紅的嫁衣襯著肌膚如雪拴念。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天褐缠,我揣著相機(jī)與錄音政鼠,去河邊找鬼。 笑死队魏,一個胖子當(dāng)著我的面吹牛公般,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播胡桨,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼官帘,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了昧谊?” 一聲冷哼從身側(cè)響起刽虹,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎呢诬,沒想到半個月后涌哲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胖缤,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年阀圾,在試婚紗的時候發(fā)現(xiàn)自己被綠了哪廓。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡初烘,死狀恐怖涡真,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情账月,我是刑警寧澤综膀,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站局齿,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏橄登。R本人自食惡果不足惜抓歼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拢锹。 院中可真熱鬧谣妻,春花似錦、人聲如沸卒稳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽充坑。三九已至减江,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間捻爷,已是汗流浹背辈灼。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留也榄,地道東北人巡莹。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像甜紫,于是被迫代替她去往敵國和親降宅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354

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

  • 第5章 引用類型(返回首頁) 本章內(nèi)容 使用對象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學(xué)一百閱讀 3,233評論 0 4
  • 普通創(chuàng)建對象和字面量創(chuàng)建對象不足之處:雖然 Object 構(gòu)造函數(shù)或?qū)ο笞置媪慷伎梢杂脕韯?chuàng)建單個對象囚霸,但這些方式有...
    believedream閱讀 2,374評論 2 18
  • 我是歸藏邮辽,愛錢的歸藏唠雕,進(jìn)長投學(xué)習(xí)也是因?yàn)閻坼X贸营。 可能這么介紹自己有點(diǎn)簡單粗暴,但這份愛的背后有一個悲傷而又...
    歸藏17閱讀 257評論 1 0
  • 親子日記第11天岩睁,共計(jì)191天钞脂。今天周五早晨我還是上班中,大寶上學(xué)捕儒。公司舉行搶紅包活動冰啃,手氣最佳者可以得到烤...
    馨寶貝之快樂每一天閱讀 127評論 0 0
  • 怕事是因?yàn)榻?jīng)的事少 怕麻煩,有時候就會有麻煩刘莹,對這句話不知你會信否阎毅。 這麻煩不是你找來的,而是來找...
    悟道修行閱讀 655評論 0 2