繁体   English   中英

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

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

我最近遇到了一个有趣的问题。 我正在开发一些现有的代码,无论好坏,通常有几个级别的原型继承以各种各种对象的构造函数结尾。 这些中的每一个最终都来自单个基础“类”。

每个构造函数都遵循以下继承模式,其中Sub是子类, Super是它的直接原型:

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

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

这种模式一直持续到单个基类。

发现我们需要为原型链上的每个对象存储构造函数名称列表非常有益,我想出了基类的以下代码添加,它使用了arguments对象的calleecaller属性:

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

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

这个问题的主要问题是它只在对象是在匿名函数(或全局范围)内构造时才有效。 例如,假设我有一个带有原型Base原型SubA的构造函数SubA1 ,如果我这样做:

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

aOk的构造函数列表是: [Base,SubA,SubA1] ,这就是我想要的。

aNotOk的构造函数列表最终为: [Base,SubA,SubA1,oops]

这是一个吸烟者

我可以通过让每个构造函数将它们的名称添加到构造函数列表本身来修复它,但是存在一些问题,其中最重要的是将代码添加到每个构建器的巨大痛苦(以及调试/维护噩梦)。许多构造函数。

有一种优雅的方式来实现这一目标吗?

请注意,虽然上面的问题是在更广泛的意义上提出的,而不是Node.js特有的,但我实际上是在Node.js环境中使用代码。 因此,欢迎特定于Node的解决方案。

更新:

在我的特定情况下,所有构造函数都在命名空间内。 所以我实际上可以通过执行检查来确定函数名称是否存在于命名空间中,然后再将其添加到constructorList

基本上,我可以这样做:

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);
}

当然,这不会在一般意义上解决它,并且它并不完美。 例如,如果调用new SubA1的函数恰好与命名空间中的一个构造函数具有相同的名称,它将抛出该列表。 在我的特定情况下,由于构造函数遵循唯一的命名模式,因此这种情况极不可能发生。

我知道arguments.callee已被弃用,并且Object.constructor不值得信任(它无法得到我想要的东西),但我不知道通过修改获取链中每个构造函数的任何其他方法只是基础'类'。

当这些函数被注册为原型的属性时,它将获取原型链的所有构造函数:

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;
}

如果没有参数type ,则返回一个函数数组,其中type = 'names'是一个函数名字符串数组。

以HTMLDivElement对象为例,使用FIDDLE作为示例 使用控制台。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM