JS進(jìn)階系列之this

在javascript中,this的指向是在執(zhí)行上下文的創(chuàng)建階段確定的,其實(shí)只要知道不同執(zhí)行方式下,this的指向分別是是什么,就能很好的掌握this這個(gè)讓人摸不透的東西。

一、全局執(zhí)行

全局執(zhí)行又分為瀏覽器和node下的執(zhí)行環(huán)境
1、瀏覽器

console.log(this);//window

2、node

console.log(this);//global

在瀏覽器器下全局執(zhí)行的this指向window,而在node環(huán)境下全局執(zhí)行的this指向global

二、函數(shù)執(zhí)行

函數(shù)執(zhí)行又分為純粹的函數(shù)調(diào)用還有嚴(yán)格模式下的函數(shù)調(diào)用
1、純粹的函數(shù)調(diào)用

function test(){
   console.log(this);
}
test();//window

2、嚴(yán)格模式下的函數(shù)調(diào)用

'use strict'
function test(){
  console.log(this);
}
test();//undefined

純粹的函數(shù)調(diào)用的時(shí)候,this默認(rèn)在全局執(zhí)行,所以指向window,但是在嚴(yán)格模式下,this指向undefined

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

當(dāng)作為對(duì)象的方法調(diào)用的時(shí)候,this指向當(dāng)前的對(duì)象

var obj = {
  name:'McRay';
  foo:function(){
    console.log(this.name);
   }
}
obj.foo();//McRay

我們還可以這樣寫

function test(){
  console.log(this.name);
}
var obj = {
    name:'McRay';
    foo:test;
}
obj.foo();//McRay

對(duì)于函數(shù)test來(lái)說(shuō),函數(shù)名test是一個(gè)引用,foo:test這句話的作用就是讓foo也指向test所指向的函數(shù),所以它們調(diào)用的是同一個(gè)函數(shù),所以this指向的是foo所在的對(duì)象。

再來(lái)看一種情況,把對(duì)象的方法賦值給另一個(gè)變量,然后直接調(diào)用這個(gè)變量

var obj = {
     name:'McRay';
     foo:function(){
        console.log(this);
     }
}
var test = obj.foo();
test();//window
}

我們發(fā)現(xiàn)此時(shí)的this指向的是全局環(huán)境下的window,因?yàn)?code>obj.foo()只是一個(gè)函數(shù)引用,讓test等于這個(gè)引用,就與obj這個(gè)對(duì)象沒(méi)有了關(guān)系了,所以當(dāng)調(diào)用test()的時(shí)候,其實(shí)就是全局執(zhí)行,this就指向window。

上面的問(wèn)題在平時(shí)的編程中也會(huì)遇到,其中比較經(jīng)典的就是異步回調(diào)函數(shù)的調(diào)用,請(qǐng)看下面的例子

var obj = {
     name:'McRay';
     foo:function(){
          console.log(this);
     },
     foo2:function(){
        console.log(this);//obj
        setTimeout(this.foo,1000);//window
    }
};
obj.foo2();

foo2()方法中的this第一次指向obj,但是為什么第二次this就指向window呢?道理其實(shí)和上一個(gè)問(wèn)題一樣,setTimeout函數(shù)的第一個(gè)參數(shù)的接受一個(gè)函數(shù),好比如fun=this.foo(),所以相當(dāng)于把this.foo()這個(gè)函數(shù)引用賦給了fun,已經(jīng)擺脫了obj對(duì)象的關(guān)系了,所以相當(dāng)于在全局環(huán)境下執(zhí)行。

解決方法是利用閉包的特性,代碼如下

var obj  = {
    name:'McRay';
    foo:function(){
        console.log(this);
    }
   foo2:function(){
       console.log(this);
       var that = this;
       setTimeout(function(){
          console.log(this);//window
          console.log(that);//obj
      },1000);
 }
}
obj.foo2();

四、作為一個(gè)構(gòu)造函數(shù)調(diào)用

在之前的文章里面,我已經(jīng)總結(jié)過(guò),在調(diào)用構(gòu)造函數(shù)(new),創(chuàng)建一個(gè)對(duì)象的過(guò)程都發(fā)生了什么,這里簡(jiǎn)單回顧一下,主要以下幾個(gè)步驟:

  • 1、創(chuàng)建一個(gè)空對(duì)象
  • 2、讓這個(gè)空對(duì)象的原型指向構(gòu)造函數(shù)的原型
  • 3、讓構(gòu)造函數(shù)中的this指向這個(gè)空對(duì)象
  • 4、返回這個(gè)新的對(duì)象
    所以我們?cè)趯?shí)例化一個(gè)對(duì)象的過(guò)程中,其實(shí)就是將this指向該實(shí)例化出來(lái)的新對(duì)象。
function Person(name){
     this.name = name;
     console.log(this);
}
var p = new Person('McRay');//p

五、箭頭函數(shù)

ES6中新增加的箭頭函數(shù),讓函數(shù)體內(nèi)的this對(duì)象,指向的就是定義時(shí)的對(duì)象,拿之前的例子說(shuō)明一下。

var obj = {
   name:'McRay';
   foo:function(){
    console.log(this);
  }
  foo2:function(){
       console.log(this);obj
       setTimeout(()=>{
           console.log(this);//obj
       }
  }
}
obj.foo2();

當(dāng)我們?cè)趕etTimeout中使用箭頭函數(shù)的時(shí)候,函數(shù)體中的this默認(rèn)指向的就是定義這個(gè)這個(gè)函數(shù)時(shí),所在的對(duì)象,就是obj

六、call、apply、bind

這三個(gè)方法的目的都是差不多,就是可以動(dòng)態(tài)改變this的指向
1、call的第一個(gè)參數(shù)接受this指向的對(duì)象,然后是逐個(gè)傳參
2、apply的第一個(gè)參數(shù)和call相同,不同的是后面?zhèn)魅氲氖菂?shù)數(shù)組
3、bind是將生成一個(gè)新的函數(shù),將該函數(shù)的this指向我們規(guī)定的對(duì)象或者函數(shù),并不會(huì)立即執(zhí)行

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持,譯者再次奉上一點(diǎn)點(diǎn)福利:阿里云產(chǎn)品券,享受所有官網(wǎng)優(yōu)惠,并抽取幸運(yùn)大...
    HetfieldJoe閱讀 7,001評(píng)論 15 54
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • 葡萄藤PPT JS中this的指向 大家好,我是IT修真院鄭州分院第6期的學(xué)員王棟,一枚正直、純潔、善良的前端程序...
    17064閱讀 679評(píng)論 0 2
  • 特別說(shuō)明,為便于查閱,文章轉(zhuǎn)自https://github.com/getify/You-Dont-Know-JS...
    殺破狼real閱讀 816評(píng)論 0 1
  • 前幾天看到一部小說(shuō),名字啥忘記了,我這人看小說(shuō)很少記得名字,記得當(dāng)時(shí)是晚上,躺在床上,越看越怕,越怕越看,架不住故...
    微波凌凌閱讀 222評(píng)論 0 0

友情鏈接更多精彩內(nèi)容