views:

85

answers:

3

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 try to find if i has toString_ function and not finding it goes into _2D.prototype (a Shape instance) and it found the function.

Here is the this referred to the Shape instance?

then it executes the function and it find 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!

A: 

This article explains everything: http://www.alistapart.com/articles/getoutbindingsituations

carnz
+1  A: 

Just add:

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

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

Ionuț G. Stan
+2  A: 

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.

James Hugard
only a note:MyFunction.prototype = Object.prototype give false and if I do:while(p = My.prototype) p = p.prototypehere I have an infinite loop but withwhile(m = m.__proto__) m = m.__proto__it end when m is null
xdevel2000