0

我正在通過ng-newsletter的2048遊戲教程,我被困在未定義的gridservice方法上。angularjs服務中的方法未定義

下面是代碼模塊注入網格模塊及其設置gridservice

angular.module('Game', ['Grid']) 
    .service('GameManager', ['GridService', function(GridService) { 

     // create a new game 
     this.newGame = function() { 
      GridService.buildEmptyGameBoard(); 
      GridService.buildStartingPosition(); 
      this.reinit(); 
     }; 
    }]); 

這是我的網格模塊和Gridserivce與方法的角度引用爲被未定義沿着:

angular.module('Grid', []) 

      /** 
      * GridService handles all the conditions of the board 
      */ 
      .service('GridService', ['TileModel', function(TileModel) { 

       return { 
        buildEmptyGameBoard: buildEmptyGameBoard 
       } 

       this.startingTileNumber = 2; 



       // grid array acts the as the board and remains static 
       this.grid = []; 

       // tiles array acts the pieces on the board and will be dynamic 
       this.tiles = []; 
       this.tiles.push(new TileModel({x: 1, y: 1}, 2)); 
       this.tiles.push(new TileModel({x: 1, y: 2}, 2)); 

       // Size of the board 
       this.size = 4; 


       //this.buildEmptyGameBoard = function() { 
       function buildEmptyGameBoard() { 
        var self = this; 

        // Initialize our grid 
        for(var x = 0; x < this.size * this.size; x++) { 
         this.grid[x] = null; 
        } 

        // Initialize our tile array 
        // with a bunch of null objects 
        this.forEach(function(x,y) { 
         self.setCellAt({x:x, y:y}, null); 
        }); 

       } 


     // Run a method for each element in the tiles array 
       this.forEach = function(cb) { 
        var totalSize = this.size * this.size; 
        for(var i = 0; i < totalSize; i++) { 
         var pos = this._positionToCoordinates(i); 
         cb(pos.x, pos.y, this.tiles[i]); 
        } 
       }; 

    // Convert i to x,y 
      // cell position from single dimensional array 
      // converts to x and y coords for pos on game board 
      this._positionToCoordinates = function(i) { 
       var x = i % service.size; 
        y = (i - x)/service.size; 
       return { 
        x: x, 
        y: y 
       }; 
      }; 


}]) 

    /** 
    * TileModel Factory to define values for our tile directive css positions 
    */ 
    .factory('TileModel', function() { 
     var Tile = function(pos, val) { 
      this.x = pos.x; 
      this.y = pos.y; 
      this.value = val || 2; 
     }; 

     return Tile; 
    }); 

Curretnly我我得到這個:錯誤:this.forEach不是一個函數

我已經能夠解決在這個應用程序中的一些其他錯誤。所有的錯誤都是關於我的gridService中的方法沒有被定義或不是一個函數。似乎是我的GridService中根本錯誤或缺失的東西,我無法看到。

注:這兩個文件被調用,在我的index.html文件

回答

0

正確加載你有幾個錯誤的位置 - 一個直接的一個,另一個你,只要你解決第一個發現。

  1. '這'並不總是你期望的Javascript。調用一個函數不會改變上下文(你可以使用諸如call/apply/bind之類的東西),所以看看你的'this'指針。用標準的JS技巧你會有更好的結果:

    var self = this; 
    

    然後用'self'代替'this'到處。

  2. this.forEach不存在,因爲您在服務本身(this)或調用者的上下文(取決於您如何調用服務)上調用它。你的意思是this.tiles.forEach()

  3. 您致電GridService.buildStartingPosition();但您尚未定義它。一旦你解決了forEach,這會在這裏拋出異常。

+0

非常感謝指針在這裏我忘了自我=這項工作:所以你的代碼更改。這解決了我的問題 – appthat 2014-09-19 21:02:28

1
  1. 你有一個早期return語句。這一點,在函數的開頭:

    return { 
        buildEmptyGameBoard: buildEmptyGameBoard 
    } 
    

    意味着下面的語句將不會被執行:

    this.startingTileNumber = 2; 
    ...etc... 
    

    的Javascript運行在第一遍的聲明(即buildEmptyGameBoard宣佈和將被定義),但不是該陳述(即this.forEach = function(cb) {}將等待第二次通過)。但是在第二遍時,立即執行返回並且沒有別的運行。

    所以**把return放在函數的末尾。

  2. 服務不是控制器,它不是用new實例化的。您的服務使用1種方法返回對象buildEmptyGameBoardthis.forEach = function(cb) {}會將foreach函數附加到某個未知對象,肯定是而不是您對象return。各地

    function buildEmptyGameBoard() { ... } 
    function foreach(cb) { ... } 
    ...etc... 
    
    return { 
        buildEmptyGameBoard: buildEmptyGameBoard, 
        foreach: foreach, 
        ...etc... 
    }; 
    
+0

非常感謝,這對理解它的流程非常有幫助。我結束了使用var self =這個工作,所以我不必將所有我的方法附加到return語句 – appthat 2014-09-19 21:00:25