JAVA & XML & JAVASCRIPT & AJAX & CSS

          Web 2.0 技術(shù)儲備............

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            77 隨筆 :: 17 文章 :: 116 評論 :: 0 Trackbacks

          [from] http://birdshome.cnblogs.com/archive/2005/06/07/169168.html

          在"JavaScript中this關(guān)鍵字使用方法詳解"一文中,我曾例舉了在JavaScript和JScript中的8種this關(guān)鍵字的方式。這不又發(fā)現(xiàn)還有兩種this關(guān)鍵字的使用方式當(dāng)時沒有說到,現(xiàn)補(bǔ)充說明一下。并且通過第一種this關(guān)鍵字使用的說明,能讓我們更好的理解JavaScript作為Object-Based語言的本質(zhì)。

          ??? 一種是和JavaScript類中的定義有關(guān),我們知道當(dāng)我們定義如下類的時候:?


          function ?JSClass()
          {
          }

          JSClass.prototype.m_Properties? = ? 100 ;

          JSClass.prototype.ToString? = ? function ()
          {
          ????alert(
          this .m_Properties);
          }


          ??? 方法ToString中的this.m_Properties就是100,那么下面這種定義呢?

          function ?JSClass()
          {
          }

          JSClass.m_Properties?
          = ?-1 00 ;

          JSClass.ToString()
          {
          ????alert(
          this .m_Properties);
          }


          ??? 這時ToString中的這個this.m_Properties是啥?是-100。一定嗎?這個不一定了,這得看我們怎么調(diào)用這個ToString方法。

          JSClass.ToString();
          var ?fun? = ?JSClass.ToString();
          fun();


          ??? 這時的運(yùn)行結(jié)果居然是:-100和undefined。真是郁悶哈,怎么才能運(yùn)行fun得到-100呢?需要這樣來為fun賦值:
          ?

          var ?fun? = ? function ()?{?JSClass.ToString();?}
          fun();


          ??? 呵呵,這樣就是-100了。好像挺廢話的,最終不還是調(diào)用的JSClass.ToString()嗎?這個我們后面再說,看看把這兩個JSClass合在一起是什么情況呢?


          function ?JSClass()
          {
          }

          JSClass.m_Properties?
          = ? - 100 ;
          JSClass.prototype.m_Properties?
          = ? 100 ;

          JSClass.ToString?
          = ? function ()
          {
          ????alert(
          this .m_Properties);
          }

          JSClass.prototype.ToString?
          = ? function ()
          {
          ????alert(
          this .m_Properties);
          }


          ??? 這兩個ToString()方法,和里面的this關(guān)鍵字它們是什么關(guān)系呢?看下面的示例:

          var ?jsclass? = ? new ?JSClass();
          jsclass.ToString();
          JSClass.ToString();


          ??? 結(jié)果為:100和-100。這里的jsclass實(shí)際上是JavaScript的語言機(jī)制,通過new關(guān)鍵字的說明來創(chuàng)建的一個新的實(shí)例。而JSClass是什么呢?他們本就是對象實(shí)例,只是長得像個函數(shù),也像一個類的說明。對于this的問題,第一個jsclass.ToString()方法里的this是指新創(chuàng)建實(shí)例,而JSClass.ToString()方法里的this是值得JSClass這個對象實(shí)例。

          ??? 理解了這兩個this指代的東西的不同本質(zhì),也就能更好的明白,為什么JavaScript叫做Object-Based的語言,而更加清楚它和Object-Oriented語言的本質(zhì)區(qū)別。

          ??? 回頭再說一下補(bǔ)充第二中this的使用方法,就是在使用eval方法的時候,這個時候的this是什么呢?看看:

          alert( this ? === ?eval( " this " ));


          ??? 的結(jié)果是什么?是true!這是因為eval內(nèi)代碼被執(zhí)行的作用域就是當(dāng)前頁面本身的說。

          posted on 2005-06-07 13:37 birdshome 閱讀(1883) 評論(10) ?編輯?收藏收藏至365Key 所屬分類: JScript&DHTML開發(fā)

          評論

          # ?re: JScript中的"this"關(guān)鍵字使用方式補(bǔ)充??回復(fù)??

          hehe,都快暈了
          2005-06-08 01:09 | robaggio

          # ?re: JScript中的"this"關(guān)鍵字使用方式補(bǔ)充??回復(fù)??

          JSClass.m_Properties = -100;

          這種方式是定義靜態(tài)屬性,當(dāng)然不能用this來調(diào)用啦。
          2005-08-15 19:20 | Avlee

          # ?re: JScript中的"this"關(guān)鍵字使用方式補(bǔ)充??回復(fù)??

          @Avlee
          。。。你看完文章了嗎?
          2005-08-15 22:21 | birdshome

          # ?re: JScript中的"this"關(guān)鍵字使用方式補(bǔ)充??回復(fù)??

          有種類叫Function,任何函數(shù)/構(gòu)造器,都是它的實(shí)例
          改變這個構(gòu)造器的原型中的屬性自然和改變這個構(gòu)造器對象的屬性是不一樣的
          2005-08-29 23:13 | ShiningRay

          # ?re: JScript中的"this"關(guān)鍵字使用方式補(bǔ)充??回復(fù)??

          一點(diǎn)心得,請birdhome兄斧正!
          在javascript里面,自定義類的定義中的this和該類的方法定義中的this不一樣,得用call函數(shù)或者apply函數(shù)轉(zhuǎn)換。這對于用慣了c#剛剛接觸javascript面向?qū)ο缶幊痰呐笥眩ū救司褪瞧渲兄唬﹣碚f是個容易出錯的地方。javascript函數(shù)定義中的this就是指函數(shù)本身,不能想當(dāng)然的認(rèn)為它指的是外層的類實(shí)例或者其他什么別的東西。prototype.js里面的bind方法可以用來轉(zhuǎn)換這個this。而且利用javascript函數(shù)的一個似乎是比較奇怪的特性——函數(shù)定義的參數(shù)個數(shù)可以跟函數(shù)調(diào)用時傳入的參數(shù)個數(shù)完全不同,可以很方便的實(shí)現(xiàn)轉(zhuǎn)換過程中的多參數(shù)傳遞問題,也就是說只要寫一個bind函數(shù),就可以轉(zhuǎn)換任意函數(shù)的上下文。

          Function.prototype.Bind = function(obj){
          var method = this;
          return function(){
          method.apply(obj,arguments);
          }
          }

          在類定義中,把obj換成this,然后調(diào)用已定義方法的Bind方法,就可以轉(zhuǎn)換方法定義中的this指針了。上面函數(shù)中的arguments是調(diào)用時實(shí)際傳給function(){...}的參數(shù)數(shù)組,所以比如我要寫一個公開的Send(arg1,arg2,arg3),它里面有this指針,怎么辦呢?我先寫一個Pri_Send(arg1,arg2,arg3),然后在類定義(注意是類定義中)中這么寫:
          this.Send = this.Pri_Send.Bind();
          大功告成,現(xiàn)在可以盡情地在類的實(shí)例上使用Send方法了。而且對于那些參數(shù)個數(shù)不同或者根本沒有參數(shù)的方法,Bind()方法同樣適用,這都是arguments的功勞,呵呵。
          此段代碼在IE6.0,FireFox1.0.7,opera 8.51下測試通過。應(yīng)該沒有太大的平臺問題。
          2006-01-13 17:48 | hzy

          # ?re: JScript中的"this"關(guān)鍵字使用方式補(bǔ)充??回復(fù)??

          @hzy
          "自定義類的定義中的this和該類的方法定義中的this不一樣",這句話我沒有明白,你是說的這種情況嗎?
          function?JSClass()
          {
          ????
          this.Property?=?'abc';
          }


          JSClass.prototype.Foo()
          {
          ????alert(
          this.Property);
          }

          這兩個this是指示的同一個東西呀。
          2006-01-13 22:18 | birdshome

          # ?re: JScript中的"this"關(guān)鍵字使用方式補(bǔ)充??回復(fù)??

          真的非常慚愧,今天早上我用了簡單的幾行代碼就證明我上面的結(jié)論是錯誤的。
          Bind()方法有用且正確,但在這里不需要,因為javascript并不像我昨天認(rèn)為的那樣奇怪,兩個this的確指的是同一個類型實(shí)例。
          經(jīng)過仔細(xì)的審查(我自己的代碼),發(fā)現(xiàn)了這個錯誤觀點(diǎn)的根源。
          雖然在birdhome兄所說的情況下,兩個this指的是同一個東西,但在某些特定情況下,卻并非如此。其根本原因還請birdhome兄多多指教。謝。
          我的代碼中就有兩處這樣的情況。
          我使用正流行的ajax設(shè)計了一個簡單的AsyncCommunicator類,用來提供更豐富的編程接口。其中兩個功能就是“更細(xì)粒度的事件處理”和“超時處理”。
          AsyncCommunicator類包含一個XmlHttpRequest屬性,這個屬性本身就是一個XMLHttpRequest類的實(shí)例。因此在AsyncCommunicator類的定義中,可以如下寫法訪問這個實(shí)例:
          this.XmlHttpRequest
          現(xiàn)在,我要給AsyncCommunicator類定義更多事件,方法是利用XMLHttpRequest的onreadystatechange屬性。如何做呢?
          我是這么寫的:
          AsyncCommunicator{
          this.XmlHttpObj= GetNewXmlHttpRequest();
          this.XmlHttpObj.onreadystatechange = this.EventStateChangeHandler;
          this.EventStateChangeHandler = function(){
          switch(this.XmlHttpObj.readyState){ case 3: this.OnTransferBack(this); break; case 4: if (!this.Pri_Aborted){
          this.Pri_HasReceived = true; this.OnReceive(this);
          switch(parseInt(((this.XmlHttpObj.status).toString()).charAt(0))){ case 1: this.OnReceive1xx(this); break;
          case 2:
          this.OnReceive2xx(this);
          break;
          case 3: this.OnReceive3xx(this);
          break;
          case 4:
          this.OnReceive4xx(this);
          break;
          case 5: this.OnReceive5xx(this);
          break;
          default:
          break;
          } //switch } //(!this.Pri_Aborted) break; default: break;
          } //switch
          } //function
          } //AsyncCommunitor

          注意這句this.XmlHttpObj.onreadystatechange = this.EventStateChangeHandler,這句就是加Bind()方法正確,不加就會出錯的源頭。經(jīng)過思考,我覺得這個this,更確切一點(diǎn)說,函數(shù)的上下文,已經(jīng)變了,不再是AsyncCommunitor,究竟是什么我也沒試出來,是否是XmlHttpObj?請birdhome兄指教。如果經(jīng)過Bind方法轉(zhuǎn)換,把this賦給Bind()方法作參數(shù),就可與更正這個問題。如下:
          this.XmlHttpObj.onreadystatechange = this.EventStateChangeHandler.Bind(this);
          我被這個問題折磨了一個晚上,因此一旦解決就緊接著犯了以偏概全的“左”傾錯誤,呵呵,把所有內(nèi)部定義的方法都看成這種情況,因此每個方法都加了Bind()方法,想來真是慚愧,正如birdhome兄所言,通常情況下無須如此,因此已經(jīng)改正。

          還有第二個情況,就是
          this.AbortWhenTimeOut方法的調(diào)用。這個方法定義如下。:
          this.Ori_AbortWhenTimeOut = function(){ if (!this.Pri_HasReceived) { this.Pri_Aborted = true; this.OnTimeOut(this); this.Abort(); } }
          在xmlhttprequest對象的open方法之后和send方法之前加入window.setTimeout方法(放在send之后就不行,奇怪,請指教),參數(shù)中就包括這個this.AbortWhenTimeOut方法,現(xiàn)在想來,很可能是window.setTimeout方法改變了this.AbortWhenTimeOut方法的上下文,導(dǎo)致該方法定義中的this指針的含義發(fā)生變化,因此不能正常執(zhí)行。同樣,自從服用了Bind()之后,腰不酸了,背不痛了,腿也不抽筋了,走路也有勁了。呵呵。

          關(guān)于上下文的這些奇妙變化(至少我覺得挺奇妙的,可能是受才智水平所限,慚愧),birdhome兄能否指教一二?
          謝謝。
          2006-01-14 15:49 | hzy

          # ?re: JScript中的"this"關(guān)鍵字使用方式補(bǔ)充??回復(fù)??

          PS,欽佩birdshome兄的專業(yè)水平。我隱約覺得javascript語言的諸多特性,是邏輯性很強(qiáng)的整體(其實(shí)事實(shí)也必然如此,用不著我去覺得,呵呵),例子舉的再多也只是“身在此山中”。遺憾我目前的水平還遠(yuǎn)遠(yuǎn)遠(yuǎn)遠(yuǎn)沒有達(dá)到可以跳出語言之外來論述語言的原理和本質(zhì)。不知道birdshome兄是否有這個空閑和興趣對javascript語言做一個總結(jié)性發(fā)言,不只是how 更重要的是why。
          這只是個非常即興的提議,更多的是某種期待。無論如何,我希望我自己也能做到,someday。
          這差不多應(yīng)該也屬于技術(shù)區(qū)的非技術(shù),呵呵,類似的話不會說第二次了。
          以后只討論技術(shù)。
          2006-01-14 16:49 | hzy

          # ?re: JScript中的"this"關(guān)鍵字使用方式補(bǔ)充??回復(fù)??

          @hzy
          ????this.XmlHttpObj.onreadystatechange = this.EventStateChangeHandler后,EventStateChangeHandler方法里的this在事件觸發(fā)后是指的window對象。第二個使用window.setTimeout也是同樣的問題,使用setTimeout觸發(fā)的方法,其內(nèi)部的this也是指的window。
          ????至于:對javascript語言做一個總結(jié)性發(fā)言。我不是很明白你具體指的內(nèi)容,畢竟JavaScript這門大家認(rèn)為"簡單"的小腳本,還是有挺多可圈點(diǎn)的內(nèi)容,似乎很難簡單的就能"總結(jié)性"道來:(
          2006-01-15 02:11 | birdshome

          # ?re: JScript中的"this"關(guān)鍵字使用方式補(bǔ)充??回復(fù)??

          我給window定義(或者說覆蓋?)了一個toString方法,讓它返回"window",然后在兩個方法開頭調(diào)用一下,果然this指的是window。多謝birdshome兄!
          現(xiàn)在我很想知道的是——為什么?
          這兩個問題背后的共性,或者說原理或者本質(zhì),究竟是什么?如何區(qū)分某個方法調(diào)用是否是這種情況?
          請birdshome兄不吝賜教。
          感謝!
          posted on 2006-03-20 09:31 Web 2.0 技術(shù)資源 閱讀(730) 評論(0)  編輯  收藏 所屬分類: Javascript
          主站蜘蛛池模板: 万荣县| 商河县| 鹰潭市| 清水县| 英德市| 武义县| 京山县| 遂宁市| 泽普县| 呼和浩特市| 河北区| 文成县| 霍邱县| 通化县| 铅山县| 吴江市| 棋牌| 陇川县| 洪湖市| 逊克县| 芷江| 云阳县| 武夷山市| 张家川| 罗田县| 嘉峪关市| 桂林市| 峨山| 合肥市| 浪卡子县| 上蔡县| 西盟| 五台县| 广宁县| 太原市| 交口县| 广水市| 华容县| 龙州县| 焦作市| 内乡县|