javascript inheritance, reflection and prototype c

2019-04-17 01:27发布

问题:

i'm trying to figure out how much i can use of the javascript language itself and how much i would have to implement myself when it comes to object reflection. here's the intended result

// property inheritance schema (defining default props) (stored in db "schemas" table)
foo
    bar
        moo
    baz
        ugh

// method inheritance schema (stored in code)
foo
    bar
        moo
    baz
        ugh

// myTree structure + property overrides (stored in db "structs" table)
myBar
    myBaz
    myUgh
        myBar
    myBaz
        myMoo

an instance of a Tree object will be constructed from the myBar structure. when building each node, it will compose the methods from the code, with the "inherited" property schema and any non-default properties from the node defined in the myBar struct itself.

the goal is to create a a system that, given a node from an instance of Tree, can self-analyze its own property inheritance path and identify at which level the property is defined.

this is to allow editing of the myBar structure and indicate which properties are inherited as defaults from the base schema (and at which level) and which ones are explicitly defined in the myBar structure.

the question is, how much can be determined from recursively analyzing the .constructor and .prototype properties using JS, and how much would need to be custom implemented?

i'm not sure if this is sufficiently clear, so please ask for any clarification.

thanks!

回答1:

You want to build prototype chains.

So let's say your chain of inheritance is

foo -> bar -> moo.

Then you have an object Foo that is your prototype for foo nodes.

You can create a Bar object by simply injecting Foo into it's prototype chain.

var Bar = Object.create(Foo, props)

Now we have a Bar prototype that is the prototype for bar nodes.

Then you do the same for Moo

var Moo = Object.create(Bar, props)

Now let's say you have a moo node.

Then you can simply take any property that you know. Let's call it "prop1" and write a simple function which gives you the object the property belongs to

var findPropertyOwner = function(obj, prop) {
  do {
    if (obj.hasOwnProperty(prop)) {
      return obj;
    }
  } while (obj = Object.getPrototypeOf(obj));
}

Now one of the issues that you may face is that the obj in the prototype chain has no meta data telling you what the object is so you may want to add a property "name" to all your node prototype objects so that you can more easily check what it is.

You may also want to have findPropertyOwner return a tuple of (obj, count) as follows

var findPropertyOwner = function(obj, prop) {
  var i = 0;
  do {
    if (obj.hasOwnProperty(prop)) {
      return [obj, i];
    }
  } while (i++, obj = Object.getPrototypeOf(obj));
}

This way you have more information like how far up the prototype chain that property was found. Also note that when the do/while loop terminates (Object.getPrototypeOf(Object.prototype) === null) it will return undefined



回答2:

Raynos's answer is great. I had to tweak it slightly, so that it worked for objects not descended from Object.

var findPropertyOwner = function(obj, prop) {
  var i = 0;
  do {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
      return [obj, i];
    }
  } while (i++, obj = Object.getPrototypeOf(obj));
}