9

The MDN hints that using .setPrototypeOf() will have a bad influence on the future performance of your code.

I also read a few Questions about why changing the [[Prototype]] of an object will lower the performance. But none of the answers really explained whats going on in the background. So I wonder if this also applies for new Objects.

In particular I really like to do things like this:

var MyPrototype = {
    method1 : function(){...},
    method2 : function(){...},
    ...
};

var newObject = Object.setPrototypeOf({
    property : 1,
    property2 : 'text'                 
}, MyPrototype);

Unfortunately you can't do this with Object.create since it doesn't accept a plain object literal.

Does my use of setPrototypeOf also decrease the performance of the executing JS engine?

Amit
  • 45,440
  • 9
  • 78
  • 110
Jovan
  • 133
  • 8
  • var newObject = Object.create(MyPrototype, {"property1":{value:1},"property2":{value:'text'}}); – Data Sep 07 '15 at 19:02
  • 1
    I know that but I think the `Object.create()` properties object is too heavy for most cases. I'd prefer to just write the usual object literal. You can avoid a lot of complexity without the additional sub- objects with the `value` property. – Jovan Sep 07 '15 at 19:09
  • So you are familiar with [Why is mutating the *\[\[prototype\]\]* of an object bad for performance?](http://stackoverflow.com/q/23807805/1048572)? – Bergi Sep 07 '15 at 19:14
  • I totally agree, Object.create() is way too messy when adding props, especially when you define writable, enumerable, etc for each one. I really wanted to use Object.create() but have now decided to use the function constructor pattern with `new`, it's much easier. – Data Sep 07 '15 at 19:14
  • well I prefer this [https://github.com/TitanNanoDE/ApplicationFrame/blob/master/util/make.js] over the `new` statement since it provides a way better way to maintain a good prototype chain. The only issue is the performance impact of `setPrototypeOf` – Jovan Sep 07 '15 at 19:24
  • 3
    The marked answer doesn't really answer the question, only provides a solution in the case that `setPrototypeOf()` really is (or will have) a large negative performance impact. But there's nothing saying that it actually _does_ have a negative performance impact. The Firefox JavaScript console, too, gives the same warning. Why is that? – user5670895 Oct 30 '15 at 15:11

2 Answers2

6

If you fear (as apparently you should..) the performance impact of using Object.setPrototypeOf(), but want to keep your object creation syntax similar to how your code is structured, try this:

var MyPrototype = {
    method1 : function(){...},
    method2 : function(){...},
    ...
};

var newObject = Object.assign(Object.create(MyPrototype), {
    property : 1,
    property2 : 'text'                 
});
Amit
  • 45,440
  • 9
  • 78
  • 110
  • Oh I see. hmm seams like I missed this one. Looks a little silly since we first create two new objects, one with the desired properties but the wrong prototype and one without any properties but the right prototype. Just to then coppy all the properties from one object to the other one. But since this will avoid future performance issues I guess it's a good way to go. Thanks! – Jovan Sep 07 '15 at 19:14
  • You create one object that has the correct prototype, and another one to copy properties from. Just the second one is "wasteful", but that's how you normally pass multiple "named" values into a function. `Object.create` uses the same mechanism – Amit Sep 07 '15 at 19:16
  • yes I know that. What I meant is, we want to create one new object with a certain prototype, but in order to achieve that we actually need to create two. I also use this method for method arguments, but here we really just want to quickly setup a new object with it's correct prototype. But this is the better way to go, so no complains ^^ – Jovan Sep 07 '15 at 19:21
  • 1
    If you're using Babel you could also consider using the `__proto__` object literal property and something like [`proto-to-create`](https://www.npmjs.com/package/babel-plugin-proto-to-create). – loganfsmyth Sep 08 '15 at 04:15
0

Another option is to merge the object literal with a shallow copy of myPrototype, although this may not be your desire.

var MyPrototype = {
    method1 : function(){},
    method2 : function(){}
};

var newObject = Object.assign({
    property : 1,
    property2 : 'text'                 
}, MyPrototype);
JBallin
  • 8,481
  • 4
  • 46
  • 51