Say we create a Function named 'Shape', and add a property 'name' & method 'toString' on it's prototype:
var Shape = function () {};
Shape.prototype.name = 'Shape';
Shape.prototype.toString = function () {
return this.name;
}
console.log(Shape.name); // ''
console.log(Shape.toString()); // function () {}
var Triangle = new Shape();
console.log(Triangle.name); // 'Shape'
console.log(Triangle.toString()); // 'Shape'
'NEW' operator did two things:
1. It points this to 'Triangle'
2. It points 'Triangle's [[proto]] to Shape.prototype
Then I can understand when I call name & toString on Triangle, it searches for it's prototype chain till Shape.prototype.
But my problem is why not Shape searching for it's property(even it's an Object) for the method & property?
Thanks.
When you access a property on an object, Javascript looks first directly on the object for any properties that have been added directly to the object (these are called "own" properties). If it doesn't find the property there, then it looks up the prototype chain.
So, when you do this:
var Triangle = new Shape();
console.log(Triangle.toString()); // 'Shape'
it looks for the .toString() property on the actual object named Triangle, but there is no property by that name directly on that object. So, since it didn't find anything on the object directly, it then looks on the prototype and it finds the Shape.prototype.toString() implementation there and that is what is executed.
A reference to the prototype is stored on the Triangle object when it is created. It is not stored in the .prototype property - that property is only used on the constructor. Instead, each JS version has its own way of storing a reference to the prototype and it has traditionally not been the same for all browsers and how it was stored was non-standard. It was originally meant only for internal use by the JS engine. For example, Chrome stores it on a property named obj.__proto__, but IE does not. To fix this lack of standardization, there is new method called obj.getPrototypeOf() which can now be used in modern browsers to get access to the prototype for a given object. In any case, the JS engine searches this prototype for you automatically when resolving property names that are not found on the actual object itself.
If you did this:
var Triangle = new Shape();
Triangle.toString = function() {
return 'Shape named Triangle';
}
console.log(Triangle.toString()); // 'Shape named Triangle'
Then, javascript would first find the toString() implementation that you attached directly to the object and it would execute that one rather than the one on the prototype.
So I am adding according to what I know.
Here Shape is a function & A function is just a special kind of object, and like any object a function can have properties.
Functions automatically get a property called prototype, which is just an empty object. This object gets some special treatment.
When you will do a new of a Function the created object inherits all of the properties of its constructor’s prototype.
Like bellow
var Shape = function () {};
Shape.prototype.name = 'Shape';
Shape.prototype.toString = function () {
return this.name;
}
When you will say
var Triangle = new Shape();
So what it does
var Triangle = {};
Triangle.name = Shape.prototype.name
Triangle.toString = Shape.prototype.toString;
"it sets up the object Triangle to delegate to Shape.prototype."
So when you will do
Triangle.name //Shape
Triangle.toString() // Shape
But for Shape you will have to say
Shape.prototype.name //Shape
Shape.prototype.toString() //Shape
because Triangle is an object, where Shape is a function (a kind of an object), therefore when you request for a property of a function and it will not find it, will not search throught it's prototype propery. But you can modify Function.prototype.name/toSTring()
Related
Sorry I can't phrase this better. But I ran across some code like the following:
MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;
And I just can't seem to figure out what it does. MyObject is defined above it something like this:
function MyObject(options) {
this.someProp = someDefault;
this.otherProp = process(options.something);
// etc...
}
and it's always called as a constructor. I'm just wondering what benefit those first two lines provide and if it's a known pattern in Javascript.
I just can't seem to figure out what it does
It creates a new object that inherits from [the old] MyObject.prototype via Object.create and then overwrites MyObject.prototype with that. It also explicitly adds a .constructor property which actually should be existing already.
I'm just wondering what benefit those first two lines provide
None, unless before that snippet someone has corrupted the prototype (like MyObject.prototype = Object.prototype) and this is an attempt to fix it.
…and if it's a known pattern in Javascript.
Not like this. Using Object.create to set up the prototype chain for inheritance between constructor-defined "classes" is a known pattern, but then the constructors would be different on each side of the assignment.
The two lines of code provided seem to be an incorrect attempt of the use of prototypal inheritance, but I see where you're going with this and what you're trying to accomplish.
As we know, there are two ways in JavaScript to define objects that have properties and methods as members - the object literal notation and function notation. Using object literal notation, we don't have immediate access to the new keyword (think of this like using abstract classes in Java or C#). With function notation, we have access to the new keyword because the initial declaration of an object as a function serves as our constructor.
In ECMAScript 5, The Object object was given a method called create that provided developers a simple way to create a new object from an existing object declared with the object literal notation. (See documentation here). However, objects created in function notation have problems with this method because they are Function objects. The Object.create method is a great way to use simple inheritance, allowing access to the base properties and methods.
With function notation, once the new keyword is used, the result is not a function, but rather an object. For example, I can test this:
var Obj = function(){};
console.log(typeof Obj) // "function"
console.log(typeof new Object()); // "object"
Because of this, you can only inherit once (meaning the child object cannot be derived from):
var MyObject = new Object();
var anotherObj = new MyObject() // throws exception
To alleviate this problem, you need to follow three steps:
Create your child object in function notation (so you can create new instances of it using the new keyword and inherit from it).
Set the child object's prototype (an object) to the result of a new instance of the base object (which will be an object as well).
Set the constructor of the child object (which happens to be on the object's prototype) back to reference the Function of itself (which is a function prior to instantiation). If you don't do this, the constructor will remain an object, which cannot spawn new instances.
From here, you can create new instances of both the child and parent objects and derive from both, using the pattern. Here's a practical example:
var Vehicle = function(){};
Vehicle.prototype.start = function() {
return this.make + " " + this.model + " " + "started";
}
var Car = function(color, make, model) {
this.color = color;
this.make = make;
this.model = model;
}
Car.prototype = new Vehicle();
Car.prototype.constructor = Car;
var myCar = new Car("red", "chevy", "aveo");
myCar.start(); //"chevy aveo started"
I really don't see any benefit in doing that.
What it's doing is providing the new object with the previous objects methods. But it's coming from the same object...
Here is a good example of JS inheritance:
http://jsfiddle.net/aDCmA/2/
var App = (function(){
var Being = function() {
this.living = true;
this.breathes = function () {
return true;
};
};
var Robert = function() {
this.blogs = true;
this.getsBored = function () {
return "You betcha";
}
};
Robert.prototype = new Being();
return {
Being: Being,
Robert: Robert,
being: function(){ return new Being(); },
robert: function(){ return new Robert(); }
}
}());
Here is another question that is similar: inherit prototype methods from other classes without overriding own prototype methods
Credit to Robert Nyman for originally blogging about it: http://robertnyman.com/2008/10/06/javascript-inheritance-how-and-why/
Let's see line by line:
MyObject.prototype = Object.create(MyObject.prototype);
This redefines MyObject.prototype to an object that inherits from MyObject.prototype. This is unusual, because it makes no sense to inherit from itself.
MyObject.prototype.constructor = MyObject;
Since the previous line overwrote MyObject.prototype, this is just fixing the constructor property that was lost in the process.
I can think of one scenario where tht might be useful: if some code before that messed up with MyObject.prototype, for example assigning the prototype of another constructor to it:
MyObject.prototype = SomethingElse.prototype; // wrong way to do inheritance.
Then the code you posted would be an attempt to fix it.
This is perfectly valid Javascript.
Any javascript function (say Func)can be used as a constructor and the constructor invocation also requires a prototype property (i.e. F.prototype or the prototype associated with the function) . Thus (almost) every function has a prototype property. The value of this property (i.e. Func.prototype).
Now the value of this prototype associated with the function is an object itself that has a single non enumerable property called constructor. And the value of this constructor property is the function object (i.e. F itself).
Lets take an example.
Say I construct a function Func
var Func = function() {
//your definition
};
Now since this can be invoked as a constructor it has to have a prototype property Func.prototype lets call this proto.
proto = Func.prototype;
Now the prototype has a single property (that is non enumerable) called constructor. This constructor has a value that is equal to the function object itself.
Dont believe me check it like this
Func.prototype.constructor === Func // =>true
Will always return true for any function.
Now from the code you explained :
So basically these two lines
MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;
are modifying the value of the prototye to have a constructor property with the value of MyObject that is defined. But that would have happened anyways in the normal course of things. But the reason could be that maybe the prototype of the object has been changed earlier from the class it has been inherited from. In that case would those two lines make sense.
Hope that helps :)
I was always taught that in Javascript there is no distinction between objects and classes. Then can someone explain why this code generate error:
var firstObj = function() {};
firstObj.prototype.sayHi = function() {
document.write("Hi!");
};
firstObj.sayHi();
Whereas this one works:
var firstObj = function() {};
firstObj.prototype.sayHi = function() {
document.write("Hi!");
};
new firstObj().sayHi();
What's the difference? Why isn't the first one working?
The key issue here is that your firstObj variable is a Function object, not a firstObj object. This is a subtle distinction, but the type of object determines which prototype it inherits.
The prototype is like a template that is applied to newly created objects of a particular type. You must create a firstObj object (usually with new which invokes the constructor and assigns a prototype) in order to have that template applied to it. In the first example, your firstObj variable is a Function object, not a firstObj object so it has the prototype of a Function not of anything else..
In your second example, you actually create a firstObj object so it inherits the prototype for that type of object.
If you want the method applied in your first example so it works on the function object you've already created, just put the method directly on your already existing function object, not on the prototype.
There is no difference in the language between objects and classes1. However, there is a big difference between one kind of object and another. In the first case:
firstObj.sayHi();
you are trying to access the sayHi property of firstObj, which is a Function object that does not have such a property. (You could, however, do firstObj.prototype.sayHi().)
In the second case:
new firstObj().sayHi();
you are first invoking the new operator on the firstObj object, which evaluates to a new object. That new object has firstObj as it's constructor property and a prototype equal to the prototype property of firstObj. You are then accessing the sayHi property of that returned object, which succeeds because sayHi is in the prototype chain for that object.
1 Technically, JavaScript doesn't have classes2 (in the traditional sense), just constructor functions that are usually called "classes".
2 However, class is a future reserved word.
when you write this:
var firstObj = function() {};
you only define a constructor function, thus you need to use the key word new for the new objects created with this constructor function.
A function is just a function until new is issued. At that point, a Function Object is created based on the prototype for the function. That is why you will not see the sayHi method present in the first version.
Also, firstObj is a function, and not an object, so you need to invoke it to actually have anything happen. firstObj will not actually invoke the function, you must use firstObj().
Further, there are ways to have the prototype used without explicitly requiring the new keyword. This is done in a number of popular frameworks (such as jQuery). It is done by checking to see if new was used, and if it was not, then it news one up for you on the spot:
jsFiddle Demo
var firstObj = function() {
if( !(this instanceof firstObj) ){
return new firstObj();
}
};
firstObj.prototype.sayHi = function() {
alert("hi");
};
firstObj().sayHi();
var a = function () {};
a.prototype.test = function () {
alert("hello");
}
works fine but in following code
var b = new Object();
b.prototype.test = function () {
alert("hello");
}
i am getting this error TypeError: Cannot set property 'test' of undefined and i am unable to get it.
As per my understanding b has inherited prototype object from Object. So we should be able to add a new property in following manner say b.prototype.x = 1 .
But Object.prototype.x = 1 works .
typeof Object and a gives function but that of b is object
I am not getting why b.prototype.x = 1 doesnt work
Thanks.
Object is a function, which has a prototype property.
new Object() creates an object, which does not have a prototype property.
If you want to set the prototype of an object, you might mean setting the prototype of the object's constructor.
b.constructor.prototype.test = ...
To clarify some of the prototype/constructor nonsense:
A function has a prototype, which is an object. It specifies properties to add to an instance of that function.
An object has a constructor, which is a function. It specifies the function that was used to create the object.
Note that a function is an object, so it also has a constructor, which is Function.
This is a tricky issue -- there are two types of prototype fields, an internal one and an external one. The external one you can directly access with the normal prototype field as you are doing. The internal one is used to do lookups when a field/key is not found in the object.
If you do new blah(), it creates a new object whose internal prototype field is set to the external prototype field of blah. By default, the external prototype field of the newly constructed object is undefined. In particular, this is why evaluating b.prototype.x fails -- you can't do a field access on an undefined value. If you wish you can create a new object for a new external prototype, e.g. b = new Object(); b.prototype = {}.
You can see the internal/external prototype fields in action here:
Object.prototype.x = 4
b = new Object()
b.x // returns 4
What's happened is that b's internal prototype field points to Object.prototype, so lookups to b that fail are redirected to do a lookup in Object.prototype.
I'm not sure why, but newly created functions get their external prototype field set to Object -- this causes the first one to work.
You can refer to this resource
It doesn't work for the new object because it doesn't have a prototype property set. prototype property points to the Object that you have inherited. And since new Object() has had no object to inherit from, its prototype is set to undefined
A function on the other hand, has a super object (it inherited) by default.
You should be able to do it like this:
var b = {};
b.test = function() {
alert('Hello');
};
I have a method that will let me select the prototype object when creating a new object (copied from "Javascript: The Good Parts" book):
Object.create = function(o) {
var F = function() {};
F.prototype=o;
return new F();
}
Now say, I have an object:
var car = {
model: "Nissan"
};
And I create a new object based on this object, using the "Create" method:
var car1 = Object.create(car);
I can then add a property to car and it will dynamically get added to car1 (dynamic prototyping). So for eg:
car.year=2011; // Gets added to "car"...
alert(car1.year); // ... Is also avaialable to car1
Q1) This behavior indicates that "year" got added to car's prototype, which is why it is available to car1. Is this correct? If not, then where does "year" get added and why is it available to both "car" and "car1"?
Also, per the rule of delegation, if a method cannot be found on an object, it will search its prototype and then check all the prototypes up the chain till it gets to Object.prototype. So now, if I type something like this:
Object.prototype.originCountry = "Japan";
alert(car.originCountry); // Outputs Japan
alert(car1.originCountry); // Outputs Japan
So far so good; however, if I do:
Object.carColor= "White";
alert(car.carColor); // Error!
Q2) When I add a property to "car" (see car.year example above, it gets added to car's prototype. However, when I add a property to Object, it does not get added to Object's prototype? If it does get added to Object's prototype, then why is it not available to "car", per the rule of delegation?
Why is this happening?
When you do this:
Object.carColor = "White";
Then the property carColor does not get added to the Object's prototype. It is now a property of Object. To see what you expect, what you would do is:
Object.prototype.carColor = "White";
Then after that:
alert(({}).carColor); // Will alert "White"
So what happens here is that. any object created including {} (which is nothing but an empty object) is a new instance of Object and hence shares the properties of whatever is set in the prototype of Object.
As for how your Object.create function works. Let us look at it line-by-line:
1. var F = function() {};
You just create a new function, an essentially blank object. The reason you use a function and not something like {} is because a function can be coupled with a new call to create a new instance of that object wherein the function would act as a constructor.
2. F.prototype=o;
You set the prototype of the new blank function to the object you've created. Now, this is purely a reference. It is not a deep-copy. What I mean is that as the object o changes, so will any instances of the objects (actually they won't change, but they would 'seem to' change. More on that later).
3. return new F();
Now you just create a new instance of that function, which has a prototype as the object you passed.
When you do the following:
var car1 = Object.create(car);
You get an object car1 which has the prototype has car. So when you do this:
car.year = 2011
It isn't like car1 changes. It is more like the object that the prototype refers to changes. So when you do something like:
car1.year
A search is made (first in the prototype, then in the object) for a property called year and turns out, that the prototype has it and hence car1.year will return 2011.
So the bottom line is this:
A prototype is shared amongst instances.
Changing the properties of an Object will not manifest into any instances changing.
In your first example, you are adding to the prototype of your car1 because car === F.prototype and car1 instanceof F. So to Q1: yes.
Object is the constructor function of all objects, as F is to your car1. If you add something on Object.prototype, it will be available on all objects - that's the reason why you should not, such non-enumerable properties mess up all for-in-loops. If you set a property of the Object constructor function, nothing changes for the things that inherit from it. Don't forget: Object equals the F function, not the o parameter for prototype setting. new Object() is like Object.create(Object.prototype).
That function doesn't let you select the prototype object it creates a nmew object constructor, the object argument as prototype and then return a new object based on the constructor.
That new object will inherit methods and properties from the object arguments. This is to allow the creation of new objects that inherits from others.
The reason this works (and by the way Object is a core javascript object and should not be extended)
Object.prototype.originCountry = "Japan";
alert(car.originCountry); // Outputs Japan
alert(car1.originCountry);
and this doesn't
Object.carColor= "White";
is because the first extend the prototype object of Object, which means object build with the Object constructor will inherits those methods and properties.
When the later is what we call a static function which does not get passed to object created from the Object constructor.
I would recommend reading more about prototypal inheritance in Javascript. here is few links.
http://www.webreference.com/programming/javascript/prototypal_inheritance/index.html
http://www.htmlgoodies.com/html5/tutorials/javascript-prototypical-inheritance-explained.html#fbid=xEJ2PwtH2Oh
http://unscriptable.com/2007/04/17/inheritance-explained/
http://jsbin.com/ifoguf/14/edit#javascript
I attempted Isolating the Inheritance Part into a Function, but when I create the object nothings is alerted, no errors are returned, so I'm stumped how to debug, and for a solution.
function Shape(){}
// augment prototype
Shape.prototype.name = 'shape';
Shape.prototype.toString = function() {return this.name;};
function TwoDShape(){}
// augment prototype
TwoDShape.prototype.name = '2D shape';
function Triangle(side, height) {
this.side = side;
this.height = height;
}
// augment prototype
Triangle.prototype.name = 'Triangle';
Triangle.prototype.getArea = function(){return this.side * this.height / 2;};
var myTriangle = new Triangle(5, 10);
function extend(Child, Parent) {
var F = function(){};
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.uber = Parent.prototype;
}
extend(TwoDShape, Shape);
extend(Triangle, TwoDShape);
var myTriangle = new Triangle(5, 10);
alert(myTriangle.getArea());
alert(myTriangle.toString());
var s = new Shape();
alert(s.name);
TIA
Your code seemed a bit complex. See a simpler example (remember to switch on a debugging tool to see log messages).
It's worth noting that inheritance in JavaScript works by following prototype chains. That means every object holds a reference to a prototype object. This prototype object is just any ordinary object, too. The key is is that whenever a property (or function) is not found within an object, its prototype object is checked. This follows the prototype links until either a value was found or no prototypes are left over.
The prototype link is stored within an object whenever an object is created and points to the object as specified in the prototype property of the object's constructor function. You can inspect the prototype in Firefox by checking an object's __proto__ property.
In the linked example, there are 3 constructors:
Shape
Triangle
createPrototype (helper to get an empty object with defined prototype link)
In the linked example, there are 2 prototype objects:
Shape.prototype (contains shared properties for shapes)
Triangle.prototype (contains shared properties for triangles)
First a shape is created by calling new Shape(). This creates a new object since new is written in front of the function named Shape. The prototype link of the object (__proto__ in Firefox) points to Shape.prototype because this property of the constructor function gives the prototype link's target. The link is set on object instantiation.
As a result whenever you try to access a property of the shape the property is retrieved as follows. First, shape is searched for the property. If it's there, use it. If not, the prototype object shape.__proto__ is retrieved which refers to the same object as Shape.prototype. Now, the prototype object is searched for the property.
For the case of triangle the thing is a bit more complex because multiple prototype links are involved. The important thing is that we need to create an empty object to hold the triangles' shared properties which also needs to have its prototype link set to point to Shape.prototype. This makes shape's prototype the fallback of triangle's prototype.
It is archived by the anonymous function that includes createPrototype. It needs to be included because every invocation of the anonymous function needs to manipulate the prototype property of a constructor function (called createPrototype in our case). After the empty prototype object with the prototype chain is created, it is instantly returned and assigned to Triangle.prototype. After that any object created by new Triangle() has the desired prototype chain.
Once this is set, we can add all shared properties of triangles into the Triangle.prototype object that was just created. This is shown by overriding paint and by adding getArea. Note this overriding actually works because the paint function for triangles is found earlier than the paint method for shapes and the first found reference/property is used.
To summarize, all property accesses on objects use prototype chains for fallbacks. In our case the chain for shape is shape→Shape.prototype and the one for triangle is triangle→Triangle.prototype→Shape.prototype.
You might want to assign a name to the anonymous function (that includes createPrototype) to have a tool for created object hierarchies. This is shown in the updated example and ends up with the following helper:
function makePrototype(parent){
// We need a new object whose prototype link points to parent.prototype
function createPrototype(){
}
createPrototype.prototype = parent.prototype;
return new createPrototype();
}