使用 Object.create() 的对象创建模式
Object creation patterns using Object.create()
我一直在研究如何在使用 Object.create() 而不是传统的构造函数时进行多级继承。我打开了 fiddle here .
我们有两类对象,程序员,和"subclass"前端开发人员。程序员继承自程序员原型对象,正如你所看到的,所有的程序员都会很尴尬。
var programmerProto = Object.create(Object.prototype,{
beAwkward: {value: function(){
return "Yeah I uhh, AHEM, *shuffles feet*";
}
}
});
function programmerFactory (name, age, neckbeard){
return Object.create(programmerProto, {
name: {writable: true, enumerable: true, value: name},
age: {writable: false, enumerable: true, value: age},
neckbeard: {writable: true, enumerable: true, value: neckbeard}
});
}
现在对于前端开发人员来说,他们都有自己的共同特点,所以我们需要一个新的原型对象来定义。但是,前端开发人员也是程序员,所以我们制作前端原型对象如下:
var frontEndProto = Object.create(programmerProto, {
beSmooth: {
value: function(){
return "Excuse me ma'am, could I interest you in a, fish sandwich?";
}
},
preferredLanguage: {writable: true, enumerable: true, value: 'JS'}
});
现在我们遇到了问题。我想使用工厂方法来创建前端开发人员的实例,因此我可以添加一些特定于前端的 属性,例如 "CSS3_skillz" 之类的。但是如果我使用 Object.create(frontEndProto, "..."),那么...将是我已经在 programmerFactoryFunction 中编写的所有代码。如果我从 frontEndFactory 中调用 programmerFactory,那么返回对象的原型是 programmerProto 而不是 frontEndProto。处理这个问题的正确方法是什么?
我认为您在继承链的事情和 Object.defineProperty()
样式属性的使用上有点过火了。
除非你有充分的理由需要像 instanceof
这样的东西,否则你可以只使用 .extend()
函数来实现你的继承。我在下面使用 underscore/lodash _.extend()
函数,但您几乎可以使用它的任何实现:
var programmerProto = {
beAwkward: function(){
return "Yeah I uhh, AHEM, *shuffles feet*";
}
};
function programmerFactory (name, age, neckbeard){
return _.extend({
name: name,
age: age,
neckbeard: neckbeard
}, programmerProto);
}
var frontEndProto = {
beSmooth: function(){
return "Excuse me ma'am, could I interest you in a, fish sandwich?";
},
preferredLanguage: 'JS'
};
function frontEndFactory(name, age, css3Skillz) {
return _.extend(programmerFactory(name, age, true), {
css3Skillz: css3Skills
}, frontEndProto);
}
我觉得这个话题讲的还不错:
http://www.youtube.com/watch?v=PV_cFx29Xz0&t=28m57s
解决您的问题的方法在于将一个对象的属性附加到另一个对象,这在这里很有用。
首先,我使用的追加函数 -
var appendObject = function(obj, toAppend) {
Object.keys(toAppend).forEach(function(el) {
Object.defineProperty(obj, el, Object.getOwnPropertyDescriptor(toAppend,el));
});
return obj;
}
它的作用非常简单——遍历 toAppend
的属性并使用它们的 属性 描述符在 obj
上定义新属性。它正在变异 obj
,但它也在变异 returns,因此如果需要,您可以链接它。
有了这个函数,你就可以像这样实现 frontEndDevFactory -
function frontEndDevFactory (name, age, pullupCount, rockStar){
var programmer = programmerFactory(name, age);
var newDev = Object.create(frontEndProto, {
pullupCount: {writable: true, enumerable: true, value: pullupCount},
rockStar: {writable: false, enumerable: true, value: rockStar}
});
appendObject(newDev, programmer);
return newDev;
}
这里有一个 fiddle 修改您的代码来演示这一点。
我一直在研究如何在使用 Object.create() 而不是传统的构造函数时进行多级继承。我打开了 fiddle here .
我们有两类对象,程序员,和"subclass"前端开发人员。程序员继承自程序员原型对象,正如你所看到的,所有的程序员都会很尴尬。
var programmerProto = Object.create(Object.prototype,{
beAwkward: {value: function(){
return "Yeah I uhh, AHEM, *shuffles feet*";
}
}
});
function programmerFactory (name, age, neckbeard){
return Object.create(programmerProto, {
name: {writable: true, enumerable: true, value: name},
age: {writable: false, enumerable: true, value: age},
neckbeard: {writable: true, enumerable: true, value: neckbeard}
});
}
现在对于前端开发人员来说,他们都有自己的共同特点,所以我们需要一个新的原型对象来定义。但是,前端开发人员也是程序员,所以我们制作前端原型对象如下:
var frontEndProto = Object.create(programmerProto, {
beSmooth: {
value: function(){
return "Excuse me ma'am, could I interest you in a, fish sandwich?";
}
},
preferredLanguage: {writable: true, enumerable: true, value: 'JS'}
});
现在我们遇到了问题。我想使用工厂方法来创建前端开发人员的实例,因此我可以添加一些特定于前端的 属性,例如 "CSS3_skillz" 之类的。但是如果我使用 Object.create(frontEndProto, "..."),那么...将是我已经在 programmerFactoryFunction 中编写的所有代码。如果我从 frontEndFactory 中调用 programmerFactory,那么返回对象的原型是 programmerProto 而不是 frontEndProto。处理这个问题的正确方法是什么?
我认为您在继承链的事情和 Object.defineProperty()
样式属性的使用上有点过火了。
除非你有充分的理由需要像 instanceof
这样的东西,否则你可以只使用 .extend()
函数来实现你的继承。我在下面使用 underscore/lodash _.extend()
函数,但您几乎可以使用它的任何实现:
var programmerProto = {
beAwkward: function(){
return "Yeah I uhh, AHEM, *shuffles feet*";
}
};
function programmerFactory (name, age, neckbeard){
return _.extend({
name: name,
age: age,
neckbeard: neckbeard
}, programmerProto);
}
var frontEndProto = {
beSmooth: function(){
return "Excuse me ma'am, could I interest you in a, fish sandwich?";
},
preferredLanguage: 'JS'
};
function frontEndFactory(name, age, css3Skillz) {
return _.extend(programmerFactory(name, age, true), {
css3Skillz: css3Skills
}, frontEndProto);
}
我觉得这个话题讲的还不错:
http://www.youtube.com/watch?v=PV_cFx29Xz0&t=28m57s
解决您的问题的方法在于将一个对象的属性附加到另一个对象,这在这里很有用。
首先,我使用的追加函数 -
var appendObject = function(obj, toAppend) {
Object.keys(toAppend).forEach(function(el) {
Object.defineProperty(obj, el, Object.getOwnPropertyDescriptor(toAppend,el));
});
return obj;
}
它的作用非常简单——遍历 toAppend
的属性并使用它们的 属性 描述符在 obj
上定义新属性。它正在变异 obj
,但它也在变异 returns,因此如果需要,您可以链接它。
有了这个函数,你就可以像这样实现 frontEndDevFactory -
function frontEndDevFactory (name, age, pullupCount, rockStar){
var programmer = programmerFactory(name, age);
var newDev = Object.create(frontEndProto, {
pullupCount: {writable: true, enumerable: true, value: pullupCount},
rockStar: {writable: false, enumerable: true, value: rockStar}
});
appendObject(newDev, programmer);
return newDev;
}
这里有一个 fiddle 修改您的代码来演示这一点。