1

I'm probably missing something really basic on javascript knowledge, but why doesn't this work?

var person = {

    name:"",
    age:0,

    set : function(name,age){
        this.name = name;
        this.age = age;
    }
}

var me = new person; // ERROR: Object doesn't support this action!
me.set('Victor',12);
me.name //Victor

But this does:

var person = function(){

    this.name="";
    this.age=0;

    this.set = function(name,age){
        this.name=name;
        this.age=age;
    }
}

var me = new person(); //WORKS!
me.set('Victor',12);
me.name; //Victor
Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
Vitim.us
  • 20,746
  • 15
  • 92
  • 109
  • 1
    Yes, only the second one works. Why/how would the first one work? You need a constructor function to call new on. – Thilo Dec 20 '11 at 04:35
  • possible duplicate of [How to "properly" create a custom object in JavaScript?](http://stackoverflow.com/questions/1595611/how-to-properly-create-a-custom-object-in-javascript) – Thilo Dec 20 '11 at 04:36

4 Answers4

2

Your first example was an object literal:

var person = {
    name: "Bob",
    //etc
};

You've created a single object called person, and that's that. The concept of creating new persons has no meaning.

If you want to create something that can be used to create more objects at will, you'd use a function, like your second example.

Note though that functions intended to be used as a constructor start with a capital letter by convention. Also note that when you set a function inside of your constructor using

this.functionName = function() .....

this creates a privileged function, since it has access to both public, and private members. If this set function only needs access to public properties, it would usually be added to the function's prototype. Here's how the whole thing might look

function Person() {
    this.name = "";
    this.age = 0;
};

Person.prototype.set = function(name,age) {
    this.name = name;
    this.age = age;
}

And here's what a privileged method might look like

function Person() {
    var localData = "Hello";

    this.showPrivateData = function() {
        alert(localData);
    };

    this.name="";
    this.age=0;
};

localData is local to the Person function, and cannot be accessed as a property on instances of Person; however, the showPrivateData function, and any other privileged functions you might add, would form a closure over it, and have access to it.

Finally, note that constructor functions can take parameters:

function Person(name, age) {
    this.name= name;
    this.age= age;
};
Adam Rackis
  • 82,527
  • 56
  • 270
  • 393
1

JavaScript has no classes (although you can simulate them), this is why. And new works only on functions (in this case it creates special variable this inside function, which is being returned implicitly after function call).

So, when using this:

var person = {
    name:"",
    age:0,
    set : function(name,age){
        this.name = name;
        this.age = age;
    }
};

you already create an object (which has a function as one of its properties).

But when you use this:

var person = function(){
    this.name="";
    this.age=0;
    this.set = function(name,age){
        this.name=name;
        this.age=age;
    }
};

you only create function, that returns this with all assigned properties when the function is called with new.

What documentation says

As documentation of new operator on Mozilla Developer Network says:

The new operator creates an instance of a user-defined object type or of one of the built-in object types that has a constructor function.

...

Creating a user-defined object requires two steps:

  • Define the object type by writing a function.
  • Create an instance of the object with new.

and you basically make both steps in the second case.

Tadeck
  • 132,510
  • 28
  • 152
  • 198
  • I almost always write like the second but all IDEs only autocomplete methods and properties in the first way, so I tried to "translate" a class to object literal, to my code could be auto completed. Any thoughts to workaround this issue? – Vitim.us Dec 20 '11 at 14:21
  • @Vitimtk: You are incorrect, at least in NetBeans you are able to write `var A = function(){this.test='ABC';};var a=new A();` and when writing `a.` in `alert(a.test);`, you are given a list of properties (with `test` among them, with proper tip about it being declared in `A`). It looks like it does not even need plugins for this. – Tadeck Dec 20 '11 at 16:35
  • In Aptana Studio doesn't work for me, I tried document my class with ScriptDoc without success... I'm so mad about this. – Vitim.us Dec 20 '11 at 16:50
  • @Vitimtk: Aptana Studio is not "_all IDEs_". Maybe you should consider changing your IDE or helping [Appcelerator](http://aptana.com/company) [expand Aptana with this feature](http://aptana.com/contribute)? – Tadeck Dec 20 '11 at 16:54
1

You answer your own question. A constructor (the thing that goes next to new) must be a function in JavaScript.

Amadan
  • 191,408
  • 23
  • 240
  • 301
0

The first version uses an object literal to create a single object instance which is assigned to person. This cannot be used like a constructor with new to create other objects from person.

The second version uses a function, which can be called as a constructor to create new objects with new person().

That's just the way new works in JavaScript. Essentially if you want to be able to create multiple instances from a template (similar to how classes work in other languages) then use the new FunctionName() syntax. If you only need to create a single instance of a particular object you can use the first syntax.

Note that in the first version you can say:

person.set('Victor',12);
alert(person.name); // 'Victor'

Note also that if you are creating a function that is intended for use as a constructor the convention is to use uppercase for the first letter of its name (or the first letter of each word in the name).

nnnnnn
  • 147,572
  • 30
  • 200
  • 241