The below code is taken from http://bonsaiden.github.com/JavaScript-Garden/
function Foo() {
this.value = 42;
}
Foo.prototype = {
method: function() {}
};
function Bar() {}
// Set Bar's prototype to a new instance of Foo
Bar.prototype = new Foo();
Bar.prototype.foo = 'Hello World';
// Make sure to list Bar as the actual constructor
Bar.prototype.constructor = Bar;
I have come across this explanation multiple times
"When accessing the property of an object, first it checks if the object its self has that property and if not than it goes to the prototype of that object to look for the property and so on."
But I am struggling to understand ho this actually works because of the behavior of the following code
var test1 = new Bar();
var test2 = new Bar();
test1.value = 24;
now value is not part of the test1 object but it is a property of its prototype which is a Foo Object, and since the prototype is a Foo Object all instances of Bar will share the value property, What i expect the above code to do is to set that value property to 24 but instead it creates a new property named 'value' to the test1 object and assigns it 24 leaving the value property in the prototype to its initial value 42. well this doesn't sound like sharing. test2.value still has a value of 42. when i look at the prototype chain in the firebug console it shows me that test1 has a value property with 24 and its prototype has a value property with 42.
This is very confusing to. Has any one you figured out why it behaves this way ?
The prototype chain is only used when reading properties and only if the property is not found in the object itself - it's not used when writing property values.
As soon as you write a property into an object (test1.value = 24) any existing "shared" property in the prototype with the same name is hidden, and all subsequent reads will access the value now store in the object itself.
I think you want .hasOwnProperty()
If that is what you are looking for, someone else has eloquently summed it up here
hasOwnProperty in javascript
EDIT
Having read the other answer, then properly read the questions this time... I'd like to retract that ;-)
...
Or maybe it is what you are looking for, it you want to check whether the property had been set on the 'hash' before doing something else.
I've read this too many times and confused I think, I'll shut up now
Just append the following lines at the end to check what's going on.
var test1 = new Bar();
test1.value = 30;
console.log(test1.hasOwnProperty("value"));
console.log(test1.value);
delete test1.value;
console.log(test1.hasOwnProperty("value"));
console.log(test1.value);
Output:
true
30
false
42
Terms:
hasOwnProperty only returns true is key is the local property of the object.
delete is used to delete local property it does not touch inherited properties.
Explanantion
If we assign a value then it creates it's own local property and overrides the prototypal property. And thus, as local properties has higher preference than prototypal properties, they are read first.
Related
ECMAScript 5
has defined a very common factory pattern for construction and inheritance, called Object.create(). I am simply passing in the object to
inherit from, and getting back a new object all properly wired up.
Consider the snippet:
var a = {
phrase: "Hello",
say: function(){ alert(this.phrase); }
};
var b = Object.create(a);
Is my understanding correct as reflected below?
When b is first created, it has a prototype-inherited property called
phrase, meaning that the property is not on the instance (b.phrase),
but actually on the prototype (b.prototype.phrase). If I were to
read the value of b.phrase at that point, JavaScript would implicitly
look it up, find it on the prototype, and return it to me.
b.say(); // alerts Hello
However, when I make the assignment of a new value to b.phrase, I see it doesn’t affects the inherited
b.prototype.phrase but have instead set (overridden) an instance property b.phrase that takes precedence over the inherited
b.prototype.phrase on future property accesses. Why?
b.phrase = "World";
a.say(); // alerts Hello >> This hasn't changed. Why?
b.say(); // alerts World
This happens because of the prototype chain. JavaScript runtime looks for own object's properties first, and if nothing is found, it looks for the property on its prototype, and so on.
In the other hand, you're not overriding a property, but you are just adding one to the whole object and it hides the prototype's one, and again, this happens because of how prototype chain works.
This is the way javascript property lookup/assignment work. If you want to update prototype property, you can create object inside prototype object.
var proto = {
fields: {
phrase: 'Hello'
},
say: function () { console.log(this.fields.phrase) }
};
var a = Object.create(proto);
a.fields.phrase = 'World';
proto.say();
a.say();
So, what is going on here?
a.fields.phrase = 'World' is equal to
var tmp = a.fields;
tmp.phrase = 'World';
a.fields === a.__proto__.fields // true
That is why property was updated in prototype.
In your example you just assign value to object and js engine does what you want – assigns value "World" with key "phrase" to object a, nothing weird
More info about how objects work in js
First take this statement
var b = Object.create(a);
This statement creates a new object, newObj(for instance). Now following things happen:
b points to newObj.
newObj is linked to a's object via [[prototype]] reference.
Till now newObj does not have any methods or properties.
Take b.Say() -- b will point to newObj,so first it tries to check whether newObj has Say() method, it doesn't have so it tries to delegate via [[prototype]] chain. As newObj's [[prototype]] link points to a's object. It tries to check whether Say() is present in a's object.So it finds the method there & execute it with the context of newObj. It prints 'Hello'
Take b.Phrase='world'
Here you are assigning phrase property to newObj object (pointed by 'b'). So from next time if you are trying to do b.Phrase it will not traverse up the [[Prototype]] chain (i.e to a's object), instead it will find the value in newObj itself.
Final b.Say()
As newObj does not have Say() method, it will traverse up the [[prototype]] chain, finds the method, & executes it in the context of newObj. And as newObj has phrase property so this.phrase returns 'world'
consider a piece of code
function F(){
this.p=10;
}
F.prototype.newProp='some value';
var f1=new F(), f2=new F();
alert(f1.__proto__==f2.__proto__); //returns true. implies f1 and f2 share same instance of prototype object
f1.newProp='new value'; //changing the value of inherited property
alert(f2.newProp); //returns 'some value'
Ok now the question is if f1 and f2 both share the same [[prototype]] object instance
and if
property retrieval in javascript works by walking along the prototype chain
So if I change value of a property (newProp, in this case) of a shared [[prototype]] object,
how come its not reflected in f2 as well ,
since f1.proto==f2.proto (which means its the SAME object)
then why changing the newProp of f1 doesn't change newProp of f2 (both inherit from same prototype object, no ?)
Surprisingly,changing f1.proto.newProp reflects the change when retrieving "f1.newProp"
So , are f1.newProp and f1.proto.newProp different properties ?
I thought the property look up in javascript worked by successively looking higher in the prototype chain.
I am sorry if my question sounds naive, but I couldn't get my head around :
If 1) f1.proto==f2.proto //true! implies both objects f1 and f2 refer same [[prototype]] object from which they inherit
and if
2) property not found in object is searched in its prototype .
then why changing f1.newProp doesn't reflect in f2.newProp too ? as both have common [[prototype]] property as shown in point (1)
Is it that properties from prototype object are being copied individually into f1 and f2. ?
but then thats in violation of point (2) [looking up the properties of prototype chain when not not found in the object]
Please explain the contradiction here. thank u very much :)
==================EDIT================
thank you #jfriend00 for the reply.
but lets say I have this code
function Person(name, age){
this.name=name;
this.age=age;
alert("obj created:"+name);
}
function Employee(name,age,eid){
this.base=Person;
this.base(name,age);
this.eid=eid;
}
Employee.prototype=new Person;
var ob1=new Employee('name1',23,100);
var ob2=new Employee('name2',24,101);
here too, obviously ob1.proto==ob2.proto
but if I am not mistaken there's 2 objects here for each instance of employee
1 is the employee object itself with only 1 property eid (and other one base func)
2nd is the Person object which is referenced by the [[prototype]] property of employee object. This object has name and age property..
So , employee obj actually stores and retrieves name and age from its [[prototype]] Person object.
Am I right ?
If so , and since ob1.proto==ob2.proto, then how are we able to store unique name and age of both objects ?
I mean, here it almost seems there's a prototype object for each employee.
if u could explain this, thank u very much :)
and one more query is :
how come the above code will work even if comment out the
Employee.prototype=new Person;
in the above line and thereby breaking the link between 2 objs. Inheritance still works just because I have declared Person function as a property of Employee and called Person from it .
how is this working
thank you :)
Once you set f1.newProp = 'new value', it no longer is setting newProp on the prototype, but on the f1 object itself. Try this, you will see:
var f1=new F(), f2=new F();
console.log(f1.hasOwnProperty('newProp')); // returns false, because it is from prototype
f1.newProp = 'new value';
console.log(f1.hasOwnProperty('newProp')); // returns true
The prototype object is shared among all objects (as you have shown).
But, when you assign to a property an the object, it doesn't change the prototype, the property goes on the object itself and because of the lookup order for resolving a property reference, the newly assigned property on the object itself is found before the one on the prototype so it becomes the active property.
When you reference a property on an object, there is a search order. First it looks for properties directly on the object. If no match is found, then it searches the prototype chain.
When you write to a property on the object, it never writes to the prototype unless you explicitly reference the prototype object, instead it puts a property directly on the object and that property then becomes the active one (essentially overriding what's on the prototype).
You can tell whether a property is on the object itself or on the prototype by using .hasOwnProperty(). That will return true only when the property is directly on the object.
So, in your code:
f1.newProp='new value'; //changing the value of inherited property
This adds a new property directly to the object (not on the prototype) and it essentially overrides what is on the prototype.
In general, data properties are usually set in the constructor to avoid any confusion about the two possible locations the property can reside and, if you're writing to them, there's really no advantage to having initially specified them on the prototype. Function properties (e.g. methods) are often set in the prototype because they generally aren't written to so it's more efficient to just have one shared prototype object that contains them that can be read from.
All the resources I have found, it says that if we use Javascript prototype pattern, that functions' prototype is shared between all the objects for that particular type.
that means the following;
function TestObj(){
}
TestObj.prototype = {
cVar: 15,
increase: function(){
this.cVar++;
}
};
var a = new TestObj();
var b = new TestObj();
a.increase();
console.log(a.cVar); // 16
console.log(b.cVar); // 15 ??
Now my question is, shouldn't the b.cVar be 16? why is it 15 then? And if it is 15 that means the TestObj with protype is not shared between objects.
Do you know??
Yes, an object's prototype is shared between instances of the object, but the this.cVar++ looks a little bit misleading.
I think its easier to explain if you rewrite
this.cVar++;
as
this.cVar = this.cVar + 1;
The important thing is that this refers to the object instance and not the prototype. So in this.cVar + 1 it'll check the object instance to see if it has a cVar property. The first time increase is called, it doesn't. So JavaScript will look up the prototype chain until it finds it. So it finds 15. However, when it does the actual assignment back to this.cVar, it sets the property on the object instance itself and not the prototype (a shadowing of sorts).
So in your example,
console.log(a.cVar); // returns property from `a` itself
console.log(b.cVar); // returns property from the prototype
We can show this by using hasOwnProperty:
console.log( a.hasOwnProperty( "cVar" ) ); // true
console.log( b.hasOwnProperty( "cVar" ) ); // false
Objects do, in fact, share the prototype with one another as your research has lead you to believe. However, as go-oleg eluded to, there is a concept of the prototype chain. The prototype chain has a couple of behaviors you have to understand.
When you try to access a property on an object, it recursively looks up the chain starting from the object and looks for the property, then returns the value (This is what happens in the case of a read/get action).
When you try to set the value on a property on an object, it doesn't bother to recurse up the chain to find the property in the chain. Instead, if it doesn't find one on the object, it just adds the property along with the value you set on the object itself. This effectively hides the property that is higher up the prototype chain (This is what happens in the case of a write/set action).
If you placed your value inside an object then tried to set the value however, it would recurse to the object reference in a read attempt and since you have a reference pointer to the object, you would be setting the value on the object directly which would have the outcome you were expecting:
function TestObj(){
}
TestObj.prototype = {
cVar: 15,
obj: { val: 5 },
increase: function(){
this.cVar++;
},
objInc: function() {
this.obj.val++;
}
};
var a = new TestObj();
var b = new TestObj();
a.increase();
console.log(a.cVar);
console.log(b.cVar);
b.objInc();
console.log(a.obj.val);
console.log(b.obj.val);
//output
//16
//15
//6
//6
Hopefully that distinction clears up the confusion.
To be clear, "a" is an object, "b" is another, separate, object.
You then call the increase function only on "a", not "b". Therefore, unless I'm off my rocker,
It would make sense that b.cVar = 15, since it was never incremented.
Your getting confused by the terminology, and TestObject a is the only TestObject that you call increase() on. So it makes sense that a = 16 and b = 16, since you never call b.increase().
... that functions' prototype is shared between all the objects for that particular type.
That doesn't mean that each time any TestObject calls increase() then every other TestObject and itself also increase their cVar. Your thinking of something similar to the way that an EventListener and EventDispatcher system is set up. That function's prototype shared between all the objects for that particular type means that each TestObject instance has the prototype you defined.
I'm currently setting up JavaScript classes by extending a function prototype with my object of functions / variables like so....
//class shorthand
var clss = function(args){
var c = function() {};
_.extend(c.prototype, args); //using underscore.js
return c;
};
//class definition
var ThisIsMyClass = clss({
varExample: 5,
test: function() {
console.log(this.varExample);
},
alter: function(){
this.varExample = 8;
}
});
//class initialisers
var hello = new ThisIsMyClass();
var hi = new ThisIsMyClass();
var ayup = new ThisIsMyClass();
My question is that everything resides inside the ThisIsMyClass.prototype and the functions can be called and the variables read, but when the values are changed, they then appear outside of the prototype for that object (and also remaining in the prototype with its original value)?
after running this code
//class initialisers
hello.varExample = 6;
hi.alter();
//look at object structure
console.log(hello);
console.log(ayup);
console.log(hi);
//trace the values
hello.test();
ayup.test();
hi.test();
The console looks like this
Is prototype just a reference to the structure, and then when any changes are made, it copies them to object itself?
When you read a property on an object, the interpreter first looks on the actual object itself for that property. If it finds it there, it returns that value. If it does not find the property on the actual object, then it looks on the prototype. If it finds the property on the prototype, it returns that value.
When you set a property on an object, it always sets the property on the actual object (not on the prototype). So, once you've set the property on an object, any reading of that property will come from the one you set on the actual object, not the one on the prototype. Setting a property directly onto the object essentially "hides" or "overrides" the value set on the prototype. You can think of the prototype as the default value for the property, but as soon as you set one on the object itself, the prototype value is no longer used.
function foo() {}
foo.prototype.greet = function() {
console.log("Hello");
}
var x = new foo();
x.greet(); // will log "Hello" - finds method on the prototype
// set new method - will set this property directly on the object itself
// overriding what was on the prototype
x.greet = function() {
console.log("Goodbye");
}
x.greet(); // will log "Goodbye" - finds method on the object
Demo: http://jsfiddle.net/jfriend00/h6akb/
In the implementation of a javascript object, the object has both a set of properties on the object itself and a reference to its prototype. When looking up a property, it is looked for first on the object itself. If it is not found there, then the interpreter gets the reference to the prototype and looks for the property on the prototype object. The prototype object itself is just yet another object, so the interpreter looks for the property directly on the prototype object and, if found returns it. If not found, it checks to see if the prototype object itself has a prototype and so on (allowing for an inheritance chain).
I am trying to understand the new word in javascript. The top answer here What is the 'new' keyword in JavaScript? recommends this article.
In that article, in the prototypes section, the author says:
In other words, obj.prototype is in general not the obj's {Prototype}.
What does this mean? I have a hazy understanding of prototype (object that begets other objects). I understand that javascript does not have classes in the way that C# and Java have classes. Is that what the sentence above is expressing?
I'm not sure that article is the best way to understand what's going on here - it's a great technical explanation, but perhaps not the best way to get an intuitive understanding.
Let's step back and work this through.
A quick look at property lookup
One way to understand prototypal inheritance is to think of it as way to say "if I don't have it, look over there".
Say you've got an object and try to access a property that doesn't exist, JS will return the value undefined:
var x = {};
x.foo //=> undefined
All objects inherit from Object.prototype, so look what happens if we modify it:
var x = {};
x.foo //=> undefined
Object.prototype.foo = 'hello there';
x.foo //=> 'hello there';
What happened? When we initially create x, JavaScript sets up an internal [[Prototype]] property that points to Object.prototype. Effectively, there is a lookup algorithm that looks something like (pseudo-code):
Lookup(obj, prop) =
if HasProperty(object, property)
return GetPropertyValue(object, property)
else if HasPrototype(object)
return Lookup(PrototypeOf(object), property)
else
return undefined
In other words, start with the initial object, check for the property, if it doesn't have it, follow the prototype chain to keep looking for it. If we hit the end of the prototype chain, the property must be undefined.
So what about the new operator?
The new operator gives us a way to:
dynamically set the prototype of an object to something other than Object.prototype
do some initialization stuff when we create an object
NOTE: in ES5, we also have Object.create which gives you 1, but not 2.
When you say new Foo(a, b), here's what happens:
we make a new object that has its internal [[Prototype]] set to Foo.prototype.
we run the function Foo (its just a normal function) with its context (think this) set to the new object we just made
we return the new object after the function finishes (actually, if the function explicitly returns a value, we just return that value, but most of the time, we won't be doing that).
But wait, where did Foo.prototype come from?
Let's see - run the following in the console:
function Foo() {}
typeof Foo.prototype //=> "object"
When we create a function in JS, it comes with an object attached to its prototype property. It's just an object, like any other, so you can manipulate it, set/delete properties, even completely overwrite it (which the mentioned article shows an example of).
For example:
function Foo() {}
Foo.prototype.answer = 42;
var foo1 = new Foo();
var foo2 = new Foo();
foo1.answer //=> 42
foo2.answer //=> 42
// If you want you can change foo2's answer
foo2.answer = 'something else';
// Foo.prototype is unchanged
Foo.prototype.answer //=> 42
foo1.answer //=> 42 (still getting its answer from the prototype)
foo2.answer //= 'something else'
Getting back to the original question
Continuing with the foo example from above, what the original article was referring to is that foo1 and foo2 don't have prototype properties set on them:
foo1.prototype //=> undefined
foo2.prototype //=> undefined
NOTE: there is a non-standard __proto__ property that many JS engines provide that will give you an object's prototype, and in ES5, you also have Object.getPrototypeOf to get access to a given object's prototype.
Relevant links:
MDN's page on the new operator.
MDN's page on "working with objects".
I understand that javascript does not have classes in the way that C# and Java have classes. Is that what the sentence above is expressing?
No. While true, it has nothing to do with that sentence.
In other words, obj.prototype is in general not the obj's {Prototype}.
What does this mean?
An object might have a {prototype} (usually referred to as [[prototype]]), which is the object from which it does inherit properties. You can access that via the Object.getPrototypeOf() function, it is not a "visible" property of the object but some "hidden field".
Also, some objects (especially function objects) do have a .prototype property, i.e. a public attribute with the literal name "prototype".
The sentence states that these two "prototypes" are different from each other.
The question you linked now explains how the new keyword relates these different "prototypes". When you call a constructor function with new, then a new instance is created. The instance does inherit (its [[prototype]] will be set to) the prototype object of the "class" (which is shared amongst all instances) and that is looked up via the .prototype property of the constructor function.
As an example, let's look at the ObjMaker function from the code there. The ObjMaker.prototype (property) is the base for all ObjMaker instances. However, Object.getPrototypeOf(ObjMaker) is the object from which all function objects inherit from ([[prototype]]), which is Function.prototype.
The sentence means that you can't access an object's prototype using obj.prototype. You can access it with obj.__proto__ or Object.getPrototypeOf(obj) though. Also see the question __proto__ Vs. prototype in JavaScript.
The article is a bit dated. What it means is that prototype is a property. A property of a function object to be precise. It provides a way to define a prototype for objects created with this function. E.g.:
function Foo() {}
Foo.prototype.myMethod = function() {};
var myFoo = new Foo();
myFoo is an object and it has a prototype that contains the method myMethod.
The prototype of myFoo is not myFoo.prototype. That doesn't even exist.