Boris Charpentier has provided a solid answer, and I'd like to supplement it with some example code:
Below is a constructor function that can initialize itself using a raw JSON object:
function Workout(workoutJson) {
if (workoutJson) {
this.duration = workoutJson.duration;
... // or copy all properties in a for-loop
}
}
var fn = Workout.prototype;
// extending the prototype with additional functions
fn.getSomeData = function () {
return this.onePart + ' ' + this.anotherPart;
};
// an alternative solution: defining properties (requires a modern browser)
Object.defineProperties(fn, {
durationMinutes: {
enumerable: true,
get: function () {
return roundMillisToMinutes(this.duration);
},
set: function (val) {
this.duration = val * 60000;
}
}
});
By implementing a property durationMinutes
, you create a real-like property that includes both getter and setter functions.
Let's include some static functions (no need for instances), which we can use later for converting raw JSON objects to domain objects:
Workout.fromJson = function(workoutJson) {
return new Workout(workoutJson);
};
Workout.fromJsonArray = function(workoutJsonArray) {
return workoutJsonArray.map(Workout.fromJson);
};
In my data access service, I convert raw data into instances of the domain model (Workout in this instance):
/**
* Get a list overview 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;
}
/**
* Retrieve a single Workout using 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));
});
}
Note: There may be better ways to handle $q promises, such as chaining instead of using $q directly. This approach showcases transforming raw JSON data into JavaScript "constructed" objects (featuring helper methods or properties in their prototype
).
Edit
I came across an informative article on this topic in the Opinionated AngularJS blog.