我正在使用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”之类的其他函数。
所以我的问题是有没有办法实现类函数,以便类的实例总是与构造函数共享相同的名称?
答案 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;
答案 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
的属性,因此您无需执行任何其他操作。
有关原型继承的更多信息,请参阅以下问题: