Reputation: 27845
reading the What techniques can be used to define a class in JavaScript, and what are their trade-offs? on stackoverflow i understand that i can define a class via
Method 1:
function Person(name, gender){
this.name = name;
this.gender = gender;
}
and add functions in prototype so as to avoid member functions recreated every time its instantiated. like
Person.prototype.speak = function(){
alert("my name is" + this.name);
}
and create its instances via
var person = new Person("Bob", "M");
I think the creation of same object is possible with out new keyword like
Method 2:
var Person = function (name, gender) {
return {name:name, gender:gender};
}
person = Person("Bob", "M");
Is the second method doing exactly the same thing done by the first one? Also if so how would i mock up addition of functions via prototype (as we see in method 1's speak) in the second approach?
Upvotes: 0
Views: 580
Reputation: 74204
As Sean Vieira explained the first method is not the same as the second method. In the first method the instance inherits from Person.prototype
. In the second method the instance inherits directly from Object.prototype
.
Method 1:
null
^
|
| __proto__
|
+------------------+
| Object.prototype |
+------------------+
^
|
| __proto__
|
+------------------+
| Person.prototype |
+------------------+
^
|
| __proto__
|
+------------------+
| person |
+------------------+
Method 2:
null
^
|
| __proto__
|
+------------------+
| Object.prototype |
+------------------+
^
|
| __proto__
|
+------------------+
| person |
+------------------+
Interestingly the above diagrams show you that objects inherit from other objects in JavaScript, and not from constructors. Hence when you create new Person
the instance inherits from Person.prototype
, not from Person
itself.
How is this relevant information? For starters it demonstrates that you don't need to create a constructor to creates instances of an object. Instead you directly create the prototype object as follows:
var person = {
create: function (name, gender) {
var person = Object.create(this);
person.gender = gender;
person.name = name;
return person;
},
speak: function () {
alert("My name is " + this.name + ".");
}
};
In the above example person
is equivalent to Person.prototype
. You may now create an instance of person
as follows:
var bob = person.create("Bob", "M");
The prototype chain of bob
will look like this:
null
^
|
| __proto__
|
+------------------+
| Object.prototype |
+------------------+
^
|
| __proto__
|
+------------------+
| person |
+------------------+
^
|
| __proto__
|
+------------------+
| bob |
+------------------+
So why should you create objects like this instead?
new
to create an instance. This solves a lot of problems.For more information about this pattern read my blog post on "Why Prototypal Inheritance Matters".
Upvotes: 3
Reputation: 159875
No, Method 2 != Method 1. The second method is creating a new anonymous object with a prototype that points at Object.prototype
while the first is creating a new object with a prototype that points at Person.prototype
.
In psuedo-code:
// Method #1
function Person(name, gender) {
// The magic JS does *for us* (but *only* when invoked with `new`)
var this = {};
// __proto__ is the *internal* prototype reference
// It's not required to be accessible unless you're in an ES6 environment.
this.__proto__ = Person.prototype;
// Person.prototype is also created by JS for us
// and provided with a reference (among other things)
// to this function as prototype.constructor.
// Our stuff
this.name = name;
this.gender = gender;
// More JS magic
return this;
}
// Method #2
function Person(name, gender) {
// Just our stuff - no magic JS goodness here
return {
name: name, gender: gender
};
}
Upvotes: 5
Reputation: 39260
Maybe this answer can explain a bit more about constructor functions, inheritance, private variables and overriding methods: Prototypical inheritance - writing up
The other answers already address your question; creating an object as an object literal {prop:val,method:function(){}}
and creating an object using constructor functions: var MyObject=function(){this.prop=val};MyObject.prototype.method=function(){}
;
Upvotes: 0
Reputation: 8606
Your examples are achieving the same thing with regards to accessing the properties, but they are not identical as the first method has the basic Object
prototype. The answer to your second question is:
function Person( name, gender ){
return {
name: name,
gender: gender,
speak: function(){
alert("my name is" + this.name);
}
};
}
Here there is no prototype. The function is baked into the object literal. The only value in using a literal instead of a prototype would be to create a closure so you can have private variables e.g:
function Person( name, gender ){
return {
speak: function(){
alert("my name is" + name);
}
};
}
Upvotes: 0