o.prototype = {...} is working only if o is a Function. Suppose I've the following Code
conf = {
a: 2,
b: 4
};
conf.prototype = {
d: 16
}
conf.a and conf.b is OK and returns proper values. But conf.d doesn't return 16 rather it goes undefined. Is there any solution suck that prototype based generalization can also be applied on these type of Objects.
You are confusing the prototype
property that can be used on Constructor Functions and the internal [[Prototype]]
property.
All objects have this internal [[Prototype]]
property, and only the new
operator when you call it with a constructor function is allowed to set it (through the [[Construct]]
internal operation).
If you want to have prototypal inheritance with object instances (without using constructors), the Crockford's Object.create
technique is what you want (that method is now part of the recently approved ECMAScript 5th Edition):
// Check if native implementation available
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {} // empty constructor
F.prototype = o; // set base object as prototype
return new F(); // return empty object with right [[Prototype]]
};
}
var confProto = {
d: 16
};
var conf = Object.create(confProto);
conf.a = 2;
conf.b = 4;
In the above code conf
will have its three members, but only a
and b
will exists physically on it:
conf.hasOwnProperty('a'); // true
conf.hasOwnProperty('b'); // true
conf.hasOwnProperty('d'); // false
Because d
exists on the conf [[Prototype]]
(confProto
).
The property accessors, .
and []
are responsible to resolve the properties looking up if necessary in the prototype chain (through the [[Get]]
internal method).
There are actually two different kind of "prototype" in JavaScript:
[[Prototype]]
to represent this hidden link). object literals by default have their hidden links pointing to Object.prototype
, function objects have their hidden link pointing to Function.prototype
, and arrays have theirs pointing to Array.prototype
. These hidden prototype links are not related to properties with name "prototype". You can't change these hidden links by adding or modifying o.prototype
.prototype
". This is mainly for the usage of constructor invocation pattern.[[Prototype]]
is used for searching properties (like the parent in classical hierarchy), whenever a property cannot be found in an object, its [[Prototype]]
is searched instead. One usage scenario: say you'd like to add a property to all objects, you could simply add it to Object.prototype
which would automatically apply to all objects since all objects somehow have Object.prototype
as their [[Prototype]]
chain root.
Lets get back to function objects' "prototype
" property. It is only useful when used with operator new
. Take the following code snippet as an example:
function F() {} // function declaration
// F now has a property named "prototype"
var f = new F(); // use "new" operator to create a new function object based on F
What new F()
does above is to first create a new function object, set the [[Prototype]]
(hidden link) of this newly created function object to be F.prototype
, and then return the new function object. This is probably what you already understand that works for function objects.
Remember that I said we can't change objects's [[Prototype]]
? Well, at least not directly. Crockford's Object.create
function does just that, by utilizing the fact that operator new
could help set [[Prototype]]
for us. So by using Object.create
, you get to deliberately indicate where your new object's hidden link should point to. (somewhat feel like indicating who is your parent class)
In your example, conf
is an object literal and conf.prototype
isn't really useful. Here's another version utilizing classical style:
function ConfBase() {}
ConfBase.prototype.d = 16;
var conf = new ConfBase();
conf.a = 2;
conf.b = 4;
document.writeln(conf.a);
document.writeln(conf.b);
document.writeln(conf.d);
Compared to the answer of @CMS, I do prefer using Object.create
. But essentially the 2 styles are using the same underlying mechanism, just that Object.create
helps tidy it up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With