Reputation: 6868
I'm not quite getting object creation and adding/extending methods in JavaScript. I know everything is an object and the use of functions as constructors, but I don't quite get prototype and creating/calling new methods.
var c1 = {
name: "Neil",
};
var c2 = function() {
this.name = "Neil";
};
With both the above I can add new stuff:
c1.town = "a town";
c2.town = "a town";
c1.setTown = function(newTown) { this.town = newTown;};
c2.setTown = function(newTown) { this.town = newTown;};
Where I fall over is with the function approach I can do this:
c2.prototype.setTown2 = function(newTown) { this.town = newTown;};
c3 = new c2();
c3.setTown2("new3");
1: What is the difference between setTown and setTown2 and why for c3 can I call c3.town="x" and c3.setTown2("x") but not call c3.setTown("x"); ?
2: I don't seem to have access to 'prototype' for the c1 (the literal constructor approach), why is this?
thanks.
Upvotes: 0
Views: 57
Reputation: 1784
This is because JavaScript literal constructors like c1
create an actual Object
, while functions with this
like c2
create constructors that can be used to create objects like you did with c3
. Here's an analysis of your code through JavaScript comments:
//This is a literal object with property name equal to "Neil":
var c1 = {
name: "Neil",
};
//We do not need to access the prototype here because c1 is an object, not a constructor:
console.log(c1.name);
//This is a constructor that creates an object with property name of "Neil".
var c2 = function() {
this.name = "Neil";
};
//This creates a property town of "a town" on c1. This works because c1 is a regular object.
c1.town = "a town";
//This creates a property town of "a town" on c2. However, if you create an object with c2, the object will not inherit town because it is not on the prototype.
//This does not throw an error because even though c2 is a function, you can still set the property town on it because this property is what's called a _static property_. Static properties are properties that are set without the prototype like the property below:
c2.town = "a town";
//With c1, we do not need to access prototype because it's a regular object and with c2, we do not need to access prototype because it's a static property.
console.log(c1.town, c2.town);
//This works the same as above, except now, we're using functions instead of regular properties.
c1.setTown = function(newTown) { this.town = newTown;};
c2.setTown = function(newTown) { this.town = newTown;};
//This sets the town property of c1 like with a regular object:
c1.setTown("HI!");
//This sets the static property town of c2 because "this" in the static method c2.setTown is c2, so "this.town" is "c2.town", or the static property town which we set above:
c2.setTown("HI!");
//Both of the following outputs "HI!" because of the .setTown() calls above.
console.log(c1.town, c2.town);
//This method is set on the prototype of c2, meaning that objects made with c2 will inherit this method.
c2.prototype.setTown2 = function(newTown) { this.town = newTown;};
//This is an object made with the constructor c2. It inherits name because of the actual constructor function and it inherits setTown2 from the prototype. However, it does NOT inherit c2.town and c2.setTown because those are static properties not on the prototype.
c3 = new c2();
//This sets the town property of c3 because c3 inherited the setTown2 method from c2.prototype, so that method now sets the properties of c3.
c3.setTown2("new3");
//c3.name outputs "Neil" because of the c2 constructor function and c3.town outputs "new3" because of the above c3.setTown2() call:
console.log(c3.name, c3.town);
Upvotes: 1
Reputation: 25332
1: What is the difference between
setTown
andsetTown2
They're both function, however you create a new function every time you want to add that as method, where with prototype
you automatically inherit it:
var c3 = new c2();
var c4 = new c2();
c3.setTown = function(newTown) { this.town = newTown;};
c4.setTown = function(newTown) { this.town = newTown;};
console.log(c3.setTown === c4.setTown) // false
console.log(c3.setTown2 === c4.setTown2) // true
Also,setTown
is a property of the objects c3
and c4
, where setTown2
is not. It's inherited. It means:
console.log(c3.hasOwnProperty("setTown")); // true
console.log(c3.hasOwnProperty("setTown2")); // false
And therefore Object.keys
won't return setTown2
; but if you execute a for…in
loop you will get both own properties and inherited properties.
and why for c3 can I call c3.town="x"
Because you're simply adding a property. Unless the object is frozen, or sealed you can add any properties you want, any time. You could also add c3.foo = "bar"
, even if it's not in the prototype or added in the constructor.
and c3.setTown2("x") but not call c3.setTown("x");
Because it's an inherited method, so the object can obtain it traversing the prototype's chain; but you never add setTown
to c3
instance, or to any object in its prototype chain.
2: I don't seem to have access to 'prototype' for the c1 (the literal constructor approach), why is this?
Because prototype
is a property only for functions, that you can use as constructors. c1
is already an object, so doesn't need to have another object as "prototype". You can use directly c1
as object's prototype to create other object based on it:
var cc1 = Object.create(c1);
That will inherit all the methods and property c1
has, so:
console.log(cc1.name) // "Neil"
console.log(cc1.hasOwnProperty("name")) // false
As we see in the first point.
Hope it helps.
Upvotes: 1
Reputation: 619
Are you familiar with inheritance? A common concept in programming, this is the way to simulate inheritance in javascript.
Basically, when you add new methods or variables to the prototype, you modify the main structure of the object... So when you decide to create a new object from the modify 'class' (there are no classes in JS I know), the only method it remains are the ones inside the prototype.
More info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
Upvotes: 1