javascript wrapper函數

來源:互聯網
上載者:User

在設計javascript的繼承體系時,有一個重要需求,方法鏈。通俗地說,說是在方法中調用父類的同名方法。類似java的this.super().method()。如何把父類的同名方法封裝到子類中呢?這就要用到wrapper函數。之所以叫wrapper,而不是wrap,因為它比wrap更加wrapper。比如像Ext那種深度繼承的結構中,如果父類沒有找祖父,祖父沒有找曾祖父,沿著原型鏈層層上溯,以擷取它所需要的功能。此外,wrapper函數在jQuery也有應用,好像分為三種wrapAll,wrapinner,wrap,專門用來對付IE的table或其他DOM。可能還有其他用處,不管了,先看如何?它。

一個普通的函數

     var greeting = function(world){      return "hello " + world +"!";    };    alert(greeting("world"));

<br /> var greeting = function(world){<br /> return "hello " + world +"!";<br /> };<br /> alert(greeting("world"));<br />

運行代碼

我們把它塞進更深一層的範圍,非bind函數。

     var wrap= function(fn){      return function(){        return fn.apply(null,arguments);      };    };

<br /> var wrap= function(fn){<br /> return function(){<br /> return fn.apply(null,arguments);<br /> };<br /> };<br /> var greeting = function(world){<br /> return "hello " + world +"!";<br /> };<br /> alert(greeting("world"));<br /> alert(wrap(greeting)("world"))</p><p>

運行代碼

但這隻是延遲了它的執行時間而已。上面函數中的null,也可以換成window。

     var wrap= function(fn){      return function(){        return fn.apply(window,arguments);      };    };

<br /> var wrap= function(fn){<br /> return function(){<br /> return fn.apply(window,arguments);<br /> };<br /> };<br /> var greeting = function(world){<br /> return "hello " + world +"!";<br /> };<br /> alert(greeting("world"));<br /> alert(wrap(greeting)("world"))</p><p>

運行代碼

因為總要人去調用函數的,null沒有此能力,就由window上。現在我們就是要在這個位置上做文章,把換成this。如果沒有進一步的改進,這裡的this還是window的替身。下面就開始複雜了,先分解一下寫法,降低閱讀難度,就像jQuery那樣把它掰成三部分:

     var wrapper= function(fn){//這裡改一下名。      var temp =  function(){        return fn.apply(this,arguments);      };      return temp;    };
     //fn為原函數    //temp為改裝了的函數    //wrapper為封裝工廠,只運作一次    //wrap為改裝了的函數的屬性,它的參數和wrapper一樣為函數,但能運行無數次,    //把原改裝了的函數內建為新增函數的內建函式。    var wrapper= function(fn){      var temp =  function(){        return fn.apply(this,arguments);      };      temp.wrap = function(callback){        var prev = fn;        fn = function(){          return callback.apply(prev,arguments);        };      };      return temp;    };

這樣就可以如下神奇效果:

<br /> var wrapper= function(fn){<br /> var temp = function(){<br /> return fn.apply(this,arguments);<br /> };<br /> temp.wrap = function(callback){<br /> var prev = fn;<br /> fn = function(){<br /> return callback.apply(prev,arguments);<br /> };<br /> };<br /> return temp;<br /> };<br /> var html = function(str){ //原函數數<br /> return "<p>"+str+"</p><p>";<br /> }</p><p> alert(html("段落"));<br /> var p = wrapper(html);//第一次封裝<br /> alert(p("段落"))</p><p> p.wrap(function(str){//第二次封裝<br /> return ""+this(str)+"<p>";<br /> });</p><p> alert(p("段落"));</p><p> p.wrap(function(str){//第三次封裝<br /> return ""+this(str)+"";<br /> });<br /> alert(p("段落"));<br />

運行代碼

可以看出,this總是為原來的同名函數(p),也就是說,我們可以稱之為父方法,這樣也super關鍵字或者相關的代替品也不用了,輕鬆調用原來覆蓋了父類的方法。因此jQuery同學單是用它來處理DOM真是大材小用。Prototype同學就做得不錯了,不過代碼寫得比較艱澀:

   wrap: function(wrapper) {    var __method = this;    return function() {      return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));    }  },

它的方法鏈設計:

     for (var i = 0, length = properties.length; i < length; i++) {      var property = properties[i], value = source[property];      if (ancestor && Object.isFunction(value) &&          value.argumentNames().first() == "$super") {        var method = value;        value = (function(m) {          return function() { return ancestor[m].apply(this, arguments) };        })(property).wrap(method);        value.valueOf = method.valueOf.bind(method);        value.toString = method.toString.bind(method);      }      this.prototype[property] = value;    }

相關文檔:http://www.prototypejs.org/learn/class-inheritance

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.