-
Notifications
You must be signed in to change notification settings - Fork 285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using __proto__
in object literals
#2901
Comments
Just reading through, it looks like they should be about the same. Also fwiw, modifying the prototype of an object right after you create it is not that bad. Modifying the prototype once the object has been passed around the codebase and such is what can cause slowdowns. |
FWIW:
Re your alternative, it's much less cumbersome to use const proto = /*...*/;
const obj = Object.assign(Object.create(proto), {
// Your properties here in the normal way, not as property descriptors
example: 42
});
console.log(obj.example); // 42 But, that won't work for accessor properties. On Twitter you asked if
and
and
but that same sentence continues with
and elsewhere in the note
So...hopefully that gives you some input into your decision whether to use Hope that helps! |
@tjcrowder fwiw we actually are working on moving things out of annex b, for example tc39/ecma262#2125 |
@devsnek - That's great news (in relation to this item), thanks!! I get leaving the accessor in Annex B, but I've really wanted |
Just for refs: Node.js lib uses some |
@devsnek From what I understood from the discussion in the linked issue, moving stuff out of annex b does not mean un-deprecating it, just making it easier available in the spec document (especially grammar productions). And I agree with @ljharb, |
To be clear; I’m not advocating for deprecating proto support in object literals; the discussion there is about the legacy ways to define getters and setters. It would break tons of code if node ever removed it, and i doubt there’s a huge performance impact any more from using 5-10 year old syntax. |
On a side-note, there are other considerations around Also note that at the moment, and after consulting with experts for the same performance considerations raised here, Rollup uses |
@lukastaegert note that that’s about removing the accessor property on Object.protoype, the syntax in object literals has no security issues and i don’t think anyone has attempted to remove it. |
A naive benchmark for creating and using an object with Code'use strict';
let sum = 0;
{
const label = 'warm up'.padEnd(25);
let counter = 100000;
console.time(label);
while (counter--) {
const object = { a1: 1, a2: 1, a3: 1, a4: 1, a5: 1 };
sum += object.a1 + object.a2 + object.a3 + object.a4 + object.a5;
}
console.timeEnd(label);
}
{
const label = '{ __proto__ }'.padEnd(25);
let counter = 100000;
console.time(label);
while (counter--) {
const object = { __proto__: null, b1: 1, b2: 1, b3: 1, b4: 1, b5: 1 };
sum += object.b1 + object.b2 + object.b3 + object.b4 + object.b5;
}
console.timeEnd(label);
}
{
const label = 'setPrototypeOf'.padEnd(25);
let counter = 100000;
console.time(label);
while (counter--) {
const object = Object.setPrototypeOf({ c1: 1, c2: 1, c3: 1, c4: 1, c5: 1 }, null);
sum += object.c1 + object.c2 + object.c3 + object.c4 + object.c5;
}
console.timeEnd(label);
}
{
const label = 'create + add'.padEnd(25);
let counter = 100000;
console.time(label);
while (counter--) {
const object = Object.create(null);
object.d1 = 1, object.d2 = 1, object.d3 = 1, object.d4 = 1, object.d5 = 1;
sum += object.d1 + object.d2 + object.d3 + object.d4 + object.d5;
}
console.timeEnd(label);
}
{
const label = 'create + assign'.padEnd(25);
let counter = 100000;
console.time(label);
while (counter--) {
const object = Object.assign(Object.create(null), { e1: 1, e2: 1, e3: 1, e4: 1, e5: 1 });
sum += object.e1 + object.e2 + object.e3 + object.e4 + object.e5;
}
console.timeEnd(label);
}
{
const label = 'create with descriptors'.padEnd(25);
let counter = 100000;
console.time(label);
while (counter--) {
const object = Object.create(
null,
{
f1: { value: 1, configurable: true, enumerable: true, writable: true },
f2: { value: 1, configurable: true, enumerable: true, writable: true },
f3: { value: 1, configurable: true, enumerable: true, writable: true },
f4: { value: 1, configurable: true, enumerable: true, writable: true },
f5: { value: 1, configurable: true, enumerable: true, writable: true },
},
);
sum += object.f1 + object.f2 + object.f3 + object.f4 + object.f5;
}
console.timeEnd(label);
}
console.assert(sum === 100000 * 5 * 6); Output:
|
If I am not mistaken, using
Object.setPrototypeOf()
and__proto__
to change object prototype is considered deprecated as a "very slow operation". Also, IIRC, this can degrade the performance of objects in V8.Also, it is usually not recommended to add properties to an object after creation as it can degrade the performance of objects in V8 as well (if I understand correctly explanations like this).
So, if I need to create an object with defined prototype AND properties, I have two options:
Object.create()
with both prototype and property descriptors arguments set. This is rather cumbersome way.Object literal with
__proto__
and properties.So the questions: are these two options equal with regard to performance? Or is the second way is just syntactical sugar for the same postponed
Object.setPrototypeOf()
operation internally? Has the second way any drawbacks? Are these drawbacks implementation-dependent or common (spec-dependent?)?(cc maybe @bmeurer?)
The text was updated successfully, but these errors were encountered: