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 )
Related
function Product(name, price) {
this.name = name;
this.price = price;
}
const p1 = new Product('Pen', 20);
const p2 = Object.create(p1);
console.log(p1.constructor.prototype === p1.__proto__); // true
console.log(p2.constructor.prototype === p2.__proto__); // false
My understanding was these two are always equal (as in the first console.log statement).
But, while doing some tweaks I found this surprising result (second console.log statement).
Can someone please clear up my understanding about the relationship between prototype and __proto__. Thanks in advance!
This only works for instances created using new from constructors that follow the standard prototype pattern. These objects will inherit from the constructors .prototype object, which has a .constructor property pointing back to the constructor. This means when accessing the inherited .constructor, we can find the prototype object that we're inheriting on it.
However, it doesn't work for arbitrary objects that have their own .constructor property (e.g. {constructor: null}) or for objects that don't inherit directly from a constructor's prototype object, such as your p2.
To clarify what's happening in your code without using new:
const Product = Object.create(Function.prototype);
Product.prototype = Object.create(Object.prototype);
Product.prototype.constructor = Product;
const p1 = Object.create(Product.prototype);
p1.name = "Pen";
p1.price = 20;
console.assert(Product.prototype == Object.getPrototypeOf(p1));
console.assert(!p1.hasOwnProperty("constructor") && p1.constructor == Product);
console.assert(p1.constructor.prototype == Product.prototype);
console.assert(p1.constructor.prototype == Object.getPrototypeOf(p1));
const p2 = Object.create(p1);
console.assert(p1 == Object.getPrototypeOf(p2));
console.assert(!p2.hasOwnProperty("constructor") && p2.constructor == p1.constructor);
Sorry for noob question. I'm just learning JavaScript.
I have an easy Object.
var bike = {
wheels: 2,
};
I create a new one that inherits all the bike values via create() and add some new properties to new Object.
var raleigh = Object.create(bike);
raleigh.color = 'red';
When I do console.log on new raleigh Object I can't see propeties inherited from bike Object.
console.log(raleigh);
The log is:
{ color: 'red' }
How to log to console all properties including these inherited?
When an object is printed through console.log, it is printed with all its own properties and a link to the object it inherits from. You can see all the inherited properties in console, you just need to follow the prototype chain of the displayed object (typically using __proto__ or [[prototype]] keys).
When you use Object.create then your prototype will be the same the object that you are inheriting, so, to show "father" properties you could see the prototype:
console.log(raleigh);
console.log(Object.getPrototypeOf(raleigh));
Maybe you will expect something more but I think that is the fast way to show that properties.
Would this help?
I'm throwing an alert, u can check the console as well!
var bike = {
wheels: 2,
};
var raleigh = Object.create(bike);
raleigh.color = 'red';
function getAllProperties( obj ) {
var properties = [];
do {
properties= properties.concat(Object.getOwnPropertyNames( obj ));
} while ( obj = Object.getPrototypeOf( obj ) );
return properties;
}
alert(getAllProperties(raleigh));
console.log(getAllProperties(raleigh));
You could create a new Object especially for your log which has everything as own properties
function flatten_inheritance(e) {
var o = Object.create(null), i, prop;
do {
prop = Object.getOwnPropertyNames(e);
for (i = 0; i < prop.length; ++i)
if (!(prop[i] in o))
o[prop[i]] = e[prop[i]];
} while (e = Object.getPrototypeOf(e));
return o;
}
flatten_inheritance(raleigh); // Object {color: "red", wheels: 2, valueOf, toString, etc..}
If you want to stop at Object.prototype or some other prototype you can do this in the while condition for example;
while (e = Object.getPrototypeOf(e) && e !== Object.prototype);
I would recommend you only do this when debugging rather than moving all your code away from inheritance though
Ok guys I've been messing about with prototypes for a while now and am not ready to give up on their usefulness just yet... despite heavy criticism!
I'm battling the age old problem of Object.prototype property inheritance in other objects such as arrays & strings. ie:
Object.defineProperty(
Object.prototype, 'jsf',
{get:function(){
return JSON.stringify(this);
}};
);
x = {abc: 123};
y = document.createElement('div');
If you're reading this page, and you are!, then you will know that because both x & y are objects, based on typeof x or y, both x & y will inherit the jsf property, ergo:
x.jsf = {"abc": 123}
y.jsf = Uncaught TypeError: Converting circular structure to JSON
Now I know there are various work-rounds like:
Object.defineProperty(y, 'jsf', {value: void 0});
And my favorite:
function Master_Object(){ this.jsf = JSON.stringify(this) }
function Master_Element(){ this.str = this.outerHTML }
Object.defineProperty(
Object.prototype, 'ms',
{get:function(){
cons=this.constructor.name;
if(cons=='Object') return new Master_Object();
else if(cons=='HTMLDivElement') return new Master_Element();
}}
);
Where every object only has 1 manageable custom property, .ms, and that property is an object containing properties specific to the objects constructor, thus:
x.ms.jsf = {"abc": 123}
y.ms.jsf = undefined
y.ms.str = <div></div>
x.ms.str = undefined
Favorite or not I don't want to have to type the prefix .ms, it's untidy and frankly in the way!
I've been playing with custom elements and I know about the life-cycle callbacks, and how they track the progression of an element...
var proto = Object.create(HTMLElement.prototype);
proto.createdCallback = function() {...};
proto.attachedCallback = function() {...};
var XFoo = document.registerElement('x-foo', {prototype: proto});
Thing is I can't seem to translate these callbacks to be used on an object scope as opposed to an element scope?!
It would save me a lot of hassle if I could just write something along these lines:
Object.defineProperty(
Object.prototype, 'createdCallback',
{value: function(){
var Proto_Clone = Object.create(Object.prototype);
var cons = this.constructor.name;
if(cons == 'Object'){
Object.defineProperty(Proto_Clone,'...',{value:...});
}
else if (cons == ...) ...;
this.prototype = Proto_Clone;
}}
);
The idea being that when an object is instantiated, a check is performed on it to ascertain it's constructor and if the said constructor is Object then it's prototype is changed to the modified Proto_Clone before it is parsed.
That way the original Object.prototype is never modified and there is no leakage of properties from one object to the next...???!!!
So what do YOU think ? Is it possible, and if so how?
You could use try/catch:
Object.defineProperty(
Object.prototype, 'jsf',
{get:function(){
try {
return JSON.stringify(this);
} catch (e) {
return undefined;
}
}};
);
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.
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"