Isolating the Inheritance into a Function - javascript

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();
}

Related

Why constructor function prototype can be assigned to an object and what it means

I am reading through the official docs:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
and in the chapter Different ways to create objects and the resulting prototype chain -> With a constructor they have the following:
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype = {
addVertex: function(v) {
this.vertices.push(v);
}
};
var g = new Graph();
// g is an object with own properties 'vertices' and 'edges'.
// g.[[Prototype]] is the value of Graph.prototype when new Graph() is executed.
But right before that it is written that:
// Functions inherit from Function.prototype
// (which has methods call, bind, etc.)
// f ---> Function.prototype ---> Object.prototype ---> null
So, Graph is a function and it should have Graph.prototype, in my understanding, to be of type Function.prototype and NOT Object.prototype, otherwise Graph would stop being a function and would instead become an object, or so I would think.
Could anyone explain why the prototype of Graph is assigned to an object and why the specified behavior of inheriting then addVertex becomes possible? Would we lose all of the function properties (call, bind) when such assignment happens?
There are two different prototype chains at play:
The prototype chain of the constructor
The prototype chain of objects that are created by that constructor
They have nothing to do with each other. The first is a function and thus related to Function.prototype, the other is not a function, but an object whose prototype object is created at the same time as the constructor function object was created. That prototype object will be used when a new instance is created by calling the constructor with new.
What can be confusing here, is that the constructor has a property that is called prototype, but that is not the prototype object of the constructor (point 1), but of objects it can create (point 2). Possibly this property would have been better named prototypeForConstructedInstances... but that's a bit long ;-)
To get the constructors own prototype you would write Object.getPrototypeOf(constructor),... and you'll see it is Function.prototype.
You may have an interest in reading more about the broader subject of prototypes at "How does JavaScript .prototype work?". It's an interesting read, and you'll also find my answer over there.

Javascript `new` operator & prototype

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()

__proto__ : function declaration versus object literal

I've just started reading this article and I'm stuck on the first paragraph:
For the code:
var foo = { x: 10, y: 20 };
we have the structure with two explicit own properties and one
implicit proto property, which is the reference to the prototype
of foo:
Figure 1. A basic object with a prototype.
My question...
Why does the diagram show a foo prototype for a basic object literal?
If I create two objects, it shows this isn't the case:-
object one - a function object / constructor function
object two - a basic object literal with key/value pairs like a dictionary
If I use the debugger, it shows that object one does indeed create a One.prototype which also has an Object.prototype further down the chain, but object two does not have a two.prototype, instead it goes straight to the Object.prototype.
Have i misunderstood the proto concept or is the article incorrect by implying object literals have their own prototype?
EDIT:
I've given up reading the article, it's broken English makes a complicated subject more complicated.
The guy in this video answers my question and to sum it up:
every object has a __ proto __
only functions have a prototype
prototype is the template used when using new operator
The __proto__ comes from the constructor's prototype.
In the first case, One is your constructor. You haven't assigned anything to One.prototype, so it defaults to a Object's __proto__ and you get the two levels of inheritance.
If you had added things to that object, they would show up as part of the One prototype.
function One() {
this.x = 4;
this.y = 'hhh';
}
One.prototype.z = 'foobar';
var one = new One();
In the second case, you are creating an object literal which has Object as it's prototype, so you only inherit from the Object prototype. Prototypes are objects themselves, so if you were to add properties to it, like so:
foo.__proto__.z = 'foobar';
You are modifying the instance of Object that is foo's prototype, it doesn't modify Object itself, only that particular instance of it. That is what the article means, by foo's prototype.
I just did a test in V8 and it seems an object literal doesn't have an instance of Object as it's prototype, it has Object's __proto__ itself, so you should not modify foo.__proto__, you would be modifying the underlying Object prototype that all Objects inherit from. If you do wish do modify it, you should create a new instance of Object first to add to:
foo.__proto__ = {};
foo.__proto__.z = 'foobar';
Example:
var x = {};
x.__proto__ = {};
x.__proto__.z = 'foobar';
var y = {};
y.z; // undefined
Object.z; // undefined
vs.
var x = {};
x.__proto__.z = 'foobar';
var y = {};
y.z; // 'foobar'
Object.z; // 'foobar'
In my opinion, it would be better if object literals automatically created a new instance of Object for their __proto__. Then again, there is no real reason in modifying the prototype of an object literal.
Also note that you should not use __proto__ directly, as it is deprecated, and its future replacement is strongly discouraged as well. You should use Object.create for implementing inheritance in Javascript.
There are two interrelated concepts with prototype in JavaScript:
First, there is a prototype property that every JavaScript function has (it is empty by default), and you attach properties and methods on this prototype property when you want to implement inheritance.Note that this prototype property is not enumerable: it is not accessible in a for/in loop. But Firefox, and most versions of Safari and Chrome, have a __ proto__ “pseudo” property (an alternative way) that allows you to access an object’s prototype property. You will likely never use this __ proto__ pseudo property, but know that it exists and it is simply a way to access an object’s prototype property in some browsers.
The prototype property is used primarily for inheritance: you add methods and properties on a function’s prototype property to make those methods and properties available to instances of that function.
The second concept with prototype in JavaScript is the prototype attribute. Think of the prototype attribute as a characteristic of the object; this characteristic tells us the object’s “parent”. In simple terms: An object’s prototype attribute points to the object’s “parent”—the object it inherited its properties from. The prototype attribute is normally referred to as the prototype object, and it is set automatically when you create a new object.To expound on this: Every object inherits properties from some other object, and it is this other object that is the object’s prototype attribute or “parent.” (You can think of the prototype attribute as the lineage or the parent). In the example code above, newObj‘s prototype is PrintStuff.prototype.

Javascript prototype behavior

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/

At what point is the prototype Object born in JavaScript?

Let's say I have a constructor function:
function Cat()
{
this.tail = "long";
this.colour = "black";
}
console.log(Cat.prototype);
// returns an empty [object Object] with no properties (checked with `for...in` loop).
So it seems at this point Cat.prototype doesn't havetail and colour.
var Charlie = new Cat();
console.log(Charlie.tail);
So how does Charlie inherit the properties of Cat if they are not defined in its prototype. I was under the assumption that the whole point of the prototype object is to mirror or store the properties of the constructor that will be inherited by all instances of cat- is this wrong?
At what point does the prototype Object get filled up with these properties? Or does this happen only when I explicitly set Cat.prototype.eyes = brown as an example?
Moreover, what is the correct approach for querying the properties of an Object's prototype? Is it a for...in loop? I guess it can't be Object.getOwnPropertyNames(Cat.prototype) because that would not return inherited properties.
You are defining the tail and colour properties directly on the instance. Those properties are not defined on the prototype object.
Btw, every function has a prototype property and it is created at the time when the function itself is created.
prototype is completely seperate from this.
All the things in this will not get inherited, the things in prototype will.
By default you inherit from Object.prototype (which is empty)
function Cat()
{
this.tail = "long";
this.colour = "black";
}
Cat.prototype.getColour = function () {
return this.colour;
}
WhiteCat.prototype = Cat.prototype;
WhiteCat.prototype.constructor = WhiteCat;
function WhiteCat(name){
Cat.call(this);
this.colour = "white";
}
var c = new Cat();
console.log(c.getColour()); // "black"
var w = new WhiteCat();
console.log(w.getColour()); // "white"
Prototypes in Javascript are a little different than what you are describing. In this case Charlie does have a tail because Charie IS A Cat that is, he is an instance of Cat the Cat class. In your Cat function you add the tail property to all cats with the this.tail = line. This happens entirely because you called the function Cat with the new keyword. When you do that, javascript creates a new object and then makes this point to that object in the context of the function.
Now prototypes work differently, they are best thought of as a chain that will be followed if a you go looking for a property or function that is not present in an object. For example, if try to go:
Charlie.tickle_wiskers();
Javascript will go looking for a function called tickle_wiskers in the charlie object. If it does not find that function it will look in Charlies prototype (which by default is Object.prototype if you don't set it explicitly). Finally I could give all Cats that function by going like this:
Cat.prototype.tickle_wiskers = function() {
alert('meow');
}
The prototype will never get the properties that you put in the object. The object has the members of the prototype, but the prototype doesn't have the members of the object.
The object doesn't inherit anything from the prototype, the members in the prototype still only exists in the prototype, they are only accessible from the object. If you remove something from the protype after an object is created, that member is no longer accessible from the object either.
A function has a prototype property, and when you use the new keyword to call the function as a constructor, the object that is created gets the prototype from the function.
If you add something to the prototype of a function, it will also be accessible by objects that were created using the function, even if you created them before adding it to the prototype:
function Cat() {}
var c = new Cat();
Cat.prototype.test = function() {
alert('test');
};
c.test(); // alerts 'test'
Moreover, what is the correct approach for querying the properties of an Object's prototype?
var myProto = Object.getPrototypeOf(someObject);
var names = Object.getOwnPropertyNames(myProto);
names.forEach(function (name) {
value = myProto[name];
...
});
Or does this happen only when I explicitly set Cat.prototype.eyes = brown as an example?
Yes, properties on the [[Prototype]] of an object are only set when you set them manually.
But since every "instance" of a prototype has a live pointer to the prototype object, these changes will reflect after the object has been created.
store the properties of the constructor that will be inherited by all instances of cat- is this wrong?
We don't store properties of objects on the prototype. We store properties (mainly methods) that we want to share among all instances of a prototype/constructor.

Categories

Resources