總結js中this的指向問題

咱們知道js中有個全局對象就是window,若是在頂層聲明一個變量如javascript

var a=1 //就至關於window.a=1

同時有了node之後,js也能夠在服務端運行了,官方解釋爲Node.js 是一個基於 Chrome V8 引擎的 JavaScript 運行環境。通俗說node是一個支持js語法的容器,直接寫js就能夠在node下運行。這裏介紹node主要說一下在node中的全局變量叫global,就像window同樣有一些js默認的變量和方法。下面只探討this在瀏覽器中的指向,有興趣的也能夠把後面的例子在node中跑一下。java

this通常在函數中使用比較多,那就從函數提及吧,咱們調用的函數通常分爲聲明式函數,或者是放在對象中做爲方法的函數

1、聲明式
function demo1(){
    console.log(this)  
}
function demo2(){
    this.num=2
    function demo3(){
          this.num++
          console.log(num)
    }
    return demo3
}
demo1() // 調用demo1函數,這裏this很顯然指向window
var a=demo2();
a()  // 這裏看到會打印出3,應該也很好理解,a變量將demo2函數執行後的的返回值及demo3函數返回,而後執行,此時this依舊指向window
2、對象中的方法調用
var obj1={
      value:3,
      increment:function(){
           this.value++;
           console.log(this,this.value)
      }
}
obj1.increment() //  obj1{value:4,increment:function(){...}},4 ;打印出obj1對象和4,obj1包含一個value值和一個increment方法,也好理解

在看一個例子node

var obj2={
      value:4,
      increment:function(){
           this.value++;
           console.log(this,this.value);
           (function(){
                 console.log('這又是啥',this,this.value)
                 this.value=1
           })() 
      },
      print:function(){
            console.log('print',this.value)
      }
}
obj2.increment() 
obj2.print()
var P=obj2.print
P()
// 打印結果出以下
// {value: 5, increment: ƒ, print: ƒ} 
// 5
// 這又是啥 Window 
// undefined
// print 5
// print 1
依次分析:
第一條先執行obj2中的increment方法,跟上一個例子同樣,這裏的this是指向我obj2對象,因此this.value再執行+1之後爲5,後面是一個自執行函數,這裏面的this直接指向了window,window的value一開始不存在因此爲undefined,後面增長一個全局變量value值爲1;而後是第二條直接執行obj2中的方法print,此時的this仍是obj2因此值爲5,;而後是第三條聲明一個變量P指向obj2中的print方法,執行這個方法這是this指向window,因此輸出1
總結來講:
使用聲明式函數(後面兩個對象中的方法也是使用的聲明式函數)會自動綁定 this,直接在全局中聲明的函數 this會直接指向 window對象

延伸一下,如今咱們都常常會用的es6的箭頭函數,箭頭函數是不會自動綁定this的,默認從上一級繼承下來,那不妨把剛纔的例子改下看看

例子1改寫
var demo1=()=>{
    console.log(this)  
}
var demo2=()=>{
    this.num=2
    function demo3(){
          this.num++
          console.log(num)
    }
    return demo3
}
demo1() // 調用demo1函數,這裏this仍是指向window,由於以前說的在全局下聲明自己就有個this指向window對象
var a=demo2();
a()  // 3,這裏也同樣
例子2改寫
var obj1={
      value:3,
      increment:()=>{
           this.value++;
           console.log(this,this.value)
      }
}
obj1.increment() // 這時候會看到輸出window對象和一個NaN
簡單說明下:
如前面所說箭頭函數不會自動綁定 this,因此執行increment函數中的 this依舊會指向 window,而 window下的 value還不存在,因此爲 undefined再執行+1操做因此 value就變成了 NaN
例子3改寫
var obj2={
      value:4,
      increment:()=>{
           this.value++;
           console.log(this,this.value);
           (function(){
                 console.log('這又是啥',this,this.value)
                 this.value=1
           })() 
      },
      print:()=>{
            console.log('print',this.value)
      }
}
obj2.increment() 
obj2.print()
var P=obj2.print
P()
// 打印結果出以下
// Window 
//  NaN
// 這又是啥 Window
// NaN
// print 1
// print 1
簡單說明下:
第一個依舊 window對象(this沒綁定的嘛),後面的value固然又是沒聲明.....而後自執行函數也沒得說,後面才接着給 windowvalue賦值爲1了,後面就兩句天然輸出兩次1了
那麼箭頭函數怎麼綁定this呢,有apply,call和bind這三個方法得嘛,你們應該都知道,具體區別能夠查一下
相關文章
相關標籤/搜索