4

Are there any performance or functional differences between having a javascript constructor return a JavaScript object literal, versus simply setting properties with this.XYZ. For example:

    function PersonA(fname, lname) {
        this.fname = fname;
        this.lname = lname;
    }

    function PersonB(fname, lname) {
        return {
            "fname": fname,
            "lname": lname
        };
    }

Both seem to behave appropriately:

    PersonA.prototype.fullName = function() { return this.fname + " " + this.lname; };
    PersonB.prototype.fullName = function() { return this.fname + " " + this.lname; };

    var pA = new PersonA("Bob", "Smith");
    var pB = new PersonB("James", "Smith");

    alert(pA.fullName());
    alert(pB.fullName());

Is one preferable for any reason, or is it a matter of taste? If taste, is one more standard?

Adam Rackis
  • 82,527
  • 56
  • 270
  • 393

2 Answers2

4

They're not entirely identical.

If you return the object being created from the constructor...

  • it will inherit from the prototype of the constructor
  • it will have instanceof available as a means of testing which constructor created it

The reason the fullName() method seems to work for pB is that you're using the PersonA constructor for both.

var pA = new PersonA("Bob", "Smith");   // uses PersonA constructor
var pB = new PersonA("James", "Smith"); // uses PersonA constructor???

FYI, the proper term is "JavaScript object literal", not "JSON object literal".


EDIT: You've updated the code in the question to use the PersonB constructor. Run it again, and you'll find an Error in the console.

user113716
  • 318,772
  • 63
  • 451
  • 440
  • @Adam: Rerun the code, and you'll see that `pB` no longer works because it doesn't have a `fullName()` method. – user113716 Aug 26 '11 at 16:38
  • Error indeed. So the PersonB ctor is simply invalid JS? `alert(pB instanceof PersonB);` shows false, so it looks like there are a lot of problems with this approach anyway – Adam Rackis Aug 26 '11 at 16:40
  • Thanks—what a stupid type for me to make...hid the fact that the whole question was moot. I saw the layout of the PersonB ctor in a JS presentation online and to me it seemed more pleasant than `this.someNewProperty = ...` but I guess doing it this way (PersonA) is simply the correct way to do it – Adam Rackis Aug 26 '11 at 16:43
  • @Adam: It is valid JS, but it just doesn't behave the same as `PersonA`. When invoking as a constructor, it implicitly returns the new object (which is referenced by `this` in the constructor). But it does allow you to override that implicit return by returning some other type of object. At that point, the object you're returning really has nothing to do with the constructor. For example, have `PersonB` do `return {foo:'bar',person:this};` Now the main object being returned is just a plain old object, but the value of the `person` property is the object actually created from the constructor. – user113716 Aug 26 '11 at 16:44
  • @Adam: Easy mistake to make. ;) – user113716 Aug 26 '11 at 16:44
  • thanks. I (think I) understand. So the PersonB function might still have value, just not as a constructor – Adam Rackis Aug 26 '11 at 16:45
  • 1
    @Adam: Right. In its current form, it's really just behaving as a regular function. But it could be that you want it to return some other type of object, but you still take the object being constructed (which is represented by `this`), and assign it somewhere else. But yeah, the way it is right now, there's not much value as a constructor. – user113716 Aug 26 '11 at 16:47
1

When you new a function constructor, an empty object is created, and is then referred to by this within the function constructor.

So with PersonA, think of it like so:

// create an empty object
var emptyObj = {}; 

// call the function as a method of the empty object
PersonA.call(emptyObj, "Bob", "Smith");

Which results in emptyObj equalling:

{
   fname : "Bob",
   lname : "Smith"
}

When you call PersonB, you are still creating an empty object by calling new, but essentially not doing anything with it, and returning a different object as the result.

Steve
  • 53,375
  • 33
  • 96
  • 141
  • No prob. Check out the "Custom Objects" section of this article: https://developer.mozilla.org/en/A_re-introduction_to_JavaScript. – Steve Aug 26 '11 at 17:38