有人的地方就有江湖,有函數的地方就有
this
。而this在不一樣的環境下,又表現爲不一樣的形式,不免讓人有種此this非彼this的疑惑javascript
在java等面向對象的語言中,this指的就是當前對象,而在javascript中這就不靈了,javascript中this是在編譯期動態綁定的,這就造成了一把雙刃劍:足夠靈活卻又容易讓人迷惑。在javascript中this能夠是全局對象、當前對象甚至任意對象(obj.call(this)
)。
咱們經過函數的幾種不一樣調用方式來看一下各自this的意義:java
在javascript中函數也是個對象,所以,函數能夠做爲一個對象的屬性出現:程序員
var object = { name:"jeffie", sayWhat:function(){ console.log(this.name + ":hello"); //jeffie:hello } } object.sayWhat();
此處的this指向object對象,也就是函數所在的對象。segmentfault
當函數直接被調用時,此時函數中的this指向全局變量,也就是window對象:數組
function obj(){ console.log(this); } obj();//Window
在做爲構造函數調用時,this指向的是新生成的實例對象:閉包
function Plugin(name,type){ this.name = name; this.type = type; } var plugin = new Plugin("core",1); console.log(plugin.name);//core
javascript中每一個函數都包含兩個方法:apply()和call(),這兩個方法很是強大,它們能夠切換函數的上下文執行環境,也就是說能夠修改this綁定的對象。簡單來講,這兩個方法能夠用來設置函數的this,兩個方法都接收兩個參數,第一個參數是運行函數的做用域,第二個參數是參數對象,惟一的區別是apply第二個參數爲參數數組(Array或者arguments):app
function Plugin(name,type){ this.name = name; this.type = type; this.debugs = function(name,type){ console.log(this); //Object {name: "base", type: 3} } } var plugin1 = new Plugin("core",1); var plugin2 = {name:"base",type:3}; console.log(plugin1.debugs.call(plugin2));
經過上面的示例能夠看出this值再也不指向Plugin對象了,而是指向了plugin2的對象。函數
一般咱們理解this對象是運行時基於函數綁定的,全局函數中this對象就是window對象,而當函數做爲對象中的一個方法調用時,this等於這個對象。因爲匿名函數的做用域是全局性的,所以閉包的this一般指向全局對象window:this
var scope = "global"; var object = { scope:"local", getScope:function(){ return function(){ return this.scope; } } }
調用object.getScope()()返回值爲global而不是咱們預期的local,在閉包中函數做爲某個對象的方法調用時,要特別注意,該方法內部匿名函數的this指向的是全局變量。參考上一篇閉包
這屬於 JavaScript 的設計缺陷,正確的設計方式是內部函數的 this 應該綁定到其外層函數對應的對象上,爲了規避這一設計缺陷,聰明的 JavaScript 程序員想出了變量替代的方法,只須要把外部函數做用域的this存放到一個閉包能訪問的變量裏面便可,約定俗成,該變量通常被命名爲 that:debug
var scope = "global"; var object = { scope:"local", getScope:function(){ var that = this; return function(){ return that.scope; } } } object.getScope()()返回值爲local。