posts - 7,  comments - 58,  trackbacks - 0

               Prototype的bind方法常常把許多學習它的人弄得糊糊涂涂,google和baidu一番后還是一塌胡涂!本人也如此;本人覺得它是個從“謎人”到“迷人”的方法。此文將發表個人對此方法的理解,希望能幫助大家成功渡“謎”,到達“迷人”的彼岸!
          <html>
          <head>
           <script src="prototype.js"></script> //@7
           <script type="text/javascript">
             /**********************************
              *
              *  實現渲染一個帶有"上一頁"和"下一頁"的組件,點擊"上一頁",當前頁減1,點擊"下一頁"當前頁加1
              *
              */
             function PagesSystem(container){
               this.currentPage = 10; //當前頁
               this.pageSysDiv = document.getElementById(container); //容器
              
               this.init = function() { //將組件畫出來
                 this.createPrePage();
                 this.createNextPage();
               };
              
               this.changePage = function(evtObj) { //根據點擊后傳過來的參數決定是加1或是減1
                  if(evtObj == "next") {
                    this.currentPage += 1;
                    alert("你已執行將當前頁加1,現在當前頁是:" + this.currentPage);
                  }else if(evtObj == "pre"){
                    //此處不作if(this.currentPage ==1) return;限制為了體現當傳入的參數為"pre"時,下面的alert()一定會執行
                    this.currentPage -= 1;
                    alert("你已執行將當前頁減1,現在當前頁是:" + this.currentPage);
                  }
                
               };
              
               this.createPrePage = function() {//創建上一頁組件
                 var _span = document.createElement("SPAN");
                 _span.style.cssText = "margin-left:16px";
                 var _a = document.createElement("A");
                 _a.href = "#";
                 _a.onclick = this.changePage; //@1 當點擊此("上一頁")銨鈕時執行
                 _a.innerText = "上一頁";
                 _span.appendChild(_a);
                 this.pageSysDiv.appendChild(_span);
               };
              
               this.createNextPage = function() {//創建下一頁組件
                 var _span = document.createElement("SPAN");
                 _span.style.cssText = "margin-left:16px";
                 var _a = document.createElement("A");
                 _a.href = "#";
                 _a.onclick = this.changePage; //@2 當點擊此("下一頁")銨鈕時執行
                 _a.innerText = "下一頁";
                 _span.appendChild(_a);
                 this.pageSysDiv.appendChild(_span);
               };
             
               this.init(); //執行初始化
             }
             function testUse(msg){//@3在提出問題環節用到
               alert(msg);
             }
             window.onload = function() {
               var ps = new PagesSystem("pageDiv");
             }
           </script>
          </head>
          <body>
            <div id="pageDiv"></div>
          </body>
          </html>

          二、分析代碼,提出問題,解決問題
          1、無法傳遞參數問題。
             你細看@1和@2處,當前的代碼實現是無法把"pre"和"next"參數傳遞過去,于是,當你運行例子,點擊上一頁或下一頁,都是沒信息alert出來的!
             這種情況,是很常見的。那么,如何實現將參數傳過去。
             將@1處代碼修改如下:
                              _a.onclick = function(){ //@1 當點擊此("上一頁")銨鈕時執行
                                   testUse("pre"); //參看@3
                                   this.changePage("pre");
                              }
             這樣創建一個匿名函數賦予_a.onclick,也就是當_a對象的onclick事件觸發后將執行此匿名函數,而匿名函數將幫忙調用testUse("pre")和this.changePage("pre")兩個方法,
             從而達成傳遞參數。
             修改代碼,運行例子后點擊上一頁后會顯示如下兩個信息,一個是testUse中輸出的信息,證明了實現參數傳遞,另一個卻是運行錯誤提示。
             

             這是執行this.changePage("pre")方法拋出來的。它并沒像我們預期想的運行。
             從提示獲到的信息是,對象不支持此屬性或方法(如果瀏覽器報的是中文提示就可以看到“對象不支持此方法或屬性”的提示)
             回頭看this.changePage("pre")方法,很明顯this是錯誤提示中所指的對象,在本應用中指PagesSystem對象指針的引用,在應用中確實是聲明了this.changePage("pre")方法,但為什么說沒此方法呢????
          2、在問題1中,我們已成功解決傳遞參數,但PagesSystem對象的changePage方法被誰偷了???
             再將剛才的代碼修改如:
                               _a.onclick = function(){ //@1 當點擊此("上一頁")銨鈕時執行
                                 testUse("pre"); //參看@3
                                 alert(this.tagName);
                                 this.changePage("pre");
                              }
             再運行例子,你會發現輸出this.tagName的值為 A, 它就是_a對象。噢,我的天啊。怎么會這樣???
             哈哈..._a對象就是<a href=""/></a>這個html 元素對象,這里是“上一頁”銨鈕對象,原型中哪來changePage方法啊,所以報錯!!!
             你可以這樣理解,看如下代碼:
               function PagesSystem(container){//此應用中的PagesSystem對象,changePage方法的上下文對象,也可以稱為歸屬者。
                 //...省略其它代碼
                 this.changePage = function(evtObj) { //根據點擊后傳過來的參數決定是加1或是減1
                   if(evtObj == "next") {
                     this.currentPage += 1;
                     alert("你已執行將當前頁加1,現在當前頁是:" + this.currentPage);
                   }else if(evtObj == "pre"){
                     //此處不作if(this.currentPage ==1) return;限制為了體現當傳入的參數為"pre"時,下面的alert()一定會執行
                     this.currentPage -= 1;
                     alert("你已執行將當前頁減1,現在當前頁是:" + this.currentPage);
                   }
                 };
                 //...省略其它代碼
               }
              
               這樣的代碼,你很容易看出this是指PagesSystem, 那么我們繼續往下看
               假設 A對象的原型如下:
               function A() {//@4
                 //...
                  this.onclick;
                 
                  this.doClick = function() { //點擊
                    this.onclick();//執行
                  }
                
                 //...
               }
              
               當你在PagesSystem方法中
                             _a.onclick = function(){ //@1 當點擊此("上一頁")銨鈕時執行
                                 testUse("pre"); //參看@3
                                 alert(this.tagName);
                                 this.changePage("pre");
                              }
              寫上這樣的代碼后,你可以離譜認為@4的代碼的模樣是如下:
              function A() {//@4
                 //...
                  this.onclick = function(){ //@1 當點擊此("上一頁")銨鈕時執行
                       testUse("pre"); //參看@3
                       alert(this.tagName); //@5
                       this.changePage("pre"); //@6
                    };
                 
                  this.doClick = function() { //點擊
                    this.onclick();//執行
                  }
                 //...
               }
               呵呵。。如果這樣看的話,@5,@6中的this當然是指a對象,沒異義。那當然是沒changePage方法。
              
          3、那么如何解決這問題呢??
             很幸運,prototype.js中的bind方法就可以解決這樣的問題,它還解決我們上面提的傳參數問題。
             看bind大俠帥樣:
            
             bind: function() {
              if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
              var __method = this, args = $A(arguments), object = args.shift();
              return function() {
                return __method.apply(object, args.concat($A(arguments)));
              }
            }
            bind方法中的this就是bind方法的所屬者(上下文)如: f.bind(),f是一個聲明了的方法,那么bind 方法里的this就是f
            再細看,bind方法其實做的工作是返回一個匿名函數,此匿名函數幫忙執行this所指的方法(bind方法的所屬者),如果你有如下代碼
            function f(msg) {
              this.functionName = "f method";
              alert(msg);
              alert(this.functionName);
            }
           
            button.onclick = f.bind(this, msg); //這里的this指f, 在bind方法中用object = args.shift()獲得,這樣的話,當點擊button后執行f方法, f方法中的this就不會無故被 button代替。^_^不然,會報錯的啊,button哪來functionName,呵呵...
            它既解決將msg參數傳過去,同時將f綁定到button環境下,bind方法得名可能就是這意義吧。至于如何實現將f綁定,靠的就是apply方法。
            apply謎人色彩就由你們自行去揭開啦!
            介紹了bind大俠給大家,我的例子就麻煩你們自己調通它啦。謝了。。
            
            歡迎交流指正。

           備注: 如需轉載本文,請注明出處
              

          posted on 2008-05-08 22:37 Sonny Li 閱讀(1939) 評論(6)  編輯  收藏 所屬分類: Prototype學習志

          FeedBack:
          # re: Prototype學習志 之 bind方法的“謎”迷人色彩!
          2008-05-08 23:21 | 鄭暉
          如果在瀏覽器中debug javascript,建議用Firefox的Firebug,它比IE好得太多了。  回復  更多評論
            
          # re: Prototype學習志 之 bind方法的“謎”迷人色彩!
          2008-05-08 23:45 | 無羽蒼鷹
          嗯,,謝謝 ^^  回復  更多評論
            
          # re: Prototype學習志 之 bind方法的“謎”迷人色彩!
          2008-05-09 22:39 |
          一樓建議不錯。。前幾天剛了解到。。  回復  更多評論
            
          # re: Prototype學習志 之 bind方法的“謎”迷人色彩!
          2008-07-30 11:31 | 杜東輝
          本人到此一游,有好東東多分享一下呀,多姐!!!  回復  更多評論
            
          # re: Prototype學習志 之 bind方法的“謎”迷人色彩!
          2009-01-20 11:15 | fujw
          挺 好  回復  更多評論
            
          # re: Prototype學習志 之 bind方法的“謎”迷人色彩![未登錄]
          2012-10-03 16:11 | lc
          我在IE中提示對象不支持“bind”屬性或方法
          請問這個是怎么回事呢?  回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2012年10月>
          30123456
          78910111213
          14151617181920
          21222324252627
          28293031123
          45678910

          常用鏈接

          留言簿(3)

          隨筆分類

          隨筆檔案

          文章分類

          相冊

          收藏夾

          博客好友

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 永清县| 伊春市| 威海市| 丘北县| 龙州县| 诏安县| 沧州市| 抚远县| 东兴市| 商南县| 新竹市| 平阴县| 县级市| 保定市| 慈溪市| 鹤峰县| 遂溪县| 慈利县| 鹿邑县| 钟山县| 新宁县| 北碚区| 庆安县| 肥西县| 营口市| 和硕县| 临泽县| 临高县| 准格尔旗| 定边县| 遂平县| 屯留县| 上思县| 陇西县| 洞口县| 镇安县| 乌兰县| 塘沽区| 会昌县| 石城县| 长泰县|