2016-05-14 62 views
1

我試圖在角度服務中使用繼承,如下所述: http://blog.mgechev.com/2013/12/18/inheritance-services-controllers-in-angularjs/,我想使用「注入父項」方法。使用Object.create的角度服務繼承()

但是,它似乎沒有工作,我不明白爲什麼。

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/

我在做什麼錯在這裏?

+0

嘗試將控制器工廠後,在頂部 –

+0

您初始化這是因爲'的init()'總是BaseModel'的'原型改變'tableName'。 – micmia

回答

2

問題是,使用此設置使用Object.create您可以通過存儲在同一個常用閉包(BaseModel函數)中的tableName變量生成服務。簡單地說,init方法修改相同本地tableName變量。

您可以修復它是這樣的:

function BaseModel() { 

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

    return service; 

    function getTableName() { 
    return this._tableName; 
    } 

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

注意,那getTableNameinit方法現在未TableModelPostModel實例之間共享實例屬性this._tableName工作。

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

0

@dfsq已經很好地解釋並給予一個簡單的解決方案。我在這裏把我對這個問題的看法放在這裏。

在您的代碼中Object.create(BaseModel)創建一個新對象,其原型返回值爲BaseModel函數。在那些兒童模型init方法中修改tableNameBaseModel函數的本地範圍內。如果您有this.tableName替換tableName,將工作如你預期:既有initgetTableName方法實際上將修改/內ThreadModelPostModel函數調用service變量的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/