Why use chained prototype inheritance in javascrip

2020-06-03 03:41发布

perf

Why do we build a prototype inheritance chain rather then using object composition. Looking up through the prototype for each step in the chain get's expensive.

Here is some dummy example code :

var lower  = {
    "foo": "bar"
};

var upper = {
    "bar": "foo"
};

var chained = Object.create(lower,  pd(upper));

var chainedPrototype = Object.create(chained);

var combinedPrototype = Object.create(pd.merge(lower, upper));

var o1 = Object.create(chainedPrototypes);
var o2 = Object.create(combinedPrototypes);

uses pd because property descriptors are verbose as hell.

o2.foo is faster then o1.foo since it only goes up two prototype chain rather then three.

Since travelling up the prototype chain is expensive why do we construct one instead of using object composition?

Another better example would be :

var Element = {
  // Element methods
}

var Node = {
  // Node methods
}

var setUpChain = Object.create(Element, pd(Node));
var chained = Object.create(setUpChain);
var combined = Object.create(pd.merge(Node, Element));

document.createChainedElement = function() {
  return Object.create(chained);
}

document.createCombinedElement = function() {
  return Object.create(combined);
}

I do not see any code merging prototype objects for efficiency. I see a lot of code building chained prototypes. Why is the latter more popular?

The only reason I can think of is using Object.isPrototypeOf to test for individual prototypes in your chain.

Apart from isPrototypeOf are there clear advantages to using inheritance over composition?

3条回答
Bombasti
2楼-- · 2020-06-03 04:07

Well, consider what would happen if lower or upper changed. The combined prototype wouldn't reflect that change since you've created a new object by copying properties from them.

For many situations that would be fine, but it's sure not as dynamic as actually constructing proper prototype chains for your objects.

查看更多
Rolldiameter
3楼-- · 2020-06-03 04:10

The main reason would have to be changes to the prototype object. A change to an ancestor object will be reflected across the entire chain. This could, conceivably, be a benefit. Though I can't immediately think of any real-world instances, I think embracing this dynamic nature could provide a dynamic that other (read: class-based) languages simply don't provide.

Objects further up the prototype chain could evolve as needed across the lifetime of an application, and those changes would be reflected across all descendant objects. This could be easily combined with JavaScript's functions as first-class objects to dynamically modify functionality as needed.

That said, if this functionality is not necessary, there is no reason to use the prototype chain over composition.

查看更多
Rolldiameter
4楼-- · 2020-06-03 04:11

Here are some benefits I can think of in order of importance

Memory usage

By using the prototype, you create shared properties. Your approach copies all the values to each object.

Upfront cost of setting up objects

Thought you are saving a little bit of time later, you are incurring the cost of copying properties when you set up the object. It'd be nice for you to account for that in your performance tests. This is a benefit that may be outweighed if you read a lot more than you set up your objects.

instanceOf

Good code doesn't use instanceOf, but sometimes you can't make all your code perfect, so why break a language feature?

Dynamically changing the prototype

Most people will claim that they never need this (like me), but many of us have extended Array.prototype after instantiating some arrays (not that you should do it). With the copy properties approach you lose the reference to the original object.

Unashamed plug: http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html

Last Note If you this is actually a bottleneck in an app, I would not be reluctant to use it for the objects in question

查看更多
登录 后发表回答