使用Object.create()的对象创建模式

时间:2015-02-12 07:40:24

标签: javascript inheritance prototype factory

在使用Object.create()而不是传统的构造函数时,我一直在研究如何进行多级继承。我打开了一个小提琴 here

我们有两种类型的对象,程序员和一个"子类"前端开发人员。程序员继承自程序员原型对象,正如您所看到的,所有程序员都可能很尴尬。

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。处理这个问题的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

我认为您在继承链事物和Object.defineProperty() - 样式属性的使用方面有点过分。

除非您有充分理由需要instanceof之类的内容,否则您只需使用.extend()函数即可实现继承。我使用下面的下划线/ 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

答案 1 :(得分:1)

这里解决您的问题的方法是将一个对象的属性附加到另一个对象在这里很有用。

首先,我使用的追加功能 -

var appendObject = function(obj, toAppend) { 
    Object.keys(toAppend).forEach(function(el) { 
        Object.defineProperty(obj, el, Object.getOwnPropertyDescriptor(toAppend,el)); 
    }); 
    return obj; 
}

这样做非常简单 - 它遍历toAppend的属性并使用其属性描述符在obj上定义新属性。它正在改变obj,但也返回它,所以你可以根据需要链接它。

使用此功能,您可以像这样实现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修改你的代码来证明这一点。