反正是否有实例的名称等于没有new的构造函数?

时间:2014-10-22 06:15:56

标签: javascript class prototype

我正在使用JavaScript实现一个简单的类。我知道有许多伟大的图书馆已经做到了这一点。但是,我的目的是更好地理解JavaScript原型模型。无论如何,我写了以下内容。据我所知,它正在发挥作用,但稍后我会描述一下:

function Class(constructor,prototypeObj){
    var c = constructor;
    c.create = function(){
        //var o = new constructor();
        var o = Object.create(c.prototype);
        c.apply(o,arguments);
        return o;
    };
    c.prototype = prototypeObj;
    return c;
}

var Animal = Class(
    function Animal(life){
        this.life = life;
    },
    {
        type: "animal",
        sayLife: function(){
            console.log(this.life);
        }
    }
);

var o = Animal.create(15);
console.log(o instanceof Animal); // True
console.log(o.sayLife()); // 15
console.log(o.type); // "animal"

然而,我的问题是当我在控制台中输入o(对于实例);它打印

Object {life: 15, type: "animal", sayLife: function}life: 15 __proto__: Object

但我希望它是

Animal {life: 15, type: "animal", sayLife: function}life: 15 __proto__: Object

如果我在constructor.create方法中更改第4行和第5行以使用新的构造函数()而不是Object.create(constructor.prototype),我会得到所需的行为,但是我在将参数传递给构造函数时遇到了问题初始化一个新对象。如果我返回的函数不是传递给类函数的构造函数,那么对象名称将不是Animal,而是“Object”或“F”之类的其他函数。

所以我的问题是有没有办法实现类函数,以便类的实例总是与构造函数共享相同的名称?

3 个答案:

答案 0 :(得分:2)

function Class(constructor, prototypeObj) {
  var c = constructor;
  c.create = function() {
    //var o = new constructor();
    var o = Object.create(c.prototype);
    c.apply(o, arguments);
    return o;
  };
  c.prototype = prototypeObj;
  c.prototype.constructor = constructor;
  return c;
}

var Animal = Class(
  function Animal(life) {
    this.life = life;
  }, {
    type: "animal",
    sayLife: function() {
      console.log(this.life);
    }
  }
);

var o = Animal.create(15);
console.log(o);

如果您只想更改控制台中正在打印的对象的类型,则需要调整构造函数的prototype属性的constructor属性,如下所示

c.prototype = prototypeObj;
c.prototype.constructor = constructor;
return c;

enter image description here

答案 1 :(得分:1)

您可能想要使用Object.create()

  

Object.create()方法使用指定的原型对象和属性创建一个新对象。

这允许您在创建时完全配置对象,包括指定任何构造函数的可能性:

var o = Object.create(Animal.prototype,{
  constructor:{
    value: Animal
  }
})

编辑:

请参阅@dfsq的答案以及下面的评论,以获得更简单的解决方案。

答案 2 :(得分:1)

您是否知道constructor函数不是真正的特殊功能?它就像原型上的任何其他方法一样。因此,您不需要与其他原型方法区别对待它。这就是我通常做的事情:

function defclass(prototype) {
    var constructor = prototype.constructor;
    constructor.prototype = prototype;
    return constructor;
}

这允许我按如下方式创建构造函数:

var Animal = defclass({
    constructor: function Animal(life) { // note that I named the constructor
        this.life = life;
    },
    sayLife: function () {
        console.log(this.life);
    },
    type: "animal"
});

然后我们可以按如下方式使用它:

var o = new Animal(15);

console.log(o instanceof Animal); // true
console.log(o.sayLife());         // 15
console.log(o.type);              // "animal"

您的代码未按预期工作的原因是您忘记重置constructor上的prototype属性。但是,使用我的方法,由于constructor方法已经是prototype的属性,因此您无需执行任何其他操作。

有关原型继承的更多信息,请参阅以下问题:

JavaScript inheritance and the constructor property