萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> Javascript淺談之this

Javascript淺談之this

 這篇文章主要介紹了Javascript中的this,有需要的朋友可以參考一下

介紹 this在各種對面對象編程中起著非常重要的作用,主要用於指向調用的對象。不過在JavaScript中,this的表現存在很大差異,特別是不同執行上下文。   由前文我們知道this也是屬於執行上下文中的一個屬性,所有它命中注定和執行上下文脫不了干系。    代碼如下: activeExecutionContext = { VO: {...}, this: thisValue};     在Javascript中,this的取值取決於調用的模式。調用模式一共有四種:方法調用模式、函數調用模式、構造器調用模式和apply調用模式。   調用模式 方法調用模式 當一個函數被保存為對象的一個屬性時,我們稱它為一個方法。當一個方法被調用時,this被綁定到該對象,即方法調用模式中的this指向調用對象。這個理解起來非常容易,你是我的一個方法,你屬於我,你的this當然指向我啦。     復制代碼 代碼如下: var myObject = {         value : 0,         increment : function(inc) {              this.value += typeof inc === "number" ? inc : 1;        }     }     myObject.increment(); console.log(myObject.value);  //輸出:1 myObject.increment(3); console.log(myObject.value);   //輸出:4     因為可以通過this訪問到自己所屬的對象,所有可以通過它調用和修改對象中屬性或者方法。由前文可知,this作為執行上下文中屬性的一員,必然是在上下文創建時才創建,所有this到對象的綁定發生在調用的時候,這屬於“延遲綁定”。通過延遲綁定可以實現對this的高度復用。     復制代碼 代碼如下: function showValue(){         console.log(this.value);   } var a = { value : "a"}; var b = { value : "b"}; a.showValue = showValue; b.showValue = showValue; a.showValue();  //輸出“a” b.showValue();  //輸出“b”     上例中函數showValue就屬於延遲綁定。   函數調用模式 當一個函數並非作為一個對象的方法來調用,這時就是函數調用。函數調用模式中,this被綁定到全局對象。(這是語言設計上的一個錯誤) 代碼如下: myObject.double = function(){     var that = this;   //解決方法     var helper = function(){         console.log(that, ": ", that.value); //輸出 Object {value: 4, increment: function, double: function} ": " 4         console.log(this, ": ", this.value); //輸出  Window {top: Window, window: Window…} ": " undefined     }       helper(); //以函數形式調用 }   按照正常思路,應該如第四行所輸出那樣,this指向函數所屬對象,可是由於語言設計上面的問題導致this指向的卻是全局對象。這個更是讓this變得神秘,令人捉摸不透。但是作為開發者,這種情況肯定是我們所不願意見到的,不按常理出牌這是,還好補救措施也很簡單,就是上例中用that指代this。這樣,在helper方法中調用that就可以當this使用,簡單方便。至於函數調用模式為什麼this會這樣,後面在分析引用類型時會詳加說明。   構造器調用模式 由於javascript是基於原型繼承,但是它的設計者又想要它能像傳統的面向對象語言那樣能通過new和構造函數創建對象,現實面向對象編程。這個貌似不是什麼好的構想,有點畫虎不成反類犬的尴尬。一是學不來,而是沒必要學。javascript的原型繼承機制已經非常強大,足以滿足面向對象所需的繼承多態。   閒話少敘,還行言歸正傳說說構造器調用模式。構造器調用模式這個非常簡單,它就是就一個函數當做構造器,然後將你打算公用的屬性和方法用this引進聲明。如下  代碼如下: function Person(name, age){         this.name = name;         this.age = age;         this.say = function(){             console.log("name : %s, age : %n", this.name, this.age);        } }   var p1 = new Person("jink", 24); p1.say(); //輸出  name : jink, age : 24   var p2 = new Person("張三", 33); p2.say();//輸出  name : 張三, age : 33       上面例子我們可以清楚看出,this是指向通過new和構造函數創建的對象。為什麼會這樣?這是因為在javascript中通過new調用構造函數時,new運算符調用“Person”函數的內部的[[Construct]] 方法,接著,在對象創建後,調用內部的[[Call]] 方法。 所有相同的函數“Person”都將this的值設置為新創建的對象。   apply調用模式 javascript中所有函數創建之後,都會自帶兩個方法:apply和call。這兩個方法的的具體使用,我在此就不想詳細說明,不知道的同學可以百度一下,挺簡單的。通過兩個方法,我們可以手動設置this。雖然this在創建時候是不允許修改的,但是,我們在創建之前,手動設置過,那就是另外一回事了。這一設置,可不得了,你就可以讓你的對象調用任意方法,就好像你可以讓汽車大海中航行,非洲象如美洲豹一樣飛馳,程序員像鋼琴師一樣彈奏。哈哈想象總是美好的,調用歸調用,但是調用了能不能實現功能就另說了。    代碼如下: var programmer = {      name : "程序員",     hand : "靈活的雙手",      programme : function(){          console.log(this.name+"用"+this.hand+"編寫代碼。");     } }   var pianist = {      name : "鋼琴家",     hand : "靈活的雙手",      play : function(){          console.log(this.name+"用"+this.hand+"彈奏動聽的樂曲。");     } }   var player = {      name : "運動員",     foot : "矯健的雙腿",      run : function(){          console.log(this.name+"用"+this.foot+"在賽場奔馳。");     } }   //循規蹈矩 programmer.programme(); //程序員用靈活的雙手編寫代碼。 pianist.play(); //鋼琴家用靈活的雙手彈奏動聽的樂曲。 player.run(); //運動員用矯健的雙腿在賽場奔馳。 //異想天開 pianist.play.apply(programmer); //程序員用靈活的雙手彈奏動聽的樂曲。 player.run.apply(programmer); //程序員用undefined在賽場奔馳。   由於自身運動缺少,沒有矯健的雙腿       上面看著是不是挺有意思的,apply的第一個參數就是執行方法中的this指向。這樣我們就可以借用別人的方法自己私下偷偷的用,可謂方便至極。在一些框架中經常用的此類技巧。   總結 關於this就說這麼多,相信大家看過之後,對在不同情境中this的判定都有些了解了,本來打算討論接下來討論引用對象的,闡述一下方法調用模式和函數調用模式中this取值的原理,但害怕篇幅過長,所以決定用單獨一章向大家分析一下引用對象這個概念。    
copyright © 萬盛學電腦網 all rights reserved