7

I'm creating javascript object by doing something like:

function field(name,label){
        this.name = name
        this.label= label;
}

var a = new field("market","Mkt").

Then I assign a to another object.

object.newField = a;

The second way of doing it is to create a new property directly

object.2ndNewField = {
    name: "market2",
    label:"Mkt2"
}

I try to read the objects in other functions. They behave differently, however, when i stringify the object, it looks ok. What's the difference between the two properties i created?

btw is there any difference of the following object?

 object.2ndNewField = {
        "name": "market2",
        "label":"Mkt2
    }
brainjam
  • 18,863
  • 8
  • 57
  • 82
Progress Programmer
  • 7,076
  • 14
  • 49
  • 54

2 Answers2

6

The difference is that in the first case, the created object inherits from field.prototype then Object.prototype (i.e. its internal [[Prototype]] is field.prototype, whose internal [[Prototype]] is Object.prototype), where as in the second case it inherits only from Object.prototype.

Another way to look at it is:

object.newField instanceof field; // true
object.newField instanceof Object; // true

object.newField2 instanceof field; // false
object.newField2 instanceof Object; // true

or the inheritance chains are:

object.newField  -> field.prototype -> Object.prototype -> null

object.newField2 -> Object.prototype -> null

where '->' means "inherits from".

RobG
  • 142,382
  • 31
  • 172
  • 209
  • I'm trying to traverse the object in another function, the field.prototype makes it not working as i expected. Is there any way to fix it? – Progress Programmer Jul 12 '11 at 01:54
  • @CKeven `function F () {}; F.prototype = {hello: "world"}; var f = new F(); alert(f.hello);` <-- That's all there is to it. The object in `f` has a `[[prototype]]` *but not* a `prototype` property (some browsers expose it as `__proto__` property or similar). The Constructor function, `F` has a `prototype` property which is used as the basis for the new objects `[[prototype]]`. –  Jul 12 '11 at 03:50
  • @CKeven At least FF support the `constructor` property on new objects, but I do not know what the spec says on this. Note that the Constructor functions `prototype` is applied to the new object at time of `new` -- assigning a new object to the `prototype` later has no effect on previously created objects (but the prototype object can be mutated, which would be shared, of course). –  Jul 12 '11 at 03:57
  • @pst - in ECMA-262, all built-in prototypes have a public constructor property that points to their related built-in constructor, e.g. `Array.prototype.constructor === Array`. If you create a prototype chain using different constructors (i.e. ones you write yourself), you can manually set the public *constructor* property to the "correct" constructor object, otherwise they will point to Function or Object or whatever. – RobG Jul 13 '11 at 03:09
1

For the First option...Stay away from using "new". You can badly effect your global namespace if "new" is used wrong, or omitted when it should be used. Plus you have to be careful with the use of "this" in some places within your code, as it could be bound to something that you don't think it is, or even to your global data.

In your 2nd option you gave, you can safely use it for objects that are only used as a collection of data/methods (i.e. not "class-like" behavior) . If you want something that you can create multiple instances of with private and public variables/methods and can be inherited from, then you should use a function that returns an object.

I did a pretty big write up and example here of how to safely create base objects and use inheritance. If you follow the link, you will see why I didn't retype it all on this post ;).

Hope this helps...

Community
  • 1
  • 1
jyore
  • 4,715
  • 2
  • 21
  • 26
  • Uhhh..... "stay away from ... new" ... "badly effect ... namespace"? I don't get it. `new` doesn't affect the namespace at all. Also using `new` "wrong" or omitting is no more serious an offense than any other semantically invalid code. –  Jul 12 '11 at 03:23
  • @pst, If you define a "class" like object in JavaScript that is intended to use "new", and you forget to use the "new" operator when initializing a new object..."this" is bound to the global object, NOT the class-like object. This can cause many problems with variable collisions with your global data. So, if you forget to call new when creating a new object, you can effect other areas of your code without knowing it, and you will not be given an error. It is usually better to use objects returned from functions...especially if you are writing APIs – jyore Jul 12 '11 at 11:25
  • 1) There are no classes ;-) 2) Forgetting to specify `new` is no different than any other semantic error -- *it is a bug in the code that must be fixed and therefore not unique* (without a `return` in the function it is *easily detected* when trying to use the new object as the result of the function will be `undefined`) 3) `new` is required to utilize the `[[prototype]]` chain because of the [unfortunate] lack of ability to specify a prototype post-creation. –  Jul 12 '11 at 17:08
  • @pst, I know there are no classes, hints the quotation marks. While they are objects and not classes, it is easier to describe them as class-like to programmers that are classically trained (which is most programmers). Yes, forgetting to specify `new` is technically semantics, and yes, you have to use `new` to use the prototype object. If you are not intending to use prototypical type inheritance patterns, then there is not much need for `[[prototype]]`. As an API writer, I prefer closures because there seem to be less ways the user can mess things up...but you are right, it is all semantics – jyore Jul 12 '11 at 17:41