xdevel2000
xdevel2000

Reputation: 21444

value of this in the prototype inheritance

If I have:

var Shape = function()
{ 
    this.toString_ = function() { alert(this.UL)}
}

Shape.prototype.UL = "<UL></UL>"

var _2D = function() { this.name = "_2D"}

_2D.prototype = new Shape()

var i = new _2D()

i.toString_()

when I call i.toString_() the JS engine tries to find if i have the toString_ function and not finding it, goes into _2D.prototype (a Shape instance) and it finds the function.

Here is the this referring to the Shape instance?

Then it executes the function and it finds in the alert this.UL now not finding it it goes to the Shape.prototype that has that property...

Now who is this?

Can someone explain me the value of this in the inheritance chain?

Does it start with i... and end with Shape.prototype?

Confused!

Upvotes: 2

Views: 231

Answers (2)

James Hugard
James Hugard

Reputation: 3236

Prototype inheritance in JavaScript works like this.

Every Function object has a property called "prototype". When an object is created using "new", the runtime allocates an empty object and sets its "prototype" property to the same value as the constructor function's "prototype" property. Standard JS has no way to update this blank object's prototype afterwards. Properties can then be added or removed from this object, either in the constructor function or later. The default value is:

MyFunction.prototype = Object.prototype

Whenever a property is accessed with "this.[property]", the runtime first looks to see if the "this" object created above has the property. If not found, then the runtime looks on "this.prototype", then "this.prototype.prototype", etc. until Object.prototype is checked. Failing to find it there will return "undefined" as the property value.

obj -> obj.prototype -> obj.prototype.prototype -> Object.prototype

For example,

var myPrototype = { prop : "ABC" }
function MyConstructor()
{
}
MyConstructor.prototype = myPrototype
var o = new MyConstructor()
alert( o.prop )

In the above, when resolving "o.prop", the runtime first looks on "o" for a property called "prop". Failing to find it on "o", the runtime looks on "myPrototype". Finding it there, the value "ABC" is returned.

Note that the "this" reference always refers to the object created above (e.g., "o"). So, if you were to assign a value to a property on the prototype using "this", the runtime will actually create a new property of that name and put it on the object referenced with "this" rather than updating the value in the prototype, thus "shadowing" the original value. In order to modify the prototype's value, one would need to directly reference the prototype object, either via "this.prototype." or via a different reference to that object, say "thePrototypeObject.[property]", assuming you had a variable assigned to the prototype object.

o.prop = "DEF"
alert( o.prop )
alert( myPrototype.prop )

In this case, the assignment statement creates a new property called "prop" on "o". So, the first alert prints "DEF", whereas the second prints "ABC".

var o = new MyConstructor()
myPrototype.prop = "DEF"
alert( o.prop )
alert( myPrototype.prop )

In this case, the original prototype's "prop" property is updated, so both will print the same value ("ABC").

In your example above,

var Shape = function()
{ 
    this.toString_ = function() { alert(this.UL)}
}
Shape.prototype.UL = "<UL></UL>"
var _2D = function() { this.name = "_2D"}
_2D.prototype = new Shape()
var i = new _2D()

i.toString_()

The prototype chain looks like the following:

Shape.prototype -> Object.prototype

Object.prototype.UL = "<UL></UL>"

_2D.prototype -> (new Shape) -> Object.prototype

i.prototype -> (new Shape) -> Object.prototype

So, when resolving "toString_()", the runtime examines first "i" and, failing to find it there, looks on the (new Shape) object. Finding it there, it calls "toString_()" passing "i" as "this". When resolving "this.UL", the runtime first looks on "i", then (new Shape), then on "Object.prototype", finally returning the value it finds there.

Upvotes: 2

Ionuț G. Stan
Ionuț G. Stan

Reputation: 179219

Just add:

alert(this instanceof Shape);
alert(this instanceof _2D);

in the toString_ method and you'll see which this you have.

Upvotes: 1

Related Questions