I've been looking into doing inheritance in JavaScript the correct prototypal way, according to Douglas Crockford: http://javascript.crockford.com/prototypal.html
He writes: "So instead of creating classes, you make prototype objects, and then use the object function to make new instances"
I figured this was the way to do it:
var objA = {
func_a : function() {
alert('A');
}
};
var objB = Object.create(objA);
objB.func_a = function() {
alert('B');
}
objB.func_b = function() {
};
var objA_instance1 = Object.create(objA);
var objA_instance2 = Object.create(objA);
var objB_instance1 = Object.create(objB);
var objB_instance2 = Object.create(objB);
etc...
But wouldn't this mean that there are now four instances of func_a (since it's isn't part of objA.prototype, it's just "inside" it), or am I not understanding this correctly?
Also, is there any way I can reach the overridden function of a function (for example call objA.func_a inside objB.func_a)?
Thanks in advance.
There is only one instance of func_a, and it is defined on objA, that is because the Crockford's Object.create method uses that object (objA) simply as the prototype of your new objects:
console.log(objA_instance1.func_a == objA .func_a); // true
console.log(objA_instance2.func_a == objA .func_a); // true
func_a on your objA_instances are reached by the prototype chain, that objects don't really own that property:
console.log(objA_instance1.hasOwnProperty('func_a')); // false
console.log(objA_instance2.hasOwnProperty('func_a')); // false
You're confusing the prototype property of constructor functions with the internal [[Prototype]] property of objects, which is inaccessible (FF makes it available as __proto__); using Object.create() sets this internal property to its argument, so objA and objB will be the actual prototypes of your 'instance' objects, ie no function objects will be duplicated.
To call the overridden functions, access them via eg objA.func_a and use call() or apply() to use them on the specific instances, eg
objB.func_a = function() {
objA.func_a.call(this); // call overridden method with current `this`
};
Related
Trying to understand Prototypes in Javascript. For this example:
var obj = new Function();
obj.prototype.x = "a";
Why do I get different results from
console.log(obj.__proto__);
and
console.log(obj.prototype);
Thanks
In:
> var obj = new Function();
a new function object is created whose internal [[Prototype]] (or __proto__ in browsers that support it) references Function.prototype, i.e. the built–in Function constructor's public prototype and assigned to the variable obj.
Because obj is a Function object, it has a prototype property by default just in case it is to be used as a constructor.
In:
> obj.prototype.x = "a";
a new x property is added to obj.prototype that is assigned a value of the string 'a'. Note that obj only has a prototype property by default because it's a Function object.
So:
obj.prototype === obj.__proto__
is essentially:
obj.prototype === Function.prototype
which is clearly false.
So to answer the question "Best way to retrieve the prototype of a JS object" then you can access a constructor's public prototype through its prototype property.
You can access a instance's internal [[Prototype]] using ES5 Object.getPrototypeOf, however it may not be supported everywhere.
You can also access a instance's internal [[Prototype]] using the non–standard __proto__ where supported.
A more general solution is to keep a reference to the constructor's prototype at the time the instance is created (since changing the constructor's prototype at some later stage will not change the [[Prototype]] of instances that have already been created).
So in a general case you might do:
function Foo() {
this.internalProto = Foo.prototype;
}
var foo = new Foo();
// ES5, where supported
Object.getPrototypeof(foo) == Foo.prototype; // true
foo.internalProto == Foo.prototype; // true
// Non–standard, Where supported
foo.internalProto == foo.__proto__; // true
According to this source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
Object.prototype.__proto__ points to the object which was used as
prototype when the object was instantiated.
It simply means that object used as prototype to create Function object was empty function, and that's why you have function Empty() {} in the output. You can observe it here:
console.log(Function.prototype);
var func = new Function();
console.log(func.__proto__);
console.log(func.prototype);
// OUTPUT:
// function Empty() {}
// function Empty() {}
// Object {}
__proto__ of an empty object (e.g. var a = {}) is Object {} because this is, what was used to create base of your object (in other words Object.prototype was used). And prototype is not even available as a property of a, because you've created a totally empty object, so there's nothing.
Also notice that __proto__ is now deprecated.
Why? I don't know, but I have never used it so I don't care :)
prototype is a different thing, e.g.
Changes to the Object prototype object are propagated to all objects
unless the properties and methods subject to those changes are
overridden further along the prototype chain.
This is why you need prototype and you don't care about __proto__ in real life. If I'm wrong please show me useful usage of __proto__.
Hope it's clearer now. And to answer your original question:
Prototype of a JS object can be retrieved only by using prototype property, as __proto__ contains sth different. If prototype property doesn't exist, there is no prototype of the JS object, even if sth was used in the process of instantiation.
Accordint to the MDN, obj.__proto__ has not been standardized.
So while obj.prototype has a clear standardized behav8our accross browsers, obj.__proto__ behaves differently in different browsers.
You're looking at this sideways...
.prototype and .__proto__ are the same object (or are at one specific point in time)...
BUUUUUT they're propertes of different objects.
var Human = function (name) {
this.num_eyes = 2;
this.num_heads = 1;
this.name = name;
};
Human.prototype.die = function () { this.isAlive = false; };
var herman = new Human("Herman");
herman.__proto__.die === Human.prototype.die; // true
.__proto__ is a link to the CONSTRUCTOR .prototype (and typically, is the SAME object)
It's almost like this:
var Human = function () {
this = {};
this.num_eyes = 2;
// ......
this.__proto__ = Human.prototype;
};
That isn't exactly how constructors work, but really, that's the idea.
And that's why .__proto__ and .prototype aren't the same thing.
Because you're looking in the wrong place.
So if:
var herman = new Human();
herman.__proto__ === Human.prototype;
var Human = new Function ();
...so logic then states that Human.__proto__ === Function.prototype;
...and if Human and Function aren't the same object, then their .prototype properties aren't going to be the same (unless you overwrite one with the other Human.prototype = Function.prototype; Human.__proto__ === Human.prototype; //true
Constructor1=function(){};
Constructor1.prototype.function1=function this_function()
{
// Suppose this function was called by the lines after this code block
// this_function - this function
// this - the object that this function was called from, i.e. object1
// ??? - the prototype that this function is in, i.e. Constructor1.prototype
}
Constructor2=function(){};
Constructor2.prototype=Object.create(Constructor1.prototype);
Constructor2.prototype.constructor=Constructor2;
object1=new Constructor2();
object1.function1();
How do I retrieve the last reference (indicated by ???) without knowing the name of the constructor?
For instance, say I had an object which inherits from a chain of prototypes. Can I know which prototype is used when I call a method on it?
Both seem theoretically possible, but I can't find any way that works without more than constant number of assignment statements (if I have many such functions).
The prototype of each function has a reference back to the function via the constructor property [MDN]. So you can get the constructor function via
var Constr = this.constructor;
Getting the prototype is a bit trickier. In browsers supporting ECMAScript 5, you can use Object.getPrototypeOf [MDN]:
var proto = Object.getPrototypeOf(this);
In older browser it might be possible to get it via the non-standard __proto__ [MDN] property:
var proto = this.__proto__;
Can I know which prototype is used when I call a method on it?
Yes, if the browser supports ES5. Then you have to repeatedly call Object.getPrototypeOf() until you find the object with that property. For example:
function get_prototype_containing(object, property) {
do {
if(object.hasOwnProperty(property)) {
break;
}
object = Object.getPrototypeOf(object);
}
while(object.constructor !== window.Object);
// `object` is the prototype that contains `property`
return object;
}
// somewhere else
var proto = get_prototype_containing(this, 'function1');
Can someone explain this?
function Foo() {
this.x = 1;
this.y = 2;
}
function FooProto() {
this.arrow = 1;
this.bow = 1;
}
document.writeln(Foo.prototype); // [object Object]
document.writeln(Foo.prototype.constructor); // function Foo() { x =1; y=2; }
My understanding here is: Foo.prototype is an Object whose constructor property is Function Foo. Foo.[[Prototype]] is Function.Prototype
obj = new Foo;
document.writeln(obj.constructor); // function Foo() { x =1; y=2; }
document.writeln(obj.constructor.prototype); // [object Object]
Foo.prototype = FooProto;
document.writeln(Foo.prototype); // function FooProto() { arrow = 1; bow = 2; }
document.writeln(Foo.prototype.constructor); // function Function() { [native code] }
Question 1: How did the look up using [[Prototype]] happen here. I would appreciate if someone can explain this to me.
document.writeln(obj.constructor); // function Foo() { x =1; y=2; } .. no change
document.writeln(obj.constructor.prototype); // function FooProto() { arrow = 1; bow = 2; }
anotherObj = new Foo;
document.writeln(anotherObj.constructor); // function Function() { [native code] }
document.writeln(anotherObj.constructor.prototype); // function Empty() {}
Question 2: Same question as Question 1. How did the Javascript interpreter perform the lookup?
When explaining prototype-based code, it is much simpler to use Object.create to explain stuff. Object.create is a function that receives a prototype object and creates a new instance object that has the prototype object as its [[prototype]]
When looking up properties in an object is work like this:
Every object has its own and immutable [[prototype]] property inside. This property is secret and hidden, unless you are in Firefox, where you can get it via __proto__.
When reading a property up we first search for it in the object itself and if we don't find it there we recursively search for the object's [[prototype]].
When writing a property we always write an own-property (we never mutate the [[prototype]], even if it also has the property we are setting).
proto = {a:1};
child1 = Object.create(proto);
child2 = Object.create(proto);
child1.a = 2;
console.log(proto.a); //1
console.log(child1.a); //2
console.log(child2.a); //1
When creating a function
Whenever we create a function object in Javascript, it comes with a prototype property already filled in. This prototype is an object (inheriting from Object.prototype) and has the constructor property set to the corresponding function.
When instantiating an object using a function constructor (new Foo)
A new object is created with the functions prototype as its [[prototype]] and the function is run o the object to initialize it.
I don´t really want to explain what is going on in the first case, since the
Foo.prototype = FooProto; part doesn't really make sense and is probably not what you wanted to do (remember that prototypes should be objects, not functions)
As for the second case, changing the prototype property of the constructor function will only affect the future instances (anotherObj). The [[prototype]] property of the already created objects is secret and immutable so there is nothing you can do to change them.
Note that if you want to dynamically change the prototype and existing objects (monkey-patching) you can do that by writing and overwriting values in the existing prototype object instead of replacing it with a new one.
There're two concepts of prototype in Javascript. (I take it as a name collision in language design.)
The prototype in the "prototype chain".
It is a inside property as mentioned in the last answer. The prefered way to access it is Object.getPrototypeOf.
var a = {};
Object.getPrototypeOf(a); // Object {}
Object.getPrototypeOf(Object.getPrototypeOf(a)); // null, the top of prototype chain.
Object.getOwnPropertyNames(Object.getPrototypeOf(a)); // the methods inherited
Every constructor (I think acutally every function declared) has a own property "prototype". It come to use in the new operator.
The new operator does 2 steps.
First is to create an object whose prototype (the 1st one, saying, [[Prototype]]) is assigned as the constructor's prototype (the 2nd one).
Second is to run the constructor (looking up from prototype.constructor) with taking the created object as implicit argument this.
Now to your case:
The first obj was created with its property [[Prototype]] (proto in some engines) assigned as Foo.prototype.
obj.constructor === obj.__proto__.constructor === Foo.prototype.constructor === Foo
obj.constructor.prototype === Function.prototype
Note that the constructor is also a Function object.
Then you changed the prototype of Foo. This changed the obj.constructor.prototype but not obj.constructor which has a different reference. The anotherObj had a new [[Prototype]] from the following new operator.
This question has been here for years. Following readers may be also confused as me. I recommendated the newly published book Speaking JavaScript from Dr. Axel Rauschmayer :
Terminology: The Two Prototypes
I am just learning Javascript and I was wondering, is using the prototype declaration, like this:
function TSomeObj()
{
this.name="my object";
}
TSomeObj.prototype.showname = function() {
alert(this.name);
}
Basically the same as doing it like this:
function TSomeObj()
{
this.name="my object";
this.showname = function() {
alert(this.name);
}
}
When I dump the object's properties I get the same result:
TSomeObj (inline version) =
{
'name': 'my object',
'test': function
}
TSomeObj (prototype declaration) =
{
'name': 'my object',
'test': function
}
What exactly is the benefit of using prototype declarations? Except less cluttering and more orderly sourcecode perhaps.
Update: I should perhaps have made it more clear that it was the final result i was curious about. The end result is ofcourse the same (i.e both register a new function in the object prototype) - but the way they do it is wildly different. Thank you for all replies and info!
Note: This answer is accurate but does not fully reflect the new way to create classes in JavaScript using the ES6 class Thing {} syntax. Everything here does in fact apply to ES6 classes, but might take some translation.
I initially answered the wrong question. Here is the answer to your actually-asked question. I'll leave my other notes in just in case they're helpful to someone.
Adding properties to an object in the constructor function through this.prop is different from doing so outside through Object.prototype.prop.
The most important difference is that when you add a property to the prototype of a function and instantiate a new object from it, that property is accessed in the new object by stepping up the inheritance chain rather than it being directly on the object.
var baseobj = {};
function ObjType1() {
this.prop = 2;
}
function ObjType2() {}
ObjType1.prototype = baseobj;
ObjType2.prototype = baseobj; // these now have the *same* prototype object.
ObjType1.prototype.prop = 1;
// identical to `baseobj.prop = 1` -- we're modifying the prototype
var a = new ObjType1(),
b = new ObjType2();
//a.hasOwnProperty('prop') : true
//b.hasOwnProperty('prop') : false -- it has no local property "prop"
//a: { prop = 2 }, b : { prop = 1 } -- b's "prop" comes from the inheritance chain
baseobj.prop = 3;
//b's value changed because we changed the prototype
//a: { prop = 2 }, b : { prop = 3 }
delete a.prop;
//a is now reflecting the prototype's "prop" instead of its own:
//a: { prop = 3 }, b : { prop = 3 }
A second difference is that adding properties to a prototype occurs once when that code executes, but adding properties to the object inside the constructor occurs each time a new object is created. This means using the prototype performs better and uses less memory, because no new storage is required until you set that same property on the leaf/proximate object.
Another difference is that internally-added functions have access to private variables and functions (those declared in the constructor with var, const, or let), and prototype-based or externally-added functions do not, simply because they have the wrong scope:
function Obj(initialx, initialy) {
var x = initialx,
y = initialy;
this.getX = function() {
return x;
}
var twoX = function() { // mostly identical to `function twoX() { ... }`
return x * 2;
}
this.getTwoX = function() {
return twoX();
}
}
Obj.prototype.getY = function() {
return y; // fails, even if you try `this.y`
}
Obj.prototype.twoY = function() {
return y * 2; // fails
}
Obj.prototype.getTwoY = function() {
return twoY(); // fails
}
var obj = new Obj();
// obj.y : fails, you can't access "y", it is internal
// obj.twoX() : fails, you can't access "twoX", it is internal
// obj.getTwoX() : works, it is "public" but has access to the twoX function
General notes about JavaScript objects, functions, and inheritance
All non-string and non-scalar variables in JavaScript are objects. (And some primitive types undergo boxing when a method is used on them such as true.toString() or 1.2.valueOf()). They all act somewhat like a hash/dictionary in that they have an unlimited(?) number of key/value pairs that can be assigned to them. The current list of primitives in JavaScript is: string, number, bigint, boolean, undefined, symbol, null.
Each object has an inheritance chain of "prototypes" that go all the way up to the base object. When you access a property of an object, if that property doesn't exist on the object itself, then the secret prototype of that object is checked, and if not present then that object's prototype, so on and so forth all the way up. Some browsers expose this prototype through the property __proto__. The more modern way to get the prototype of an object is Object.getPrototypeOf(obj). Regular objects don't have a prototype property because this property is for functions, to store the object that will be the prototype of any new objects created using that function as their constructor.
A JavaScript function is a special case of an object, that in addition to having the key/value pairs of an object also has parameters and a series of statements that are executed in order.
Every time a function object is invoked it is paired with another object that is accessed from within the function by the keyword this. Usually, the this object is the one that the function is a property of. For example, ''.replace() boxes the string literal to a String, then inside the replace function, this refers to that object. another example is when a function is attached to a DOM element (perhaps an onclick function on a button), then this refers to the DOM element. You can manually choose the paired this object dynamically using apply or call.
When a JavaScript function is invoked with the new keyword as in var obj = new Obj(), this causes a special thing to happen. If you don't specifically return anything, then instead of obj now containing the return value of the Obj function, it contains the this object that was paired with the function at invocation time, which will be a new empty object with the first parent in its inheritance chain set to Obj.prototype. The invoked Obj() function, while running, can modify the properties of the new object. Then that object is returned.
You don't have to worry much about the keyword constructor, just suffice it to say that obj.constructor points to the Obj function (so you can find the thing that created it), but you'll probably not need to use this for most things.
Back to your question. To understand the difference between modifying the properties of an object from within the constructor and modifying its prototype, try this:
var baseobj = {prop1: 'x'};
function TSomeObj() {
this.prop2 = 'y';
};
TSomeObj.prototype = baseobj;
var a = new TSomeObj();
//now dump the properties of `a`
a.prop1 = 'z';
baseobj.prop1 = 'w';
baseobj.prop2 = 'q';
//dump properties of `a` again
delete a.prop1;
//dump properties of `a` again
You'll see that setting a.prop1 is actually creating a new property of the proximate object, but it doesn't overwrite the base object's prop1. When you remove prop1 from a then you get the inherited prop1 that we changed. Also, even though we added prop2 after a was created, a still has that property. This is because javascript uses prototype inheritance rather than classic inheritance. When you modify the prototype of TSomeObj you also modify all its previously-instantiated objects because they are actively inheriting from it.
When you instantiate a class in any programing language, the new object takes on the properties of its "constructor" class (which we usually think of as synonymous with the object). And in most programming languages, you can't change the properties or methods of the class or the instantiated object, except by stopping your program and changing the class declaration.
Javascript, though, lets you modify the properties of objects and "classes" at run-time, and all instantiated objects of that type class are also modified unless they have their own properties that override the modification. Objects can beget objects which can beget objects, so this works in a chain all the way up to the base Object class. I put "classes" in quotes because there really isn't such a thing as a class in JavaScript (even in ES6, it's mostly syntactic sugar), except that the new keyword lets you make new objects with the inheritance chain hooked up for you, so we call them classes even though they're just the result of constructor functions being called with the new keyword.
Some other notes: functions have a Function constructor, objects have an Object constructor. The prototype of the Function constructor is (surprise, surprise) Object.
Inheriting from an object without the constructor function running
In some cases, it's useful to be able to create a new "instance of an object" without the constructor function running. You can inherit from a class without running the class's constructor function like so (almost like manually doing child.__proto__ = parent):
function inheritFrom(Class) {
function F() {};
F.prototype = Class.prototype;
return new F();
}
A better way to do this now is Object.setPrototypeOf().
The accepted answer missed the most important distinctions between prototypes and methods bound to a specific object, so I'm going to clarify
Prototype'd functions are only ever declared once. Functions attached using
this.method = function(){}
are redeclared again and again whenever you create an instance of the class. Prototypes are, thus, generally the preferred way to attach functions to a class since they use less memory since every instance of that class uses the same functions. As Erik pointed out, however, functions attached using prototypes vs attached to a specific object have a different scope, so prototypes don't have access to "private" variables defined in a function constructor.
As for what a prototype actually is, since it's an odd concept coming from traditional OO languages:
Whenever you create a new instance of a function:
var obj = new Foo();
the following logic is run (not literally this code, but something similar):
var inheritsFrom = Foo,
objectInstance = {};
objectInstance.__proto__ = inheritsFrom.prototype;
inheritsFrom.apply( objectInstance, arguments );
return objectInstance;
so:
A new object is created, {}, to represent the new instance of the function
The prototype of the function is copied to __proto__ of the new object. Note that this is a copy-by-reference, so Foo.prototype and objectInstance.__proto__ now refer to the same object and changes made in one can be seen in the other immediately.
The function is called with this new object being set as this in the function
and whenever you try to access a function or property, e.g.: obj.bar(), the following logic gets run:
if( obj.hasOwnProperty('bar') ) {
// use obj.bar
} else if( obj.__proto__ ){
var proto = obj.__proto__;
while(proto){
if( proto.hasOwnProperty('bar') ){
// use proto.bar;
}
proto = proto.__proto__;
}
}
in other words, the following are checked:
obj.bar
obj.__proto__.bar
obj.__proto__.__proto__.bar
obj.__proto__.__proto__.__proto__.bar
... etc
until __proto__ eventually equals null because you've reached the end of the prototype chain.
Many browsers actually expose __proto__ now, so you can inspect it in Firebug or the Console in Chrome/Safari. IE doesn't expose it (and may very well have a different name for the same thing internally).
How do you determine the difference between new Object and new fn under these conditions?
var fn = function(){};
fn.prototype = {};
You may not rely on __proto__ or Object.getPrototypeOf existing, as they are not in IE or Opera.
The solution may not statically use fn, such as instanceof fn.
Implementing your own Object.getPrototypeOf is fine.
Not required: It would be nice if your solution works with objects from other frames and doesn't use function serialization.
Here's some example base code to start off with:
var fn = function(){};
fn.prototype = {};
var x = new fn,
y = new Object;
fn = null; // prohibit static reference to fn
// define your detection function here
function isNewObject(obj) {
};
alert(isNewObject(x) !== isNewObject(y) ? "pass" : "fail");
I'm pretty sure you can't do this in ES3 with only standard support, and here's why:
Look at x and y creation.
var fn = function(){};
fn.prototype = {};
var x = new fn,
y = new Object;
When x is instantiated, its internal [[Prototype]] is being set to an object referenced by fn.prototype (just an Object object that you assigned to fn.prototype). Object's constructor - fn - is then being called in a context of that newly created object, but since it doesn't mutate ab object in any way, we can consider that step irrelevant.
When y is instantiated, its internal [[Prototype]] is being set to Object.prototype, which is an Object object too. Its constructor (Object) is then being called in a context of this newly created object as well, but nothing happens there either.
So now you end up with 2 Object objects which only differ in that their internal [[Prototype]]'s reference different objects - x's one references whatever you assigned to fn.prototype and y's references Object.prototype. Their internal [[Class]] properties are identical too (i.e. equal to "Object")
You can't get direct access to [[Prototype]] in ES3. You can infer something about it by using instanceof, but since fn is nulled in your example intanceof-based inference is out of the picture.
Now, you can augment Object constructor in such way that it would somehow mutate instantiated object. You can then inspect an object and detect this augmentation. For example:
Object = function() {
return ({ __: void 0 });
}
and then:
function isNewObject(object) {
return '__' in object;
}
but this will, of course, only work when object is being created with new Object and not via, say, an object literal - { }. It's also rather obtrusive :)
Perhaps there are other ways, but I can't see them right now.
HTH
As far as I know your problem is impossible to solve with ES3: instanceof and isPrototypeOf() can't be used to solve it because the prototype object of fn is inaccessible, and only ES5 allows access to the internal [[Prototype]] property via Object.getPrototypeOf().
Btw, an even harder problem to solve would be if you assign Object.prototype to fn.prototype, eg
var x = (function() {
function Foo() {}
Foo.prototype = Object.prototype;
return new Foo;
})();
As the prototype chain of Foo and Object instances is identical, there shouldn't be any way to distinguish them.