I have this piece of code:
var MyConstructor = function(){};
var MyObject = new MyConstructor();
What I noticed is MyObject.constructor is not pointing to MyConstructor. So what is the standard way of accessing the constructor of an object from the object itself?
I need this to access constructor's prototype properties like MyConstructor.prototype = {mykey : "value"}. I can access mykey this way: MyConstructor.prototype.mykey but MyObject.constructor.prototype.mykey is not defined.
Here is the complete code and their output using jsconsole.com:
var MyConstructor = function(){};
MyConstructor.prototype = {mykey : "value"};
var MyObject = new MyConstructor();
MyObject.mykey; // output: "value"
MyConstructor.prototype.mykey; // output: "value"
MyObject.constructor.prototype.mykey; // output: undefined
MyObject.constructor === MyConstructor; // output: false
MyObject.constructor.prototype.mykey === "value"; // output: false
This happens because you change the prototype property of MyConstructor. That means that MyObject is created from that object and does not get the constructor property that the original prototype object had. So in your test case, MyObject.constructor === Object, since that is the constructor that is used for the object literal {mykey: "value"}.
To avoid this behaviour, don't assign a new object to the prototype property, but mutate the existing one:
var MyConstructor = function(){};
MyConstructor.prototype.mykey = "value";
var MyObject = new MyConstructor();
console.log(
MyObject.mykey, // output: "value"
MyConstructor.prototype.mykey, // output: "value"
MyObject.constructor.prototype.mykey, // output: "value"
MyObject.constructor === MyConstructor, // output: true
MyObject.constructor.prototype.mykey === "value", // output: true
);
Object.getPrototypeOf(MyObject).mykey gets the prototype directly from MyObject.
Mozilla developer link
Related
var triangle = { a: 1, b: 2, c: 3 };
function ColoredTriangle() {
this.color = 'red';
}
ColoredTriangle.prototype = triangle;
var obj = new ColoredTriangle();
console.log(obj.constructor.name, obj);
//result: Object ColoredTriangle {color: "red"}
I use chrome browser.
Here, var obj = new ColoredTriangle(); using this, you are creating a new object of function ColoredTriangle().
Hence, in your console result, ColoredTriangle {color: "red"} shows the content of the obj that you are printing. You can see it also shows function properties.
obj is instance of the constructor ColoredTriangle. So the obj.constructor will be the function object which is ColoredTriangle. .name will get the name of that function.
According to MDN about Function.prototype.name
A Function object's read-only name property indicates the function's name as specified when it was created, or "anonymous" for functions created anonymously
See the example below.
Note: The name property is only specific for the function objects. I will not work for other datatypes.
function foo(){}
let instance = new foo();
console.log(instance.constructor); //function foo(){}
console.log(foo.name) //foo
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
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'.
var myObject = new Object();
var myObjectCopy = myObject;
myObject.Name = 'alav';
// logs Name alav on both variable
console.log(myObject, myObjectCopy);
myObject = null;
// logs myObject as null and myObjectCopy still has name 'alav' -> bcoz of reference copy
console.log(myObject, myObjectCopy);
The same behavior is not getting replicated below.
var objA = {property: 'value'};
var pointer1 = objA;
// update the objA.property, and all references (pointer1 & pointer2) are updated
objA.property = pointer1.property;
objA.property= null;
// logs 'null null' because objA, pointer1 all reference the same object
console.log(objA.property, pointer1.property);
Why the above reference copy behavior is not applicable to inner properties(property here) of an object?
objA.property = pointer1.property; -> aren't reference COPY?
In case one you were setting reference to null therefore no change in actual object
myObject = null;// setting reference to null object , but no change in actual object
In second case you are making changes into the object(changing state of object)
by setting property to null
objA.property = null;
hence in every reference , value of property will be null
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.