1

I have a collection of users which I just got from a JSON server response. Assume the following:

var users = [
    {id: 1, name: 'john', surname: 'smith'},
    {id: 2, name: 'john', surname: 'smith'},
    {id: 3, name: 'john', surname: 'smith'},
    {id: 4, name: 'john', surname: 'smith'},
    {id: 5, name: 'john', surname: 'smith'},
    {id: 6, name: 'john', surname: 'smith'},
    {id: 7, name: 'john', surname: 'smith'}
];

At some points in the business logic and the (handlebars) templates of the application I need to have the full name of each user but of course I don't want to repeat the concatenation logic of name + ' ' + surname all over the place.

Thus I do the following which "enhances" those users and adds this function I want:

for(var i=0,length=users.length; i<length; i++) {
    users[i].getFullName = function() {
        return this.name + ' ' + this.surname;
    }
}

This technique works fine but my questions are:

  • is there a better way of doing this? Note that I want an object oriented style solution and not something like getFullNameOfUser(user).
  • I can measure the time penalty to add the function to all those objects, but can I measure the memory penalty for adding the function to the objects? Solutions such as JavaScript object size do not count functions.
Community
  • 1
  • 1
cherouvim
  • 31,725
  • 15
  • 104
  • 153
  • 1
    `users[i].fullname = users[i].name + ' ' + users[i].surname` is not an option? :) – Ja͢ck Feb 26 '13 at 14:41
  • @Jack: No because this would cache the value. I want a live function/method on the object which can do anything with the state of the object. – cherouvim Feb 26 '13 at 14:43
  • Okay I was half kidding on that, but that was a point I had not considered :) – Ja͢ck Feb 26 '13 at 14:45

3 Answers3

4

you could create a class, Users, and add getFullNameOfUser to the prototype.

var User = function(obj){
   this.id = obj.id;
   this.name = obj.name;
   this.surname = obj.surname;
};

User.prototype.getFullNameOfUser = function(){
   return this.name + ' ' + this.surname;
};

for(var i=0,length=users.length; i<length; i++) {
    users[i] = new User(users[i]);
}

About your question in the comment, you could do:

var User = function(obj){
       for(var key in obj){
          this[key]  = obj[key];
       }
    };

but this way you might end up with unwanted properties in the object

André Alçada Padez
  • 10,987
  • 24
  • 67
  • 120
0

This seems inefficient because you are adding a function to each user.

Using handlebars.js you should be able to simply handle concatenation in the view, i.e.:

<h2>Welcome {{user.name}} {{user.surname}}!</h2>
disperse
  • 1,216
  • 10
  • 22
  • The code was examplatory and simplified for the sake of the question. I'm doing more than just concatenation within those functions (e.g launching rockets). – cherouvim Feb 26 '13 at 14:39
  • Andre's answer is correct, creating a new class and creating JavaScript's version of a static method will prevent you from having to add a new function for each user. Ideally you would create a list of User objects when loading the data so you don't double your memory usage. – disperse Feb 26 '13 at 14:42
0

You could always create a bunch of utility functions and call them with a specific context as needed.

function getFullName () {
   return this.name + ' ' + this.surname;
};

getFullName.call(users[0]);
istos
  • 2,654
  • 1
  • 17
  • 19