views:

169

answers:

3

Here I made two objects; one has accessor methods created in the constructor, the other in the prototype. Why would one choose one of these over the other?

function spy1(name){
  this.name = name;
  var secret;
  this.setSecret = function(message){
    secret = message;
  };
  this.getSecret = function(){
   return secret;
  };
}

function spy2(name){
  this.name = name;
  this.secret;
  /* (see comment) was:
  var secret;
  */
}
spy2.prototype.setSecret = function(message){
  this.secret = message;
  /*was:
  secret = message;
  */
};
spy2.prototype.getSecret = function(){
  return this.secret;

  /*was:
  return secret;
  */
};

bond = new spy1("007");
smart = new spy2("86");

bond.setSecret("CONTROL is a joke.");
smart.setSecret("The British Secret Service is for sissies.");
+1  A: 

With the second version you end up with a cleaner "constructor".

Flavius Stef
Yes, and I also end up with things which are related to the class sort of floating out there by themselves, not visibly a part of the class. That bothers me a just little bit.
Shawn J. Goff
+4  A: 

The primordial differrence is that in your first example, without prototype, the getSecret and setSecret function implementation will reside on every instance of spy1.

On your second example, the functions are defined on the prototype, and all instances refer to them directly, you can test it:

var bond = new spy1("007"),
    bond2 = new spy1("007");

bond.getSecret === bond2.getSecret; // <-- false since they are two functions

var smart = new spy2("86"),
    smart2 = new spy2("86");


smart.getSecret === smart2.getSecret; // <-- true since is the same function
                                      // on all instances

Also note what @T.J. commented, in your second example, using the prototype, you don't have access to the constructor function closure, and for that you are making a window.secret global variable.

If you intend to work with privileged methods, extending the prototype is not an option, all the methods that need access to the variables defined within the scope of the constructor function need to be declared inside of it...

See also: Closures.

CMS
...which (for the questioner's benefit) has serious memory usage ramifications and should be avoided if possible.The non-prototype version does have the advantage that you can have truly private instance vars, because the member functions are closures. (Although not in the way that it's done in the questioner's question.)
T.J. Crowder
It may have serious memory usage ramifications, but if you're only creating a small number of instances, you have nothing to worry about.
Daniel Yankowsky
+3  A: 

In your first example, you're creating new functions for each instance of the object whenever you instantiate a new one. In the second, only a single copy of the function is created which is used by all the instances.

The second way can save memory. You can also use prototype chaining to implement inheritance.

Btw, your second example won't work as written. the secret variable in spy2 is local to the constructor. In the setSecret and getSecret functions in the prototype, you're accessing a single global variable.

jimr
Ah, I see. So if I really want private variables, I can't use the prototype.
Shawn J. Goff