简体   繁体   English

Javascript:如何获取对象的原型链构造函数名称列表?

[英]Javascript: How to get a list of an object's prototype chain constructor names?

I recently encountered an interesting problem. 我最近遇到了一个有趣的问题。 I am developing with some existing code where, for better or worse, there are often several levels of prototypical inheritance ending in constructors for all kinds of various objects. 我正在开发一些现有的代码,无论好坏,通常有几个级别的原型继承以各种各种对象的构造函数结尾。 Each of these ultimately inherit from a single base 'class'. 这些中的每一个最终都来自单个基础“类”。

Each constructor follows the following inheritance pattern, where Sub is a subclass and Super is it's immediate prototype: 每个构造函数都遵循以下继承模式,其中Sub是子类, Super是它的直接原型:

function Sub(/*args*/) {
    Super.call(this,/*args*/);
}

Sub.prototype = Object.create(Super.prototype);

This pattern continues all the way up to the single base class. 这种模式一直持续到单个基类。

Discovering that it would be incredibly beneficial for our needs to store a list of constructor names for each object up the prototype chain, I came up with the following code addition for the base class, which uses the callee and caller properties of the arguments object: 发现我们需要为原型链上的每个对象存储构造函数名称列表非常有益,我想出了基类的以下代码添加,它使用了arguments对象的calleecaller属性:

var curConstructor = arguments.callee;
this.constructorList = [curConstructor.name];

while(curConstructor.caller && curConstructor.caller.name !== ''){
    curConstructor = curConstructor.caller;
    this.constructorList.push(curConstructor.name);
}

The main issue with this, is it only works if the object was constructed inside of an anonymous function (or global scope). 这个问题的主要问题是它只在对象是在匿名函数(或全局范围)内构造时才有效。 For instance, assuming I have a constructor SubA1 with prototype SubA with prototype Base , if I do this: 例如,假设我有一个带有原型Base原型SubA的构造函数SubA1 ,如果我这样做:

function() {
  var aOk = new SubA1();
  function oops() {
    var aNotOk = new SubA1();
  }
  oops();
}

aOk 's constructor list is: [Base,SubA,SubA1] , which is what I want. aOk的构造函数列表是: [Base,SubA,SubA1] ,这就是我想要的。

aNotOk 's constructor list ends up as: [Base,SubA,SubA1,oops] . aNotOk的构造函数列表最终为: [Base,SubA,SubA1,oops]

Here's a plunker . 这是一个吸烟者

I could fix it by having each constructor add their name to the constructor list themselves, but there are several problems with that, not least of which is the tremendous pain (and debugging / maintenance nightmare) it would be to add code to each of the many many constructor functions. 我可以通过让每个构造函数将它们的名称添加到构造函数列表本身来修复它,但是存在一些问题,其中最重要的是将代码添加到每个构建器的巨大痛苦(以及调试/维护噩梦)。许多构造函数。

Is there an elegant way to achieve this? 有一种优雅的方式来实现这一目标吗?

Note that although the above question was asked in a more general sense, and not specific to Node.js, I am actually working with code in a Node.js environment. 请注意,虽然上面的问题是在更广泛的意义上提出的,而不是Node.js特有的,但我实际上是在Node.js环境中使用代码。 Therefore, solutions specific to Node are welcome. 因此,欢迎特定于Node的解决方案。

Update: 更新:

In my particular case, all of the constructors are within a namespace. 在我的特定情况下,所有构造函数都在命名空间内。 So I can actually solve the problem by performing a check to make sure that the function name exists in the namespace before adding it to the constructorList . 所以我实际上可以通过执行检查来确定函数名称是否存在于命名空间中,然后再将其添加到constructorList

Basically, I can do this: 基本上,我可以这样做:

var curConstructor = arguments.callee;
this.constructorList = [curConstructor.name];

while(curConstructor.caller){
    curConstructor = curConstructor.caller;

    // Exit if the function name isn't part of the namespace
    if(typeof namespace[curConstructor.name] !== 'function') break;

    this.constructorList.push(curConstructor.name);
}

This won't solve it in a generic sense though of course, and it isn't perfect. 当然,这不会在一般意义上解决它,并且它并不完美。 If the function which calls new SubA1 for example just happens to have the same name as one of the constructors in the namespace, it will throw the list off. 例如,如果调用new SubA1的函数恰好与命名空间中的一个构造函数具有相同的名称,它将抛出该列表。 In my particular case, since the constructors follow a unique naming pattern, that occurrence is extremely unlikely. 在我的特定情况下,由于构造函数遵循唯一的命名模式,因此这种情况极不可能发生。

I am aware that arguments.callee is deprecated, and that Object.constructor is not trustworthy (it doesn't get me what I want anyway), but I am unaware of any other way to get names of each constructor in the chain by modifying the base 'class' only. 我知道arguments.callee已被弃用,并且Object.constructor不值得信任(它无法得到我想要的东西),但我不知道通过修改获取链中每个构造函数的任何其他方法只是基础'类'。

This function gets all constructors of a prototype chain, when they are registered as a property of the prototype: 当这些函数被注册为原型的属性时,它将获取原型链的所有构造函数:

function getConstructorChain(obj, type) {
    var cs = [], pt = obj;
    do {
       if (pt = Object.getPrototypeOf(pt)) cs.push(pt.constructor || null);
    } while (pt != null);
    return type == 'names' ? cs.map(function(c) {
        return c ? c.toString().split(/\s|\(/)[1] : null;
    }) : cs;
}

Without argument type an array of functions is returned, with type = 'names' an array of function-name strings. 如果没有参数type ,则返回一个函数数组,其中type = 'names'是一个函数名字符串数组。

Working FIDDLE with a HTMLDivElement object as example here . 以HTMLDivElement对象为例,使用FIDDLE作为示例 Use console. 使用控制台。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何查看 Javascript 对象的原型链? - How can I see a Javascript object's prototype chain? 原型链中的函数解析将如何用于 Object.prototype 作为构造函数 - How function resolution in prototype chain will work for Object.prototype as constructor Javascript:如果该构造函数已在另一个对象的原型上定义,则如何追加到该构造函数的原型 - Javascript: how to append to a constructor's prototype, if that constructor is already defined on another object's prototype 如何在不调用构造函数的情况下复制对象及其原型链? - How do I copy an object and it's prototype chain without calling its constructor function? 原型构造函数链有多长? - How long is the prototype constructor chain? 在维护原型链的同时,如何在javascript中使用代理来捕获构造函数? - How to use a Proxy in javascript to capture a constructor while maintaining the prototype chain? Javascript原型对象构造函数 - Javascript Prototype Object Constructor JavaScript 原型链参考 Object.prototype - JavaScript Prototype Chain Reference to Object.prototype 为什么在该对象的原型链中还有一个额外的原型? - Why is there an extra prototype in this object's prototype chain? 如何在JavaScript中的构造函数中定义对象的原型? - How to define the prototype of an object in a constructor in JavaScript?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM