this在全局中調用時指向的是全局對象。
this在函數中調用時指向調用函數的對象,調用函數的在不一樣狀況下有javascript
1.直接調用,此時函數內部的this指向全局對象 2.做爲對象的方法,此時this指向該對象 3.構造函數,此時this指向構造的實例對象 4.call/apply改變this指向
this是Javascript語言的一個關鍵字。
它表明函數運行時,自動生成的一個內部對象,只能在函數內部使用。好比,html
function test(){ this.x = 1; }
隨着函數使用場合的不一樣,this的值會發生變化。可是有一個總的原則,那就是this指的是,調用函數的那個對象。
下面分四種狀況,詳細討論this的用法。java
這是函數的最一般用法,屬於全局性調用,所以this就表明全局對象global/window(在瀏覽器中全局對象即頂層對象指的是window,在nodejs中全局對象指的是global)。
請看下面這段代碼,它的運行結果是1。node
function test(){ this.x = 1; alert(this.x); alert(this === window); test(); // 1 //true
爲了證實this就是全局對象,我對代碼作一些改變:瀏覽器
var x = 1; function test(){ alert(this.x); } test(); // 1
運行結果仍是1。再變一下:app
var x = 1; function test(){ this.x = 0; } test(); alert(x); //0
當調用函數test()後,執行this.x 語句,而這裏的this.x指向的是全局的x,因此全局的x=1在這個時候變成x=0,因此在最後alert(x)的時候數據0。
從這裏能夠看出函數裏的 this.x 指的是全局變量x裏吧。函數
那若是是帶有參數的函數呢?再來看看下面的例子:this
var a = 20; function fun(a){ this.a = 1; console.log(a); console.log(this.a); }; fun(10); //10 //1
當函數帶有參數時,this依舊指向全局的變量,與參數沒有任何關係,上面的寫法就相似於下面的這種寫法。code
var a = 20; function fun(b){ this.a = 1; console.log(b); console.log(this.a); }; fun(10); //10 //1
若是把this.a改爲this.b呢?那this.b指向的是全局的變量仍是函數裏面的變量呢?htm
var a = 20; function fun(b){ this.b = 1; //沒有用var 至關於定義了一個全局變量b,並賦值爲1 console.log(b); //10 打印出傳入的參數b console.log(this.b); //1 打印出全局變量b }; fun(10); console.log(b); //1 打印出全局變量b
JavaScript裏規定,全局函數裏沒有用var定義的的變量是全局變量,因此這裏的this.b就至關於定義了一個全局的變量b,因此在最後能打印出變量b
如今你能看懂下面兩個函數了吧
var a = 20; function fun(a){ this.a = 1; console.log(a) }; console.log(a);//20 沒有執行this.a=1 語句時,全局變量a依舊爲20 fun(10);//10 var a = 20; function fun(a){ this.a = 1; console.log(a) }; fun(10);//10 console.log(a);//1 執行this.a=1 語句後,全局變量a變爲1
函數還能夠做爲某個對象的方法調用,這時this就指這個上級對象。
function test(){ alert(this.x); } var o = {}; o.x = 1; o.m = test; o.m(); // 1
或者用對象字面量來建立方法是好理解些,但都是一個意思
var pet = { words : 'my dear', speak : function(){ console.log(this.words); //my dear console.log(this === pet); //true } } pet.speak();
所謂構造函數,就是經過這個函數生成一個新對象(object)。這時,this就指這個新對象。
function test(){ this.x = 1; } var o = new test(); alert(o.x); // 1
運行結果爲1。爲了代表這時this不是全局對象,我對代碼作一些改變:
var x = 2; function test(){ this.x = 1; } var o = new test(); alert(x); //2
運行結果爲2,代表全局變量x的值根本沒變。
再來看一個在實際應用中的例子
function Pet(words){ this.words = words; this.speak = function(){ console.log(this.words); console.log(this) } } var cat = new Pet('Miao'); cat.speak(); //當nwe了一個實例對象cat後,cat擁有了本身的word屬性和speak方法,而cat.speak()調用時this指的的是cat對象本身 // Miao //Pet { words: 'Miao', speak: [Function] }
apply()是函數對象的一個方法,它的做用是改變函數的調用對象,它的第一個參數就表示改變後的調用這個函數的對象。所以,this指的就是這第一個參數。
var x = 0;
function test(){
alert(this.x);
}
var o={};
o.x = 1;
o.m = test;
o.m.apply(); //0
apply()的參數爲空時,默認調用全局對象。所以,這時的運行結果爲0,證實this指的是全局對象。
若是把最後一行代碼修改成
o.m.apply(o); //1
運行結果就變成了1,證實了這時this表明的是對象o。
apply有兩種實際的應用場景:
1.在對象中--調用時才改變this指向,如上例子,也許下面的例子好理解些
var pet = { words : 'my dear', speak : function(say){ console.log(say + ' ' +this.words) } } pet.speak('hello');//hello my dear //利用apple調用時改變this的指向 var dog = { words :'wang' } pet.speak.call(dog,'hello');//hello wang pet.speak('hello')//hello my dear
2.實現繼承時的構造函數--定義時改變this指向
function Pets(words,sex){ this.words = words; this.sex = sex; this.speak = function(){ console.log(this.words + ' ' + this.sex) } } function Dog(words,sex){ //Pets.call(this, words, sex); //Pets.apply(this,[words, sex]) Pets.apply(this,arguments) } var dog = new Dog('wang','girl') dog.speak();//wang,girl
參考資料:
1.《JavaScript的this用法》--阮一峯