2011-06-17 68 views
0

我有兩個幾乎完全相同的以js編寫的類。我想讓其中一個擴展另一個,以減少代碼。我是JavaScript的新手,我需要一點幫助才能做到這一點。 我在這裏發佈課程。任何人都可以幫忙嗎?在javascript中擴展一個類

//============================================================================================================================================ 
     //Class1================================================================================================================================== 
     //============================================================================================================================================ 
     function Class1(config){ 
      var targetObj; 
      var copycanvas = null; 
      var copy = null; 
      var outputcanvas = null; 
      var draw = null; 
      var direction = config.direction || "lr"; 

      var TILE_WIDTH = config.tileWidth || 100; 
      var TILE_HEIGHT = config.tileHeight || 100; 

      var SOURCERECT = {x:0, y:0, width:0, height:0}; 
      var interval; 
      var tiles2 = []; 
      var cols = 0; 
      var rows = 0; 

      createTiles = function(){ 
       tiles = [];  
       tiles2 = [];   

       var y=0; 
       while(y < SOURCERECT.height){ 
        var x=0; 
        cols = 0; 
        while(x < SOURCERECT.width){        
         cols++; 
         x += TILE_WIDTH; 
        } 
        rows++; 
        y += TILE_HEIGHT; 
       } 

       var i, j; 
       if (direction == "tl"){ 
        for (i = 0; i < rows; i++) 
         for (j = 0; j < cols; j++){ 
          x = j * TILE_WIDTH; 
          y = i * TILE_HEIGHT; 
          var tile = new Tile(); 
          tile.imageX = x; 
          tile.imageY = y; 
          tiles2.push(tile); 
         } 
       } 
       arrangeSquares(); 
      }; 

      arrangeSquares = function(){ 
       var i, j, k; 
       var M, N; 

       M = rows; 
       N = cols; 
       i = j = 0; 
       var cnt = 0; 
       for (i = 0; i < N + M - 1; i++) 
        for (j = 0; j <= i; j++) 
         if (j < M && (i - j) < N){ 
          tiles.push(tiles2[j * N + (i - j)]); 
         } 
      } 

      processFrame = function(){ 
       copycanvas.width = outputcanvas.width = targetObj.width; 
       copycanvas.height = outputcanvas.height = targetObj.height; 
       copy.drawImage(targetObj, 0, 0, targetObj.width, targetObj.height); 

       for(var i=0; i < tiles.length; i++) { 
        var tile = tiles[i]; 

        tile.alpha += 0.05; 

        var TH = Math.max(0, Math.min(TILE_HEIGHT, targetObj.height - tile.imageY)); 
        var TW = Math.max(0, Math.min(TILE_WIDTH, targetObj.width - tile.imageX));     

        draw.save(); 
        draw.translate(tile.imageX, tile.imageY); 
        draw.globalAlpha = Math.max(0, tile.alpha);   

        draw.drawImage(copycanvas, tile.imageX, tile.imageY, TW, TH, 0, 0, TW, TH);   
        draw.restore(); 
       } 

       var ok = true; 
       for (i = 0; i < tiles.length; i++) { 
        if (tiles[i].alpha < 1) { 
         ok = false; 
         break; 
        } 
       } 
       if (ok) 
       { 
        clearInterval(interval); 
        showComplete(); 

       } 
      }; 

      function showComplete() { 
       $target.trigger("showComplete"); 

       $img.show(); 
       $(copycanvas).remove(); 
       $(outputcanvas).remove(); 
       if ($hideTarget) 
        $hideTarget.hide(); 
      }; 

      this.hide = function(target) { 

      }; 
      var $target = null; 
      var $img = null; 
      var $hideTarget = null; 
      this.show = function(target, hideTarget){ 
       $target = $("#" + target).show(); 

       align($target); 

       if (hideTarget != undefined) { 
        $target.before($hideTarget = $("#" + hideTarget).show()); 
        align($hideTarget); 
       } 

       $img = $("#" + target + " > img").filter(":first").hide(); 

       $("<canvas/>").attr("id", "sourcecopy") 
           .css("position", "absolute") 
           .appendTo($target) 
           .hide(); 
       copycanvas = document.getElementById("sourcecopy"); 
       copy = copycanvas.getContext('2d'); 

       $("<canvas/>").attr("id", "output") 
           .css("position", "absolute") 
           .appendTo($target); 
       outputcanvas = document.getElementById("output"); 
       draw = outputcanvas.getContext('2d'); 

       targetObj = document.getElementById($img.attr("id")); 

       clearInterval(interval); 

       SOURCERECT = {x:0, y:0, width: targetObj.width, height: targetObj.height}; 
       createTiles(); 

       for(var i=0; i<tiles.length; i++){ 
        var tile = tiles[i]; 
        tile.alpha = 0 - (i * (2/tiles.length)); 
       } 

       var intervalDelay = (config.duration * 1000)/(40 + rows + cols); 
       interval = setInterval(function() { processFrame(); }, intervalDelay); 
      }; 

      function Tile(){ 
       this.alpha = 1; 
       this.imageX = 0; 
       this.imageY = 0; 
      }; 
     }; 

     //============================================================================================================================================ 
     //Class2=================================================================================================================================== 
     //============================================================================================================================================ 
     function Class2(config){ 
      var targetObj; 
      var copycanvas = null; 
      var copy = null; 
      var outputcanvas = null; 
      var draw = null; 
      var direction = config.direction || "lr"; 

      var TILE_WIDTH = config.barWidth || 50; 
      var TILE_HEIGHT = 100; 

      var SOURCERECT = {x:0, y:0, width:0, height:0}; 
      var interval; 
      var tiles = []; 

      createTiles = function(){ 
       tiles = [];    
       var y=0; 
       while(y < SOURCERECT.height){ 
        var x=0; 
        while(x < SOURCERECT.width){ 
         var tile = new Tile(); 
         tile.imageX = x; 
         tile.imageY = y; 
         tiles.push(tile); 
         x += TILE_WIDTH; 
        } 
        y += TILE_HEIGHT; 
       } 
      }; 

      processFrame = function(){ 
       copycanvas.width = outputcanvas.width = targetObj.width; 
       copycanvas.height = outputcanvas.height = targetObj.height; 
       copy.drawImage(targetObj, 0, 0, targetObj.width, targetObj.height); 

       for(var i=0; i < tiles.length; i++) { 
        var tile = tiles[i]; 

        tile.alpha += 0.05; 

        var TH = Math.max(0, Math.min(TILE_HEIGHT, targetObj.height - tile.imageY)); 
        var TW = Math.max(0, Math.min(TILE_WIDTH, targetObj.width - tile.imageX));     

        draw.save(); 
        draw.translate(tile.imageX, tile.imageY); 
        draw.globalAlpha = Math.max(0, tile.alpha);   
        draw.drawImage(copycanvas, tile.imageX, tile.imageY, TW, TH, 0, 0, TW, TH); 
        draw.restore(); 
       } 

       var ok = true; 
       for (i = 0; i < tiles.length; i++) { 
        if (tiles[i].alpha < 1) { 
         ok = false; 
         break; 
        } 
       } 
       if (ok) 
       { 
        clearInterval(interval); 
        showComplete(); 
       } 

      }; 

      function showComplete() { 
       $target.trigger("showComplete"); 

       $img.show(); 
       $(copycanvas).remove(); 
       $(outputcanvas).remove(); 
       if ($hideTarget) 
        $hideTarget.hide(); 
      }; 

      this.hide = function(target) { 

      }; 
      var $target = null; 
      var $img = null; 
      var $hideTarget = null; 
      this.show = function(target, hideTarget){ 
       $target = $("#" + target).show(); 

       align($target); 

       if (hideTarget != undefined) { 
        $target.before($hideTarget = $("#" + hideTarget).show()); 
        align($hideTarget); 
       } 
       $img = $("#" + target + " > img").filter(":first").hide(); 

       $("<canvas/>").attr("id", "sourcecopy") 
           .css("position", "absolute") 
           .appendTo($target) 
           .hide(); 
       copycanvas = document.getElementById("sourcecopy"); 
       copy = copycanvas.getContext('2d'); 

       $("<canvas/>").attr("id", "output") 
           .css("position", "absolute") 
           .appendTo($target); 
       outputcanvas = document.getElementById("output"); 
       draw = outputcanvas.getContext('2d'); 

       targetObj = document.getElementById($img.attr("id")); 

       clearInterval(interval); 

       if (direction == "tb" || direction == "bt") 
       { 
        TILE_WIDTH = targetObj.width; 
        TILE_HEIGHT = config.barWidth; 
       } 
       else 
       { 
        TILE_WIDTH = config.barWidth; 
        TILE_HEIGHT = targetObj.height;   
       } 

       SOURCERECT = {x:0, y:0, width: targetObj.width, height: targetObj.height}; 
       createTiles(); 

       if (direction == "lr" || direction == "tb") 
       { 
        for(var i=0; i<tiles.length; i++){ 
         var tile = tiles[i]; 
         tile.alpha = 0 - (i * (1/tiles.length)); 
        } 
       } 
       else 
       { 
        for(var i=tiles.length - 1; i >= 0 ; i--){ 
         var tile = tiles[i]; 
         tile.alpha = 0 - ((tiles.length - i - 1) * (2/tiles.length)); 
        } 
       } 

       var intervalDelay = (config.duration * 1000)/(40 + tiles.length); 
       interval = setInterval(function() { processFrame(); }, intervalDelay); 
      }; 

      function Tile(){ 
       this.alpha = 1; 
       this.imageX = 0; 
       this.imageY = 0; 
      }; 
     }; 
+0

方式很多代碼 – Ibu 2011-06-17 06:55:09

+0

代碼並不重要。我已經完全發佈了它,以查看類的結構。 – gabitzish 2011-06-17 07:48:43

回答

1

你有一對夫婦的選擇。您可以將通用功能隔離爲第三個對象,即Class1Class2共享(聚合),或者實際上可以創建對象的層次結構(繼承)。我會在這裏談論繼承。

JavaScript沒有類,它是一個典型的語言。對象實例由原型對象「支持」。如果你向實例請求一個它沒有的屬性(並且函數作爲屬性附加到對象上),那麼JavaScript解釋器會檢查該對象後面的原型,以查看它是否具有該屬性(如果不是,則返回原型對象等等)。這是原型繼承的工作原理。

JavaScript是一種不尋常的原型語言,直到最近,還沒有辦法創建一個對象並直接分配其原型;你必須通過構造函數來完成它。如果您使用的是基於類的術語,那麼無論如何,您可能會更熟悉構造函數。 :-)

這裏有一個基本的繼承設置(這不是我怎麼會真正做到這一點,更多的是下圖):

// Constructs an Vehicle instance 
function Vehicle(owner) { 
    this.owner = owner; 
} 

// Who's this Vehicle's owner? 
Vehicle.prototype.getOwner = function() { 
    return this.owner; 
}; 

// Constructs a Car instance 
function Car(owner) { 
    // Call super's initialization 
    Vehicle.call(this, owner); 

    // Our init 
    this.wheels = 4; 
} 

// Assign the object that will "back" all Car instances, 
// then fix up the `constructor` property on it (otherwise 
// `instanceof` breaks). 
Car.prototype = new Vehicle(); 
Car.prototype.constructor = Car; 

// A function that drives the car 
Car.prototype.drive = function() { 
}; 

現在我們可以使用Car並獲得Vehicle特點:

var c = new Car("T.J."); 
alert(c.getOwner()); // "T.J.", retrived via Vehicle.prototype.getOwner 

上面有點尷尬,它遇到了一些棘手的問題。它也有問題,大多數函數是匿名的,我不喜歡匿名函數(函數名稱help your tools help you)。如果你還有一個函數的副本(如「超級調用」  —不是一種不常見的層次結構操作),那麼調用你的原型的函數版本也很尷尬。出於這個原因,您會看到許多用於構建層次結構的「框架」,通常使用基於類的術語。下面是其中一些人的名單:

  • ProotypeClass功能,通用的JavaScript庫
  • 院長愛德華茲的base2
  • 約翰Resig的Simple JavaScript Inheritance(Resig的是誰的人創造的jQuery)
  • 呃,恩,mine   —據我所知,約三人正在使用。我這樣做是因爲我在做出上述每個決定時都有問題。我將更新它以不使用類術語(並且實際上將它作爲一個小型庫,而不僅僅是一篇博客文章發佈),因爲它們中沒有一個向JavaScript添加類,並且表現得好像錯過了JavaScript原型模型的觀點。

在這四個中,我推薦Resig's或我的。 Resig使用函數反編譯功能(在函數實例上調用toString  ,它從未標準化,在某些平臺上不起作用),但即使函數反編譯不起作用,它也可以工作,在這種情況下效率稍低。然而,在跳過任何一個之前,我鼓勵你看看道格拉斯克羅克福德(Douglas Crockford)所倡導的true prototypical approach(JSON的名聲,也是YUI的一個大假髮)。克羅克福德在latest version of ECMAScript上投入了大量的意見,他的一些想法(最明顯的是Object.create)現在已經成爲最新標準的一部分,並正在進入瀏覽器。使用Object.create,您可以直接將原型分配給對象,而不具有構造函數。

對於需要繼承的地方,我更喜歡構造函數(用我的語法幫助),但是克羅克福德的方法是有效的,有用的,並且越來越受歡迎。這是你應該瞭解和理解的東西,然後選擇何時或是否使用。

2

嘗試聲明這樣的類。

var theClass = function theClass() { 
    .... 

擴展這個類可以使用原型法:

theClass.prototype.newMethodName = function() { 
    ....