Composing a prototype chain in JavaScript As an exercise, I wrote a simple function that composes a prototype chain from a list of objects by appending to the prototype chain of the first object, the rest of the objects. This is the code (example usage and tests in this gist):

var assign = Object.assign || require('object.assign');

// Non-enumerable properties are omitted. Property attributes are not respected 
// and getters and setters aren't copied.
function appendToProto(obj, proto)
{
  if (obj === null)
    throw new Error(
      'Prototype chains are assumed to be delimited by Object.prototype.'
    );
  else if (obj === Object.prototype)
    return proto;
  else
    return assign(
      Object.create(
        appendToProto(Object.getPrototypeOf(obj), proto)
      ),
      obj
    );
}

// Takes a list of objects. The first object will be the farthest away from root
// (Object.prototype).
function composeProtoChain(prototypes)
{
  return prototypes.reduce(appendToProto);
}


As noted above, I can identify three issues with this code:


Non-enumerable properties are omitted from the prototype chain.
Property attributes are not respected and getters and setters aren't copied.
The assumption that Object.prototype is the last object before null in the prototype chain of objects.


I don't think there is a solution for the first issue, but workarounds could be implemented for the second and third ones. I preferred to keep things simple here, so I avoided doing that. 
(Exceeding the maximum recursion depth in appendToProto shouldn't be a problem.)

I have two questions:


Is throwing an error in appendToProto the right way to enforce the assumption from the third issue? 
Are there any other caveats that I haven't considered?
I'll admit to being new to this concept, and can't think of a real-world application for this method. Regardless, here's my thoughts. 

Issues #1 and #2 are directly results of your use of Object.Assign which seems an acceptable limitation. Issue #3 is stating a fact of how Object prototypes are set up. The prototype of Object.prototype is by definition null, so #3 is technically a given.

However, your questions make your meaning of #3 more clear.


  Is throwing an error in appendToProto the right way to enforce the assumption from the third issue?


I wouldn't think so, as it limits the usefulness of your function. I would simply skip null values: 

if (obj === null || obj === Object.prototype)
    return proto;


This has the benefit of treating null input essentially as if it were not provided, which would seem a more expected result. You could still have an error thrown, but I don't see the value. 

If you choose to have an error, at least make the issue more obvious. "Prototype chains are assumed to be delimited by Object.prototype." is confusing and unclear what the issue is to me. I would go for something like: "Cannot appendToProto of null."

In general the error message should indicate what is wrong with the input instead of the codes philosophy regarding what its input should be.