Let's say I have the following code;
var A = {a:10};
var B = {b:20};
B.prototype = A;
alert(B.a);
I am getting undefined for B.a .
Am I doing something wrong? How do I set the prototype for object literal ?
I know how to do for Constructor object. So the following code works perfect
function A(){this.a=10}
function B(){this.b=20}
B.prototype = new A();
b = new B;
alert(b.a);
How do I do it for object literal ?
Objects inherit from their constructor's prototype property, not their own. The constructor's prototype is assigned to the internal [[Prototype]] property that is available in some browsers as the __proto__ property.
So for b to inherit from a, you need to put a on b's inheritance chain, e.g.
Classic prototype inheritance:
var a = {a: 'a'};
function B(){}
B.prototype = a;
var b = new B();
alert(b.a); // a
Using ES5 Object.create:
var a = {a: 'a'};
var b = Object.create(a);
alert(b.a); // a
Using Mozilla __proto__:
var a = {a: 'a'};
var b = {};
b.__proto__ = a;
alert(b.a); // a
The prototype property is usually present in a Function object. This prototype should be an object, and this object is used to define the properties of an object created with a constructor.
// Plain object, no prototype property here.
var plainObject = {one: 1, two: 2};
// Constructor, a prototype property will be created by default
var someConstruct = function() {
// Constructor property
someConstruct.constructProp = "Some value";
// Constructor's prototype method
someConstruct.prototype.hello = function() {
return "Hello world!";
}
};
// Another constructor's prototype method
someConstruct.prototype.usefulMethod = function() {
return "Useful string";
}
var someInstance = new someConstruct();
console.log(someInstance.hello()); // => Hello world!
console.log(someInstance.usefulMethod()); // => Useful string
console.log(someConstruct.constructProp); // => Some value
console.log(someConstruct.prototype); // => {usefulMethod: function, hello: function}
console.log(plainObject.prototype); // => undefined
So, plain objects have no prototypes.
Functions which work as constructors do have prototypes. These prototypes are used to fill an instance created with each construct.
Hope that helps :)
Only when using Function object that prototype is used, e.g. when you use a constructor. But no need of that for object literals.
Both of them are very good techniques, so it depends on what you want to do in a project and the JavaScript pattern you are using or like.
Related
function classA(){};
classA.prototype.age =25;
var obj = new classA();
console.log(obj.age) //returns 25
Now, when I do:
classA.prototype = {};
Why obj.age is still returning 25?
This is happening because you pointed the classA.prototype to a new object but you didn't change the object that obj.prototype points to.
What is happening is:
classA.prototype ------> A
// create object with new classA()
// now its prototype also points to A
obj.prototype ------> A // points to the same prototype
now you reasign the prototype of classA
classA.prototype ------> B
but the prototype of obj still points to A (it was never changed)
obj.prototype ------> A
So all you did was change the prototype reference of classA after the prototype reference for obj was already established.
If you want to have obj see the changes on the prototype, then change the object it references (A in the example above) and not the reference itself:
Sample code:
function classA(){};
classA.prototype.age =25;
var obj = new classA();
console.log(obj.age) // 25
// change the object itself, not the reference
delete classA.prototype.age;
console.log(obj.age); // undefined
If your code is in the following order:
function classA(){};
classA.prototype.age = 25;
classA.prototype = {};
var obj = new classA();
console.log(obj.age) // returns undefined
The result will be indeed your excepted behavior. It depends on when you set the prototype of the classA function. This will be demonstrated by the following code snippet:
function classA(){};
classA.prototype.age = 25;
var obj1 = new classA();
classA.prototype = {};
var obj2 = new classA();
console.log(obj1.age) // returns 25
console.log(obj2.age) // returns undefined
Hence, a object is only affected by the changes to a prototype of a function, when this happens before the object's creation.
reassigning your prototype after creating the object has no effect on the previously created object , it will still have the old prototype when it was created. New prototye will only effect newly created objects
What I currently have is an object, say b, that inherits an other object, say a. In object a I have an object as property(value). To clear things up:
var a = (function(){});
a.prototype.value = {
val : "value a"
};
var b = (function(){
this.value.val = "b";
alert("object b: " + this.value.val);
});
b.prototype = Object.create(a.prototype);
b.prototype.constructor = a;
new b(); // alerts "object b: b"
http://jsfiddle.net/qqmtb846/
So far, so good. In object b I set the 'val' property of the 'value' object to another value. As expected the value is set(value is now 'b').
When I create another object, lets say c, I would expect that I get the original value('value a').
This is not the case. I'm sure this is due object reference.
var a = (function(){});
a.prototype.value = {
val : "value a"
};
var b = (function(){
this.value.val = "b";
alert("object b: " + this.value.val);
});
var c = (function(){
alert("object c: " + this.value.val);
});
b.prototype = Object.create(a.prototype);
b.prototype.constructor = a;
c.prototype = Object.create(a.prototype);
c.prototype.constructor = a;
var ObjectB = new b(); // alerts "object b: b"
var ObjectC = new c(); // alerts "object c: b", I want that "object b: value a" is displayed
http://jsfiddle.net/eb6dsgv9/1/
I want to use an object as property in the super class because most of the values will be the same, but sometimes they have to change. There is still a referance despite it's a new instance.
1) Is this some kind of design weakness of JavaScript?
2) How can I resolve this?
This is expected behavior. In your constructor, this.value refers to the same object as a.prototype.value. You can overwrite this.value with a new value (which will leave a.prototype and its properties unchanged), but if you modify this.value.val you are modifying the val property of a.prototype.value.
I don't know what you mean by "design weakness" so I can't answer (1). This is simply the way JavaScript's prototypal inheritance works.
As for how to resolve it, I think you need to show us a more concrete example, as I don't think there's a simple one-size-fits-all solution to this. It could be resolved by using a deep copy instead of Object.create (though depending on how you do the deep copy you could lose any methods on the prototype, if it has any). To put it simply, if you need to modify the properties of the prototype's properties, you are going to run into a situation like this.
Probably a better solution is to have a separate set of data values for each instance. Having all your instances share the same set of data values is creating a mess in your situation.
Initialize the properties in a's constructor:
var a = function () {
this.value = {
val: "value a"
};
};
And then you can call that constructor from b and c's constructor:
var b = function () {
b.prototype.constructor.call(this);
this.value.val = "b";
console.log("object b: " + this.value.val);
};
var c = function () {
c.prototype.constructor.call(this);
console.log("object c: " + this.value.val);
};
http://jsfiddle.net/eb6dsgv9/6/
To add to JLRishe answer, you can make it work this way:
http://jsfiddle.net/eb6dsgv9/3/
var a = (function(){
this.value = {
val : "value a"
}
});
var b = (function(){
a.call(this);
this.value.val = "b";
alert("object b: " + this.value.val);
});
var c = (function(){
a.call(this);
alert("object c: " + this.value.val);
});
var ObjectB = new b();
var ObjectC = new c();
Here, 'value' is property of 'a', not a.prototype. In 'a' and 'c' constructors you create new, separate 'a', so you get a fresh 'value a' each time. The downside of it is you spend more memory for all 'a' instances.
I based my answer on this: Javascript property inheritance
Object.create(a.prototype) creates a brand new object with it's [prototype] pointing to a.prototype.
Your new ObjectB and ObjectC are brand new objects with their [prototype] pointing to c.prototype resp. b.prototype which is
your above new empty object with [prototype] pointing to a.prototype.
In your b constructor you try set the property value.val to "b" but ObjectB does not have such a property value. javascript than looks into b prototype which is again
empty object but has the link in it's [prototype] to another object which is a.prototype. that object has property value so it is set value.val = "b" .
In case of ObjectC the linking is the same, the only difference is that you are looking for property value. Javascript looks in every objects in the [prototype] chain until it finds the value property which is in your a.prototype object.
It is not design weakness of javascript it is it's strength actually. javascript is not OOP language.
I have a problem I can't solved because I can't explain this behaviour :
var A = function(value) {
this.prop = value;
};
A.prototype = {
prop: 0
};
var a = new A(1);
var b = new A(2);
console.log(a.prop);
console.log(b.prop);
output :
1
2
But, with this code (almost the same) :
var A = function(value) {
this.prop.value = value;
};
A.prototype = {
prop: {
value: 0
}
};
var a = new A(1);
var b = new A(2);
console.log(a.prop.value);
console.log(b.prop.value);
I have this output :
2
2
Can anybody explain me this ?
Thanks...
EDIT :
Here's a solution :
var A = function(value) {
this.prop = {};
this.prop.value = value;
};
A.prototype = {
};
var a = new A(1);
var b = new A(2);
console.log(a.prop.value);
console.log(b.prop.value);
In example 1, this.prop is a primitive type, which is referenced by value and thus not shared between instances.
In example 2, this.prop is an Object whose reference is initialized from the prototype from a single object, so this single object is shared by all instances.
In the last "example" solution, you create a new object with = {}, so all instances now have their own object.
More details about primitive types : Primitive value vs Reference value
prototype is created only once and it's only a simple object whose childs are attached for all instances of a function it belongs to.
So it's basically the same as if you write:
var obj = { value: 0 };
var a = {}, b = {};
a.obj = obj;
b.obj = obj;
obj.value = 2;
as you can see both a.obj and b.obj references to the same obj and both a.obj.value and b.obj.value will be 2 in this example
This is happening because in JS, objects are passed by reference, while primitives are not.
Since the prototype is shared between the 2 instances, modifying a object on it will update all instances.
Think of a prototype property as a property shared amongst all instances.
Yet you can override it on each instance, that 's what you do in the first example.
Once overriden in each instance, you do not access any more to the prototype property with obj.prop, which now refers to the instance property. You would need to use obj.prototype.prop to read it again, but this syntax is illegal : you can use obj.__proto__.prop (non standard) or Object.getPrototypeOf(obj).prop (EcmaScript 5) to do so.
In the second instance, you do not change the property in the constructor : rather you change a property of this property. So both constructor access to the very same object, then change one of its property value, so the last to set it will 'win'. Here the prototype property is not overriden ('hidden') by the instance property and accessing obj.prop in fact access 'obj.prototype.prop'.
How Object.getPrototypeOf(obj) works?
As per definition Object.getPrototypeOf(obj) should return prototype property of an Object or in another way it is same as obj.constructor.prototype.
Objects created with new use the value of the prototype property of their constructor function as their prototype.
Lets take an example:
>element = document.getElementById("test")
>a = Object.getPrototypeOf(element)
HTMLDivElement
Let's say HTMLDivElement is the prototype of element.
>a.constructor.prototype
HTMLDivElement
so a.constructor.prototype is HTMLDivElement so Object.getPrototypeOf(a) should return HTMLDivElement but it returns HTMLElement. I am totally confused with definition of getPrototypeOf().
>b = Object.getPrototypeOf(a)
HTMLElement ----> why? a.constructor.prototype is HTMLDivElement
Actually it's returning proto property of prototype, isn't it wrong as per definition of getPrototypeOf()?
>a.constructor.prototype.__proto__
HTMLElement
quote from https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Inheritance_Revisited
JavaScript is a bit confusing for developers coming from Java or C++,
as it's all dynamic, all runtime, and it has no classes at all. It's
all just instances (objects). Even the "classes" we simulate are just
a function object.
NOTE that prototype is also AN OBJECT, so it ALSO CAN HAVE IT'S OWN UNIQUE PROTOTYPE
so code that make you confuse look like this
a = Object.getPrototypeOf(element)
b = Object.getPrototypeOf(a)
can be translated to this
a = element.__proto__
b = element.__ptoto__.__proto__
I think it's now clear that a != b
1) Every object in JavaScript has a prototype, you can access it through the __proto__ property
2) Function is also an object in Javascript
3) Functions also have a prototype property
4) We can create objects in JavaScript by calling function with keyword new
4) Function prototype is the initial __proto__ for any objects created by them
To create new object we can write something like this
//here we define a function
function SomeFunctionThatCreateObject() {
this.someStringProperty = "blablabla";
}
var obj = new SomeFunctionThatCreateObject(); //we create new object with function
var p = Object.getPrototypeOf(obj);
this code is equal to this
var SomeFunctionThatCreateObject = function(#this) {
#this.someStringProperty = "blablabla";
return #this;
};
SomeFunctionThatCreateObject.prototype = {}; //note that prototype is also an object
var obj = {};
obj = SomeFunctionThatCreateObject(obj);
obj.constructor = SomeFunctionThatCreateObject;
obj.__proto__ = SomeFunctionThatCreateObject.prototype;
var p = obj.__proto__;
PS: also read this
https://stackoverflow.com/a/9220317/474290
and this
https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Inheritance_Revisited
var elem = document.getElementsByTagName("div")[0],
a = Object.getPrototypeOf ( elem );
console.log( elem.__proto__ ); //HTMLDivElement
console.log( a ); // HTMLDivElement
console.log( a.__proto__ ); //HTMLElement
console.log( Object.getPrototypeOf ( a ) ); //HTMLElement
so Object.getPrototypeOf return object.__proto__ ( object.constructor.prototype )
I understand that there are two ways of creating classes in JavaScript
var MyObj = function(val)
{
this.vari = val;
}
Where val will be a non static member.
Whereas,
var MyObj = new Object();
MyObj.vari = "";
This is a single object so members of it here will act like static members. My question is that how do we have both static as well as non static content in same class?
There are no classes in JavaScript, only objects.
When you create a new object you are "extending" from the function's prototype, not the function itself. In order to make a variable or function appear to be static you would have to attach it to the function used to create the object, and not its prototype.
js> var Foo = function(){ this.member = "member"; };
js> Foo.staticMember = "staticMember";
js> var f = new Foo();
js> Foo.member;
undefined
js> Foo.staticMember;
"staticMember"
js> f.member;
"member"
js> f.staticMember;
undefined
Using your first example:
var MyObj = function(val) {
this.vari = val;
};
MyObj.var2=value;
Will create a new "static" property callable as:
var o = MyObj.var2;
The first one initializes the MyObj variable with the anonymous function - it does not create the class. The MyObj may be later used as the object constructor that initializes one object field - vari. There is nothing "statis" in OOP meaning.
The second one creates the object of the Object type and initializes its property. Again, there is nothing static.
In OOP "statis" means the member of the class, e.g. variables and objects that belong to class definition. For example, the following schema demonstrates this concept:
function MyClass() {
this.objectProperty = "I'm object property";
// the following demonstrates initialization of
// the object property from class (static) property:
this.varFromStatic = MyClass.classProperty;
}
MyClass.classProperty = "I'm class (static) property";
var obj = new MyClass();
// now obj.varFromStatic contains "I'm class (static) property"