Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there efficient ways to use `__proto__` or `setPrototypeOf()` in javascript?

MDN has a huge scary warning about modifying the prototype in your code:

Changing the [[Prototype]] of an object is, by the nature of how modern JavaScript engines optimize property accesses, a very slow operation, in every browser and JavaScript engine. The effects on performance of altering inheritance are subtle and far-flung, and are not limited to simply the time spent in the Object.setPrototypeOf(...) statement, but may extend to any code that has access to any object whose [[Prototype]] has been altered. If you care about performance you should avoid setting the [[Prototype]] of an object. Instead, create a new object with the desired [[Prototype]] using Object.create().

—MDN > JavaScript > Object.setPrototypeOf()

I’m wondering if there are any situations where you can modify an object’s prototype without causing cascading optimization effects that kill your program's performance. It seems like there should be. For example if you only modify the prototype right after the object is created (and before its used by anything else). But I imagine this is very engine-dependent.

So does anyone know if there are efficient ways to modify an object’s prototype?

Edit: The motivation for this question comes from a desire to create objects that actually inherit from Function. And the only way I know how to do that is by modifying the prototype of a function. See the very bottom of Raynos’s answer here: javascript class inherit from Function class

like image 713
B T Avatar asked Sep 29 '17 00:09

B T


1 Answers

The motivation for this question comes from a desire to create objects that actually inherit from Function.

It seems what you are trying to do is the following:

  • Create new objects
  • Set these objects' prototype (or __proto__ property) to refer to Fuction.prototype such that they inherit properties from Function.prototype, e.g.:
    • .apply
    • .call
    • .bind

You should never need to change any object’s prototype as long as you can correctly set it to the desired reference at the time the object is created.


Answer One: How to Set an Object's Prototype

You can set any object’s prototype upon creation using Object.create(). Note that assigning any object's prototype to Function.prototype will not cause the object to be a callable function. But if you still wanted to assign the prototype to refer to Function.prototype, or to some other object, you could do the following:

var obj1 = Object.create(Function.prototype);

This will:

  • Create a new object, obj1
  • Set its prototype (or __proto__ property) to refer to Function.prototype or whatever object you pass in as the argument
    • i.e., it will delegate failed property lookups to Function.prototype via the prototype chain (this is what a JavaScript prototype is and what __proto__ refers to: a place to delegate failed property lookups)

This does not require you to use Object.setPrototypeOf() to change an existing object's prototype because it assigns the prototype at the moment the object is created. See MDN docs for Object.create() for more examples and info -- this does not carry the same scary warnings as setPrototypeOf(). You can use Object.create() to set any new object's prototype.


Answer Two: Functions are Already Objects

That said, if you want an object that behaves like a function, you can simply create a function. A function is still an object, but with additional function-specific properties and behaviors; you can still treat it like an object by assigning properties to it. If you're looking to create a function that also acts like an object, or an object that can also do the same things as a function, then a function already does that. You can do things like:

var func = function() { return 'hello world'; }; // func is a function
func.property1 = 'foo'; // func is also an object
func.property2 = 'bar';

The best solution to your question may be to take advantage of the fact that functions are, in fact, already objects with added function-abilities.

like image 147
moriah Avatar answered Oct 04 '22 15:10

moriah