Angular / Javascript - 在实例化对象之前引用“class”属性?

时间:2014-04-19 14:44:22

标签: javascript angularjs

我有一个c#背景,我开始探索Angular JS。我将我的工厂类/对象基于这篇文章:https://medium.com/opinionated-angularjs/2e6a067c73bc

所以我有2个工厂类,但我想在另一个工厂内引用一个工厂的实例。但是,由于java脚本不是类型化语言,因此在“编译”时,其他工厂内的某个工厂的属性和方法不可用。

检查这个小提琴:http://jsfiddle.net/Frinkahedron/PxdSP/1337/     var myApp = angular.module('myApp',[]);

myApp.factory('grid', function () {

// Constructor, with parameters
function grid(sizeX, sizeY, gridName) {
    //public properties
    this.cells = new Array();
    this.name = gridName;

    //load cells
    var numCells = sizeX * sizeY;
    for (var i = 0; i < numCells; i++) {
        this.cells.push(i);
    }
}

//Return the constructor function
return grid;
});

myApp.factory('game', ['grid', function (_grid_) {
//private reference for the grid factory
var grid = _grid_;

function game(){
    //do some setup with grid reference
    this.gridName = "Grid : " + grid.gridName;
};

game.prototype.isWinner = function () {
    //iterate cells to see if game has been won  

    //this loop doesn't cause "compile" errors
    for (var c in grid.cells){
        //do something with each cell in the grid
    }

    //this loop doesn't work due to grid.cells.length 
    //because there is no length property of undefined 
    //uncomment to see it blow up
    //for(var i=0; i< grid.cells.length;i++){}
    return true;
};

return game;
}]);


function MyCtrl($scope, grid, game) {
var g = new grid(3, 3, "Test Grid");

$scope.myLength = g.cells.length;
$scope.myGridName = g.name;
//how to pass the grid reference to the game?
//if i pass the grid in the constructor of the game, 
//it still doesn't work because javascript doesn't have types
//and the grid.cells (and other grid property references) are
//problematic
var a = new game();
$scope.myGameName = a.gridName;
$scope.myWinner = a.isWinner();
}

Grid工厂按预期工作,但我无法弄清楚如何在Game工厂中引用网格实例。我已经尝试将网格“对象”传递给Game构造函数,但由于java脚本不是类型化语言,因此游戏工厂中的网格属性/方法未定义。

2 个答案:

答案 0 :(得分:0)

在角度中,工厂应该返回一个物体。你返回一个函数。

您似乎希望提供商能够配置您的网格而不是工厂。

示例(未经测试):

myApp.provider('grid', function () {
  'use strict';

  var x, y, name;

  var Grid = function () {
    // Grid instance has access to x, y and name
  };

  this.setX = function (newx) {
    x = newx;
  };

  this.sety = function (newy) {
    y = newy;
  };

  this.setname = function (n) {
    name = n;
  };

  this.$get = function () {
    return new Grid();
  };

});

使用此提供商,您可以:

myApp.configure(['gridProvider',
  function (gridProvider) {
    'use strict';

    gridProvider.setx(100);
    gridProvider.sety(100);
    gridProvider.setname('name');

  }
]);

myApp.controller('myCtrl',
 ['grid', '$scope',
  function (grid, $scope) {
    'use strict';

     // grid is now an instance of 'Grid'
  }
 ]);

修改

myApp.factory('Grid', function () {
  'use strict';

  function Grid(sizeX, sizeY, gridName) {
    var
    i, numCells = sizeX * sizeY;

    this.cells = [];
    this.name = gridName;

    for (i = 0; i < numCells; i++) {
      this.cells.push(i);
    }
  }

  return Grid;
});

myApp.factory('Game', function () {
  'use strict';

   function Game(grid){
     this.gridName = "Grid : " + grid.name;
   };

   Game.prototype = {
     isWinner: function () {
       var i, l;
       for (i = 0, l = grid.cells.length; i < l; i++) {
         //do something with each cell in the grid
       }
       return true;
     }
   };

   return Game;
});


myApp.controller('myCtrl', ['$scope', 'Grid', 'Game',
function ($scope, Grid, Game) {
  'use strict';
  var
  grid = new Grid(3, 3, "Test Grid"),
  game = new Game(grid);

  $scope.myLength = grid.cells.length;
  $scope.myGridName = grid.name;
  $scope.myGameName = game.gridName;
  $scope.myWinner = game.isWinner();
}]);

答案 1 :(得分:0)

我找到了一个解决方案,但这并不理想:http://jsfiddle.net/Frinkahedron/LJqz7/2/

我现在将Grid的参数传递给Game函数并在Grid中创建Game。

myApp.factory('game', ['grid', function (_grid_) {
    var grid = _grid_;

    //TODO: instead of passing the parameters for the grid
    //into the game, I would prefer to pass the grid "class"
    //But that doesn't seem possible since java script 
    //doesn't recognize the "class" properties until the 
    //object is instantiated
    function game(sizeX, sizeY, gridName){
        this.gameGrid = new grid(3, 3, "Test Grid");
        this.gridName = "Grid - " + this.gameGrid.name;
    };

    game.prototype.isWinner = function () {
        for(var i=0; i< this.gameGrid.cells.length;i++){
            //set to false if necessary
        }
        return true;
    };

    return game;
}]);

我现在可以正确引用Grid的属性。

function MyCtrl($scope, grid, game) {
    var aGame = new game(3, 3, "Test Grid");

    $scope.myGridName = aGame.gameGrid.name;
    $scope.myLength = aGame.gameGrid.cells.length;
    $scope.myGameName = aGame.gridName;
    $scope.myWinner = aGame.isWinner();
}

然而,我仍然希望能够通过网格&#34; class&#34;进入游戏工厂。但这不起作用,因为grid.cells未定义,直到网格被实例化。这可以在Java Script / Angular中克服吗?

function game(grid){
    this.gridName = "Grid - " + grid.name;
};

game.prototype.isWinner = function () {
    for(var i=0; i< grid.cells.length;i++)
        //set to false if necessary
    }
    return true;
};