简体   繁体   English

使用Object.create()进行角度服务继承

[英]Angular service inheritance using Object.create()

I'm trying to use inheritance in angular services, as explained here: http://blog.mgechev.com/2013/12/18/inheritance-services-controllers-in-angularjs/ , I want to use the "Inject the parent" method. 我正在尝试在角度服务中使用继承,如此处所述: http : //blog.mgechev.com/2013/12/18/inheritance-services-controllers-in-angularjs/ ,我想使用“注入父”方法。

However, it doesn't seem to work, and I can't see why. 但是,它似乎不起作用,我也看不出原因。

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

The result is that ThreadModel.getTableName() returns "posts" in stead of "threads". 结果是ThreadModel.getTableName()返回“ posts”而不是“ threads”。

I tried both Object.create(...) and angular.copy(BaseModel, this) , but both don't seem to make a deep copy. 我尝试了Object.create(...)angular.copy(BaseModel, this) ,但似乎都没有进行深拷贝。

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

What am I doing wrong here? 我在这里做错了什么?

The problem is that with this set up using Object.create you produce services with the tableName variable stored in the same common closure (BaseModel function). 问题在于,使用Object.create进行此设置时,您将使用tableName变量存储在相同的通用闭包(BaseModel函数)中来产生服务。 To put it simply, init method modifies the same local tableName variable. 简单地说, init方法修改了相同的本地tableName变量。

You could fix it like this: 您可以这样解决:

function BaseModel() {

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

  return service;

  function getTableName() {
    return this._tableName;
  }

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

Note, that getTableName and init methods now work with instance property this._tableName which is not shared between TableModel and PostModel instances. 请注意, getTableNameinit方法现在与实例属性this._tableName ,该属性在TableModelPostModel实例之间不共享。

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

@dfsq has already well explained and given a simple solution. @dfsq已经很好地解释了,并给出了一个简单的解决方案。 I put here what I am thinking about this issue. 我把关于这个问题的想法放在这里。

In your code Object.create(BaseModel) creates a new object whose prototype is a returned value of BaseModel function. 在您的代码中, Object.create(BaseModel)创建一个新对象,其原型是BaseModel函数的返回值。 In those children models init method modifies tableName within the local scope of BaseModel function. 在那些子模型中, init方法会在BaseModel函数的本地范围内修改tableName If you replace tableName with this.tableName , that will work as you expected: both init and getTableName methods will actually modify/call tableName property of service variable within ThreadModel or PostModel functions. 如果用this.tableName替换tableName ,它将按预期工作: initgetTableName方法实际上将在ThreadModelPostModel函数中修改/调用service变量的tableName属性。 But it looks complicated. 但是看起来很复杂。

In your case I would like suggest the following service inheritance solution, which would be clearer. 对于您的情况,我想提出以下服务继承解决方案,这将更加清楚。 There is an other post that can be interesting. 还有另一篇可能很有趣的文章。

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/ JSFiddle: http : //jsfiddle.net/Lvc0u55v/3993/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM