This question is more about support and backwards compatibility. I have tested the following code.
function newFunc() {}
newFunc.prototype = {
literal : {
init : function() {
console.log(this);
this.test();
},
test : function() {
console.log('test');
}
}
}
var inst = new newFunc();
inst.literal.init();
This works, though I've not seen object literals as prototypes in any other code. Is there a reason for this? This seems like a logical way of coding to me though I don't want to pursue it if it has serious pitfalls.
It's perfectly normal to use an object literal to create the prototype for a function, but normally only as the actual value of the prototype
object.
What's unusual is doing what you've done and include a nested object within the prototype.
In effect you've only added one object to the prototype, the one named literal
. All of the methods are then properties of that object. It's technically valid syntax, but I've never seen it used before. As @squint points out in the comments, it also appears to break the way that the this
variable works, because it binds this
to the "next left" property that was used in the function call:
var inst = new newFunc();
inst.literal.init();
> Object { init: function, test: function }
i.e. this
has been set to point at the .literal
object, and not at the actual instance that has been created.
Yes, using literals for prototype
is correct. For example Mozilla explicitly uses a literal in the prototype's documentation:
var Customer = function(name) {
this.name = name;
}
var Person = { // this is a literal
canTalk : true,
greet : function() { /* ... */ }
}
Customer.prototype = Person;
Some explanation: Value of prototype
is an object. It doesn't matter how the object was created - using simply {}
is fine. It is often initialized using something like MyClass1.prototype = new MyClass2()
, but new
just creates a new object. It also sets the prototype
property and executes the constructor (MyClass2
) but on the new object, it doesn't affect MyClass1
in any way (see explanation here).
Using a nested literal doesn't make a difference. In the question, the prototype is set to { literal : { ... } }
. What actually happens when you call inst.literal.init()
is:
inst
and checks whether the object has a value assigned for property literal
.inst
dos not have such property, therefore the runtime continues with its prototype
propertyinst.prototype
references the literal object to which it was initialized. This object has assigned a value for property literal
.inst.literal
therefore evaluates to the nested literal inst.prototype.literal
init
init()
function is calledThis is one of the principles of JavaScript (ECMA Script) so there should be no compatibility issues.
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