Today morning I came across a tweet from Šime Vidas where he presented the following possibility of using super
in object literals:
let A = {
run() {
console.log('A runs');
}
};
let B = {
run() {
super.run();
}
};
Object.setPrototypeOf(B, A);
B.run(); // A runs
This works, and assigning B.__proto__ = A;
instead seems to work as well, both in Firefox and Chrome.
So I figured I could do the same with Object.create
:
let A = {
run() {
console.log('A runs');
}
};
let B = Object.create(A);
B.run = function() { super.run() };
Unfortunately, this results in an error in both Firefox:
SyntaxError: use of super property accesses only valid within methods or eval code within methods
And Chrome:
Uncaught SyntaxError: 'super' keyword unexpected here
The same happens when I try to pass a property descriptor object to the second argument of Object.create
.
Semantically, they both seem equal to me, so I'm not quite sure what is happening (is it because of the object literal?).
Now I'm wondering, is this standard behaviour that is exactly defined (spec reference appreciated)? Are there some implementations missing for Object.create
, or should object literals not work in the first place?
Object. assign() provides shallow copying (Only properties and methods) and it will override the method and property declared. while Object. create() provides Deep copying provides prototype chain.
The super keyword in JavaScript acts as a reference variable to the parent class. It is mainly used when we want to access a variable, method, or constructor in the base class from the derived class.
The Object. create() method creates a new object, using an existing object as the prototype of the newly created object.
prototype while Object. create(null) doesn't inherit from anything and thus has no properties at all. In other words: A javascript object inherits from Object by default, unless you explicitly create it with null as its prototype, like: Object. create(null) .
Allen Wirfs-Brock, the editor of the ES2015 spec, was kind enough to answer my question on twitter.
Why is this an error?
super property references can only occurs in “concise methods” within a class def or obj lit http://tc39.github.io/ecma262/#sec-function-definitions-static-semantics-early-errors
In that section of the spec, Static Semantics: Early Errors, there are four points that seem to be relevant:
So, super properties calls are neither allowed in function parameters, nor in regular function bodies. Thus my problem.
Why is it necessary to use a method definition?
the reason is that
super
requires a back link from the method to its containing object. http://tc39.github.io/ecma262/#sec-runtime-semantics-definemethod
Meaning, if I have a super call in a method, and I assign that method to another variable, it still has to work:
let B = {
run() {
super.run();
},
walk() {
console.log(typeof this.run);
}
};
var run = B.run;
run(); // the 'super' binding still works, thanks to the internal MakeMethod
var walk = B.walk;
walk(); // 'undefined': the 'this' binding on the other hand is lost, as usual
This is specified in step 7 of the section defining the method semantics, which currently does not happen for regular assignments to an object:
Could these semantics change in the future?
The back link is essential. Ways to dynamically set it were considered and could be again. Left out b/c error prone
So it would be possible that something like .toMethod
, which can set the object super
references to, could be introduced into the language after all, making my initial example with Object.create
possible.
I mean you can do this:
let A = {
run() {
console.log('A runs');
}
};
let B = {
run() {
super.run();
}
};
Object.setPrototypeOf(B, A);
let C = Object.create(B);
C.run(); //A runs
By the way, this also fails:
let A = {
run() {
console.log('A runs');
}
};
let B = {
run: function() {
super.run(); // 'super' keyword unexpected here
}
};
Object.setPrototypeOf(B, A);
B.run();
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