【问题标题】:Angular / Java Script - reference "class" properties before object is instantiated?Angular / Java Script - 在实例化对象之前引用“类”属性?
【发布时间】:2014-04-21 00:09:15
【问题描述】:

我有 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();
}

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

【问题讨论】:

    标签: javascript angularjs


    【解决方案1】:

    在 Angular 中,工厂应该返回一个对象。你返回一个函数。

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

    示例(未经测试):

    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();
    }]);
    

    【讨论】:

    • 我已经可以在控制器中获得一个网格实例。我的问题是我无法在游戏工厂中引用网格的实例。或者换一种说法,我需要能够引用游戏工厂中的类属性/方法,然后我可以在控制器中实例化两者(网格,游戏)并将网格实例传递给游戏实例。
    • 我用你的代码编辑了我的答案。我试图按照您的意愿进行操作,但我不确定。它是未经测试的。您的myApp 中将存在多少个GridGame 实例?从角度 factory 返回函数并不是它的本意,但由于在 JavaScript 中函数是第一类对象,它会起作用。 factory 这个名字有点误导人。
    【解决方案2】:

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

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

    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();
    }
    

    但是,我仍然希望能够将网格“类”传递到游戏工厂。但这不起作用,因为在网格实例化之前 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;
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-02
      • 2013-03-06
      • 2018-04-28
      • 1970-01-01
      • 1970-01-01
      • 2021-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多