[Javascript實驗課] What is this?

javascript 中的關鍵詞 this 代指 執行上下文(Execution Contexts),函數做用域中的this,理解上來講是指調用這個函數的對象。相信如下幾個實驗能夠加深對this關鍵字的理解。javascript

實驗一:全局下的this

全局做用域下的函數裏面的this,顯然等於全局對象windowhtml

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

因此,顯然,能夠經過this,改變window裏面的全局變量java

var global = "global"

function test(){

  this.global = "global2"

}
test()
console.log(global)//global2

因此,若是你建立了一個構造函數,而後不當心調用了它,那麼至關於你爲全局對象賦值了,這個缺陷能夠經過ES5裏面的"use strict"來解決。閉包

"use strict";

var global = "global"

function test(){
  console.log(this)//undefined
  this.global = "global2"//TypeError because 'this' undefined

}
test();

嚴格模式下,全局模式下的函數內部的this爲undefined,而不會默認爲windowapp

實驗二 : 對象中的this

經過普通對象聲明的函數this函數

var myobject = {
  foo : function(){
    console.dir(this) //myobject
  }
}
myobject.foo()

foo裏面的this指向調用foo的對象myobject,這個對象裏面只有一個方法foo,所以咱們能夠經過this操做 指向對象 裏的其餘值oop

var myobject = {
  v : 5,
  foo :  function(){
        this.v ++
        console.log(this.v)//6
   } 
}

myobject.foo()

多層對象的狀況下,this指向最近的一個對象,即誰直接調用這個函數,誰是thisthis

var myobject = {
  foo : {
    bar : function(){
        console.dir(this)//foo
    }
  }

}
myobject.foo.bar()

以上狀況this指向foo對象,那麼咱們再考慮以下的狀況code

var myobject = {
  foo : function(){
    console.dir(this)//myobject
    var bar = function(){
      console.dir(this)/*window "use strict" undefined*/
    }
    bar()
  }
}
myobject.foo()

咱們能夠發現,若是在foo函數裏聲明新的函數(閉包),好比綁定事件,settimeout裏的匿名函數等狀況,這裏面的this會變爲window(嚴格模式下undefined)。
形成這個錯誤的緣由是,bar()調用的時候,是全局對象window在調用的它,而不是經過myobject調用(換句話說myobject裏面壓根就沒有bar),這種狀況下若是要經過myobject調用bar須要用到call或applyhtm

var myobject = {
  foo : function(){
    console.log(this)//myobject
    var bar = function(){
      console.log(this)
    }   

    bar.call(myobject)//myobject
  }

}
myobject.foo()

理解爲,函數中的this,跟調用時的情形有關。

構造函數經過new來賦值情形也跟對象相似,好比

function testobject(){
  this.kk = 6;
  this.dd = function(){console.log(this)};
}

var fish = new testobject
fish.dd();

/*
[object Object] {
  dd: function (){window.runnerWindow.proxyConsole.log(this)},
  kk: 6
}
*/

new操做符會將this指向構造函數構造出來的對象

實驗三:事件回調裏的this

var myobject = {
  foo : function(){
    console.log(this)//myobject

    document.body.onclick = function(){
      console.dir(this)//[object HTMLBodyElement]
    }
  }
}
myobject.foo()

點擊回調裏的this指向點擊對象

總結:解決辦法

爲避免this混亂,能夠採用下面幾種方法

經過變量傳遞

var myobject = {
  foo : function(){
    var that = this   
    document.body.onclick = function(){
      console.dir(that)//myobject
    }
  }
}
myobject.foo()

經過call或apply

var myobject = {
  foo : function(){
    var bar = function(){
      console.log(this)
    }   

    bar.call(myobject)//myobject
  }

}
myobject.foo()

直接用對象名代替this

var myobject = {
  v : 5,
  foo : function(){
    var bar = function(){
      console.log(++myobject.v)//直接修改myobject對象裏的值
    }   
    bar();
  }

}
myobject.foo()

更多相關請參考

http://www.ruanyifeng.com/blog/2010/04/using_this_keyword_in_javascript.html

http://javascript.ruanyifeng.com/oop/basic.html

https://developer.mozilla.org/zh-CN/docs/JavaScript/Reference/Operators/this#Function_context_.E5.87.BD.E6.95.B0.E4.B8.8A.E4.B8.8B.E6.96.87

http://ryanmorr.com/understanding-scope-and-context-in-javascript/

http://stackoverflow.com/questions/9468055/what-does-new-in-javascript-do-anyway

相關文章
相關標籤/搜索