Boris Charpentier 已经给出了很好的答案。我可以添加一些示例代码:
一个可以通过原始 JSON 对象初始化自身的构造函数:
function Workout(workoutJson) {
if (workoutJson) {
this.duration = workoutJson.duration;
... // or copy all properties in a for-loop
}
}
var fn = Workout.prototype;
// extend the prototype with some functions
fn.getSomeData = function () {
return this.onePart + ' ' + this.anotherPart;
};
// another smart solution: get properties (modern browser necessary)
Object.defineProperties(fn, {
durationMinutes: {
enumerable: true,
get: function () {
return roundMillisToMinutes(this.duration);
},
set: function (val) {
this.duration = val * 60000;
}
}
});
现在您有一个属性durationMinutes,它的行为类似于一个真实的属性,但由一个getter 和setter 函数组成。
让我们添加一些静态函数(不需要实例),稍后我们将使用它们将原始 JSON 对象转换为域对象:
Workout.fromJson = function(workoutJson) {
return new Workout(workoutJson);
};
Workout.fromJsonArray = function(workoutJsonArray) {
return workoutJsonArray.map(Workout.fromJson);
};
在我的数据访问服务中,我将原始数据转换为我的域模型的实例(在本例中为锻炼):
/**
* Get an overview list of all workouts.
* @returns {*} a promise resolving in an array of `Workout` objects
*/
function getOverview() {
var defer = $q.defer();
$http.get('/api/web/workouts?overview=1')
.success(function (data) {
defer.resolve(Workout.fromJsonArray(data));
}).error(function (response) {
defer.reject(response);
});
return defer.promise;
}
/**
* Get a single Workout by its `extId`.
* @param extId
* @returns {*} a promise resolving in the fetched workout
*/
function getByExtId(extId) {
return WorkoutRS.get({id: extId}).$promise.then(function (data) {
return $q.when(Workout.fromJson(data));
});
}
备注:我知道有更好的方法来处理 $q 承诺并做一些链接而不是使用 $q。这是 Angular 的一些早期工作。这里的重点是在何处以及如何将原始 JSON 数据转换为 JavaScript“构造”对象(在其 prototype 中使用辅助方法或属性。
编辑
我在 Opinionated AngularJS 博客中发现了一篇关于此的有趣文章。