修改
感谢Shaun Scovill在下面使用lodash的优雅答案
// create instance and inject server object - inside of the ChartService below
var chart = new Chart(serverChartObject);
// replace Chart factory with the following code to streamline the creation of the object constructor using the server object as well as hydrate it!
Chart.$inject = [];
function Chart() {
return function(serverChartObject) {
var keys = ['app_id', 'article_id', 'section_id', 'data', 'headline', 'legend', 'source', 'source_url', 'subtitle', 'summary', 'width', 'height'];
_.assign(this, _.pick(serverChartObject, keys));
};
}
DEV工具
Angular:1.4.7 RequireJS:2.12 Laravel 5.1.x Lodash 3.10.1
问题:
我想知道是否有更好的方法来自动保湿和保护AngularJS / JavaScript对象实例。
之情况
在下面的示例中,我从Laravel 5.1中获取了一组图表对象,但可以是任何后端,因为它返回一个json对象。我有一个服务模块ChartService,然后将数据解析为JavaScript Chart对象。
目的
使用最少量的代码我希望实现以下目标:
第一种方法
我使用Object.defineProperty(Chart, 'app_id', { value: 1 });
和上面提到的受保护方法但是如果我然后执行chart.app_id = 3
它会覆盖app_id与Object.freeze(chart)
,以阻止所有属性被覆盖或修改。
当前的方法
注意:为了简洁起见,删除了很多代码,如果我删除了太多的上下文以便理解,请为此道歉。
define([
'angular',
'lodash'
], function(angular, _) {
'use strict';
ChartService.$inject = ['$http', '$q', '$sce', '$rootScope', 'api', 'Chart'];
function ChartService($http, $q, $sce, $rootScope, api, Chart) {
var chartService = {
charts: [],
// NOTE : call parse from external source
parseCharts: function(items) {
var self = this,
chart,
articleId = null,
sectionId = null;
// NOTE : items are a collection of chart objects from Laravel
if (angular.isDefined(items) && Object.keys(items).length > 0) {
// NOTE: c = chart server object
_.each(items, function(c,k) {
// factory Chart instance
chart = new Chart();
// NOTE : hydrate chart instance with c (server chart object data)
chart = hydrateInstance(c, chart);
// freeze object
Object.freeze(chart);
})
}
}
};
function hydrateInstance(obj, instance) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop) && instance.hasOwnProperty(prop)) {
instance[prop] = obj[prop]
}
}
return instance;
}
return chartService;
}
Chart.$inject = [];
function Chart() {
/**
* Constructor, with class name
*/
function Chart(app_id, article_id, section_id, data, headline, legend, source, source_url, subtitle, summary, width, height) {
var self = this;
self.app_id = app_id;
self.article_id = article_id;
self.section_id = section_id;
self.data = data;
self.headline = headline;
self.legend = legend;
self.source = source;
self.source_url = source_url;
self.subtitle = subtitle;
self.summary = summary;
self.width = width;
self.height = height;
}
// removed rest of object / prototype properties for brevity sake
return Chart;
}
return angular.module('cmo.content.charts', [
])
// remove config for brevity
.factory('Chart', Chart)
.service('ChartService', ChartService);
});