JavaScript:萬惡的this拿命來(一)

侃侃JavaScript中的this

this爲什麼如此多變?node

this老是跟它的執行上下文有關,而在JavaScript總會有開闢新的執行上下文的東西,好比函數,因此,this才如此的變化。

執行環境對JavaScript中的this有影響嗎?瀏覽器

JavaScript是一門解釋型語言,須要有一個執行環境去執行它,一般的執行環境是瀏覽器,還有node腳本,還有`REPL`(「讀取-求值-輸出」循環(Read-Eval-Print Loop,簡稱REPL))。

若是對REPL有興趣的話,博客中的另外一篇文章介紹了`REPL`

this默認指代誰?安全

在不一樣的執行環境中,會指代不一樣的對象

瀏覽器中:函數

> this              // Window {top: Window, window: Window,...
> this === window   //true

> var a = 1;        //在全局中,用var聲明變量,會默認給window添加
> this.a   // 1
> window.a // 1
> b = 1;            //不使用var聲明變量,會默認給全局的this添加屬性
> this.b   // 1
> window.b // 1

node腳本中oop

console.log(this);              //{}
console.log(this === global);   //false
console.log(this === window);   //ReferenceError: window is not defined

var a = 1;         //在全局中,使用var聲明變量,未給global添加屬性

console.log(this.a);            //undefined
console.log(global.a);          //undefined
console.log(window.a);          //ReferenceError: window is not defined

b = 1;            //不使用var聲明變量,會默認給全局的global添加屬性。

console.log(this.b);            //undefined
console.log(global.b);          // 1   

在node腳本中,this默認指向一個空對象,並非指向global,也不是指向window。

REPLthis

> this
{ DTRACE_NET_SERVER_CONNECTION: [Function],
  DTRACE_NET_STREAM_END: [Function],
  ...
> global === this  //true

> var a = 1;       //在全局中,使用var聲明變量,會默認給全局的global添加屬性
> this.a           // 1
> global.a         // 1

> b = 1;           //不使用var聲明變量,會默認給全局的this添加屬性
> this.b           // 1 
> global.b         // 1

實例擴展

咱們對於省略var的變量聲明方式,咱們總說它是不安全的,可是是合法的。code

爲何不安全?對象

如上文所述:不使用var聲明變量,會讓變量默認的添加到了全局的this中,這有時候會莫名的給變量提高它的做用域,從而影響其餘全局變量。

舉個栗子:ip

var position = "outer";           //this.position = "outer"

function test(){
    position = "inner";           //this.position = "inner",在函數執行後,覆蓋原先的值
    console.log(this.position);
}

test();

咱們在外部定義了一個名爲position的全局變量,它會被默認添加到全局this的屬性上。作用域

而後在咱們的test函數中,又定義了一個同名的變量,可是注意,函數中的變量聲明沒有用var

由於咱們並無對函數實例化,因此this.positionthis會默認指代全局。

而當咱們調用函數test時,函數會生成一個執行上下文,而內部position會將做用域從函數內部提高到全局,從而覆蓋(污染)了外部全局定義的position變量。

因此,在JavaScript的嚴格模式中,是不容許省略var來聲明變量的。故在聲明變量的時候,就順手加上var吧。

總結

  • this在不一樣的執行環境中的默認指代
  • 經過省略var聲明變量致使「變量提高」現象的發生及預防
相關文章
相關標籤/搜索