【问题标题】:How to get name of child constructor?如何获取子构造函数的名称?
【发布时间】:2023-03-17 00:43:01
【问题描述】:

我有一个带有原型方法printConstructorName 的类,它打印构造函数的名称:

function Parent(){
}

Parent.prototype.printConstructorName = function(){
   console.log(this.constructor.name);
};

var parent = new Parent();
parent.printConstructorName(); // It gets 'Parent'.

一个类Child通过原型继承Parent

function Child()
{
}

Child.prototype = Parent.prototype;

var child = new Child();
child.printConstructorName(); // It gets 'Parent', but 'Child' is necessary.

如何通过Parent的原型方法获取Child的构造函数名称?

【问题讨论】:

  • 请注意name 是函数的非标准属性,不能用于除调试以外的任何用途。

标签: javascript


【解决方案1】:

Working fiddle

继承模式是个问题。这是快速修复:

function inherits(childCtor, parentCtor) {
  function tempCtor() {};
  tempCtor.prototype = parentCtor.prototype;
  childCtor.prototype = new tempCtor();
  childCtor.prototype.constructor = childCtor;
};

function Parent(){}

Parent.prototype.printConstructorName = function(){
   return this.constructor.name;
};

var parent = new Parent();
console.log(parent.printConstructorName()); // It gets 'Parent'.

function Child() {
    Parent.call(this);
};
inherits(Child, Parent);

var child = new Child();
console.log(child.printConstructorName()); // It gets 'Child'.

【讨论】:

  • 您的小提琴实际上并没有工作。您忘记在顶部实际命名 inherits 函数。
  • @alex23 比我快:P +1
【解决方案2】:

您将Parents 原型对象分配给Child.prototype - 这意味着每个子实例都继承自与所有父实例相同的事物,当然它们以这种方式继承相同的constructor 属性。

相反,为Child.prototype 创建一个新对象,继承自Parent.prototype,然后您可以覆盖constructor 属性:

Child.prototype = Object.create(Parent.prototype, {
    constructor: {value: Child, configurable: true}
});

【讨论】:

    【解决方案3】:

    您的继承机制显然是错误的。按照你的做法,如果给 Child.prototype 添加一个属性,所有的 Parent 对象也会得到它...

    您可能想要一个类似这样的inherit 函数:

    inherit = (function() {
        function F() {};
        return function(parent, child) {
            F.prototype = parent.prototype;
            child.prototype = new F();
            child.prototype.constructor = child;
        };
    }());
    

    然后你可以这样使用:

    function Parent() {
    }
    
    Parent.prototype.printConstructorName = function(){
       console.log(this.constructor.name);
    };
    
    var parent = new Parent();
    parent.printConstructorName();  // Parent
    
    function Child() {
    }
    
    inherit(Parent, Child);
    
    var child = new Child(); // Child
    child.printConstructorName();
    

    【讨论】:

    • inherit 函数本身在一个闭包内,其中包含函数F,但使用它不会在其他代码中引入额外的闭包。 (parentchild 不收集对此类闭包的任何引用。)
    【解决方案4】:

    在扩展现有构造函数时,应将子原型设置为父类的实例,以便对子原型的更改不会影响父原型。

    然后您可以简单地覆盖constructor,使其指向正确的函数。

    function Parent() {
        ....code...
    }
    
    Parent.prototype.printConstructorName = function () {
        console.log(this.constructor.name);
    };
    
    function Child() {
        ...code...
    }
    
    Child.prototype = new Parent();
    Child.prototype.constructor = Child;
    
    p = new Parent();
    p.printConstructorName(); //Parent
    
    c = new Child();
    c.printConstructorName(); //Child
    

    【讨论】:

      【解决方案5】:

      编写一个扩展函数,类似于:

      __extend = function(child, sup) {
          for (prop in sup.prototype) {
              child.prototype[prop] = sup.prototype[prop];
          };
      };
      

      然后你调用它而不是使用 prototype = new parent 技巧 - 比如:

      var Parent = function() {}
      Parent.prototype.name = function() { return "name" };
      
      var Child = function() {}
      __extend(Child, Parent);
      

      看看这个小提琴:http://jsfiddle.net/Cmg4A/

      【讨论】:

        【解决方案6】:

        也许您应该覆盖 Child :D 中的 printConstructorName。

        【讨论】:

        • 谢谢。但我需要一种适用于所有孩子的方法)
        猜你喜欢
        • 2018-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多