tags:

views:

76

answers:

5

These are the ways of creating javascript objects:

function apple(optional_params) {
    this.type = "macintosh";
    this.color = "red";
    this.getInfo = function () {
        return this.color + ' ' + this.type + ' apple';
    };
}

var apple = {
    type: "macintosh",
    color: "red",
    getInfo: function() {
        return this.color + ' ' + this.type + ' apple';
    }
}

I really prefer the latter one most since it's Json syntax, but I've seen more of the first one than the latter one.

  • Are there any differences between them functionally?
  • Could each of them be extended, inherited and cloned/copied?
  • In the latter one I could easily create nested elements, is this possible with the first one?
  • In the latter one I can't pass optional parameters?
  • Are they serving different purposes? If yes, could you give scenarios where I would use either of them.
A: 

Sorry, I'm still a little noob at javascript, but aren't these functions and not objects? Object-oriented, yes, but functions? Quite interested actually.

Oh, I've only used the first one. I think it looks clearer to me because it outright declares "new function".

Danae
Put this as a comment and I'm sure you'll get answers:)
never_had_a_name
In JS, a Function is a kind of Object
Tobias Cohen
Actually most everything become an object. [] = Object, {} = Object, function() {} = Object. It's a very flexible model and opens up some pretty interesting possibilites.
thomasmalt
+3  A: 

The difference is that you can reuse the first one. Example:

function Apple(type, color) {
  this.type = type;
  this.color = color;
  this.getInfo = function () {
    return this.color + ' ' + this.type + ' apple';
  }
}

var red = new Apple("Macintosh", "red");
var green = new Apple("Granny Smith", "green");

vs.

var red = {
  type: "Macintosh",
  color: "red",
  getInfo: function() {
    return this.color + ' ' + this.type + ' apple';
  }
};

var green = {
  type: "Granny Smith",
  color: "green",
  getInfo: function() {
    return this.color + ' ' + this.type + ' apple';
  }
};
Guffa
Isn't it possible to pass parameters to the second one somehow?
never_had_a_name
@ajsie: You could wrap the object literal in a function and pass parameters to the function that you use in the object. That's used sometimes when you want a factory function rather than a constructor.
Guffa
+3  A: 

For your first object you'd want to put the member function in the prototype, like such:

function apple(optional_params) {
    this.type = "macintosh";
    this.color = "red";
}

apple.prototype.getInfo = function () {
    return this.color + ' ' + this.type + ' apple';
}

This causes the "object" to only create two new fields in memory (type and color) while keeping the function as part of the prototype for that object. Your second object (hash table) creates a new function for each object.

So as you can see using the function approach is good if you have lots of functions, because the functions then don't take up extra memory.

To clarify: Your two examples produce the same result, but if you put the function in a prototype the result is different.

Tor Valamo
Can't I do the same for the second one, only have the attributes in that json string but then insert them afterwards with: "apple.getInfo = function() {...}"?
never_had_a_name
note the `prototype` bit. and yes, it is possible, as long as you also create a constructor for it. (the function-object itself is a constructor by default when using the `new` keyword)
Tor Valamo
+2  A: 

The second example simply defines an instance of Object, with a few properties set. The first one is much more interesting.

Functions in JavaScript have dual purposes, one as a normal function/procedure, and the other as the basis for prototypal inheritance, similar to a "class" in normal OOP.

For example:

var apple = function() {
    this.type = 'granny smith';
};
var myApple = new apple();
alert(myApple.type); // -> 'granny smith'

Here, we've defined a "class" called apple, with an initializer that sets the type property. myApple is then created as an instance of apple, and the type property gets set by the apple() initializer.

(As an aside, new apple() could also be called as new apple with the parenthesis omitted and the result is still the same, the initializer is still called, it just receives no arguments)

The other major thing that using new gives us is prototypal inheritance. All functions come with a prototype object that we can set properties on. Those properties then become fallback values for instance objects that don't have their own value defined.

Example:

var greenApple = function() { };
var myApple = new apple();
alert(myApple.color); // -> undefined
greenApple.prototype.color = 'green'
alert(myApple.color); // -> green

Here, setting greenApple.prototype.color affected the color property for the myApple we had already created. This is what is referred to as prototypal inheritance, and it has a wide variety of uses.

 

Edit: The following refers to an earlier version of the question that was edited while I was writing this. You can safely ignore it unless you're especially interested.

Now, back to your first example:

var apple = new function() { ... }

Because you have the new keyword before the function definition, the effect is like creating the apple class, making a myApple object, then throwing the apple class away. If you had access to this class, you could use .prototype to add prototype properties, but you don't - all that's contained in the apple variable (in OOP terms) is an instance of the class, not the class itself.

Tobias Cohen
+1  A: 

This is the way I create Javascript objects in most cases:

/**
 * This becomes the constructor of Apple, a type of fruit.
 */
 var Apple = function() {
    // Object init here
    // This becomes a "private" variable
    var seeds = 50;

    // This becomes "public" properties
    this.color  = 'red';
    this.weight = 100; // in grams if you wonder. 

    /**
     * Do stuff to count the seeds
     * This becomes a privileged method that can access private variables
     * and be called from outside the object
     */
    this.countSeeds = function() {
        // Do stuff to count the seeds.
        return seeds;
    }
}

/**
 * Static functions can be utility functions that can be called separate from 
 * object instances. They do not have access to any variables or functions
 * in the constructor.
 */
Apple.getTypes = function() {
    return ['golden', 'granny', 'red', 'pink'];
}

/**
 * Public function that gets the default color
 */
Apple.prototype.getColor = function() {
    return Apple.color;
} 

/**
 * Public function that sets the color of the object instance.
 */
Apple.prototype.setColor = function(color) {
    this.color = color;
    return this.color;
}

var golden = new Apple();
golden.setColor('yellow');
alert('The color of the apple is ' + golden.color);
thomasmalt
I think you forgot the quotes around "red". And the Apple.getColor() doesn't work. It returns "undefined". Why is that?
never_had_a_name
Sorry about that. Static functions are called outside object instances and naturally do not have access to object internals and variables set by the constructor. my bad. I wrote the example without checking.
thomasmalt