1

Just a quick thought, of which I have no idea how to google it.

If you get a list of lets say 'persons' from an API in JSON format with AngularJS and you convert it to a JS array/object:

[
  {firstName: 'Foo', lastName: 'Bar'},
  {firstName: 'Banana', lastName: 'Fruit'}
]

And you want some general function that joins first and last name into fullName.

Is it then generally considered better to use solution 1 or 2?

Solution 1 Array consists of objects which have all methods they need inside themself.

[
  {firstName: 'Foo', lastName: 'Bar', fullName: function(){return this.firstName+' '+this.lastName;}},
  {firstName: 'Banana', lastName: 'Fruit', fullName: function(){return this.firstName+' '+this.lastName;}}
]

I think this is the most OOP solution, but is in also the best solution in case of Javascript (and long lists)?

Solution 2 Make helper function that's only being instantiated once.

var helper = function(person)
{
   return person.firstName+' '+person.lastName;
}

I know this is very basic, but sometimes that is the best stuff to get right ;)

Gersom
  • 651
  • 3
  • 19

2 Answers2

3

In your first solution you'r adding a function to every object, it feels eavy, if you have a lot of objects and if you iterate other them, I don't think that's best.

The second is more light.

Another idea :

Maybe you could parse your JSON to a specific object, like in here :

Parse JSON String into a Particular Object Prototype in JavaScript

And then use the prototype

Foo.prototype.fullname = function (){
    return this.firstName+' '+this.lastName;
}

And so every Foo object will be able to call fullname() through the prototype (in memory only once vs in every object).

Community
  • 1
  • 1
Boris Charpentier
  • 3,515
  • 25
  • 28
1

You have already a good answer by Boris Charpentier. I can add some example code:

A constructor function which can initialize itself by 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;

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

Now you have a property durationMinutes which behaves like a real property, but consists of a getter and setter function.

Let's add some static functions (no instance necessary), we'll use them later to transform 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'm transforming raw data to instances of my domain model (Workout in this case):

/**
 * 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));
    });
}

Remark: I know there are better ways to deal with $q promises and do some chaining instead of using $q. This is some early work with Angular. The important point here is where and how to transform raw JSON data to JavaScript "constructed" objects (with helper methods or properties in their prototype.

Edit

I've found an interesting article about this in the Opinionated AngularJS blog.

hgoebl
  • 12,637
  • 9
  • 49
  • 72