【问题标题】:Angular service inheritance using Object.create()使用 Object.create() 的角度服务继承
【发布时间】:2016-05-14 08:50:48
【问题描述】:

我正在尝试在角度服务中使用继承,如下所述: http://blog.mgechev.com/2013/12/18/inheritance-services-controllers-in-angularjs/,我想使用“注入父级”的方法。

但是,它似乎不起作用,我不明白为什么。

var myApp = angular.module('myApp',[]);

angular.module('myApp').controller('MyCtrl', MyCtrl);
angular.module('myApp').factory('BaseModel', BaseModel);
angular.module('myApp').factory('ThreadModel', ThreadModel);
angular.module('myApp').factory('PostModel', PostModel);

function MyCtrl($scope, ThreadModel, PostModel) {
  $scope.tableNameForThreads = ThreadModel.getTableName();
  $scope.tableNameForPosts = PostModel.getTableName();
}

function BaseModel() {
  var tableName = "";

  var service = {
    init: init,
    getTableName: getTableName
  };

  return service;

  function getTableName() {
    return tableName;
  }

  function init(theTableName) {
    tableName = theTableName;
  }
}

function ThreadModel(BaseModel) {
  var service = Object.create(BaseModel);
  service.init("threads");
  return service;
}

function PostModel(BaseModel) {
  var service = Object.create(BaseModel);
  service.init("posts");
  return service;
}

结果是 ThreadModel.getTableName() 返回“posts”而不是“threads”。

Object.create(...)angular.copy(BaseModel, this) 我都试过了,但似乎都没有做深拷贝。

JSFIDDLE:http://jsfiddle.net/dirkpostma/Lvc0u55v/3989/

我在这里做错了什么?

【问题讨论】:

  • 尝试将控制器放在工厂之后,在初始化时放在顶部
  • 这是因为init()总是在BaseModel的原型中改变tableName

标签: javascript angularjs oop inheritance factory


【解决方案1】:

问题在于,通过使用Object.create 进行此设置,您可以使用存储在同一个公共闭包(BaseModel 函数)中的tableName 变量来生成服务。简单来说,init 方法修改了 same 本地的tableName 变量。

你可以这样修复它:

function BaseModel() {

  var service = {
    init: init,
    getTableName: getTableName
  };

  return service;

  function getTableName() {
    return this._tableName;
  }

  function init(theTableName) {
    this._tableName = theTableName;
  }
}

请注意,getTableNameinit 方法现在可以与实例属性 this._tableName 一起使用,该属性不在 TableModelPostModel 实例之间共享。

演示: http://jsfiddle.net/Lvc0u55v/3991/

【讨论】:

    【解决方案2】:

    @dfsq 已经很好地解释并给出了一个简单的解决方案。我把我对这个问题的想法写在这里。

    在您的代码中Object.create(BaseModel) 创建一个新对象,其原型是BaseModel 函数的返回值。在这些子模型中,init 方法在 BaseModel 函数的本地范围内修改 tableName。如果将tableName 替换为this.tableName,这将按预期工作:initgetTableName 方法实际上将修改/调用service 变量在ThreadModelPostModel 函数中的tableName 属性.但是看起来很复杂。

    在您的情况下,我想建议以下服务继承解决方案,这会更清晰。 an other post 可能很有趣。

    var myApp = angular.module('myApp', []);
    
    angular.module('myApp').controller('MyCtrl', MyCtrl);
    angular.module('myApp').service('BaseModel', BaseModel);
    angular.module('myApp').service('ThreadModel', ['BaseModel', ThreadModel]);
    angular.module('myApp').service('PostModel', ['BaseModel', PostModel]);
    
    function MyCtrl($scope, ThreadModel, PostModel) {
      $scope.tableNameForThreads = ThreadModel.getTableName();
      $scope.tableNameForPosts = PostModel.getTableName();
    }
    
    function BaseModel() {
      this.tableName = "";
    
      this.getTableName = function() {
        return this.tableName;
      }
    
      this.init = function(theTableName) {
        this.tableName = theTableName;
      }
    }
    
    function ThreadModel(BaseModel) {
      angular.extend(ThreadModel.prototype, BaseModel);
      this.tableName = "threads";
    }
    
    function PostModel(BaseModel) {
      angular.extend(PostModel.prototype, BaseModel);
      this.tableName = "posts";
    }
    

    JSFiddle:http://jsfiddle.net/Lvc0u55v/3993/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 2016-02-15
      • 2015-03-20
      • 2016-10-02
      • 2023-03-22
      相关资源
      最近更新 更多