Patrón OLOO de Kyle Simpson frente al patrón de diseño de prototipo

109

¿El "patrón OLOO (objetos enlazados con otros objetos)" de Kyle Simpson se diferencia de alguna manera del patrón de diseño del prototipo? Aparte de acuñarlo con algo que indique específicamente "vinculación" (el comportamiento de los prototipos) y aclarar que no hay nada de "copiar" sucediendo aquí (un comportamiento de clases), ¿qué introduce exactamente su patrón?

Aquí hay un ejemplo del patrón de Kyle de su libro, "No conoces JS: esto y prototipos de objetos":

var Foo = {
    init: function(who) {
        this.me = who;
    },
    identify: function() {
        return "I am " + this.me;
    }
};

var Bar = Object.create(Foo);

Bar.speak = function() {
    alert("Hello, " + this.identify() + ".");
};

var b1 = Object.create(Bar);
b1.init("b1");
var b2 = Object.create(Bar);
b2.init("b2");

b1.speak(); // alerts: "Hello, I am b1."
b2.speak(); // alerts: "Hello, I am b2."
shmuli
fuente
2
¿Puede al menos vincular a una descripción del patrón por el que está preguntando? Aún mejor sería mostrar un ejemplo de código en su pregunta.
jfriend00
4
Getify está en Stackoverflow a veces. Le he tuiteado esta pregunta :)
Puntiagudo

Respuestas:

155

¿Qué introduce exactamente su patrón?

OLOO adopta la cadena de prototipos tal como está, sin necesidad de aplicar otras semánticas (confusas en mi opinión) para obtener el enlace.

Entonces, estos dos fragmentos tienen el mismo resultado EXACTO, pero llegan de manera diferente.

Forma de constructor:

function Foo() {}
Foo.prototype.y = 11;

function Bar() {}
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.z = 31;

var x = new Bar();
x.y + x.z;  // 42

Formulario OLOO:

var FooObj = { y: 11 };

var BarObj = Object.create(FooObj);
BarObj.z = 31;

var x = Object.create(BarObj);
x.y + x.z;  // 42

En ambos fragmentos, un xobjeto es[[Prototype]] vinculado a un objeto ( Bar.prototypeo BarObj), que a su vez está vinculado al tercer objeto ( Foo.prototypeo FooObj).

Las relaciones y la delegación son idénticas entre los fragmentos. El uso de memoria es idéntico entre los fragmentos. La capacidad de crear muchos "niños" (también conocidos como muchos objetos como x1through x1000, etc.) es idéntica entre los fragmentos. La actuación de la delegación ( x.yyx.z ) es idéntico entre los fragmentos. El rendimiento de creación de objetos es más lento con OLOO, pero la comprobación de la cordura que revela que el rendimiento más lento no es realmente un problema.

Lo que sostengo que ofrece OLOO es que es mucho más simple simplemente expresar los objetos y vincularlos directamente, que vincularlos indirectamente a través del constructor /new mecanismos. Este último pretende ser sobre clases, pero en realidad es una sintaxis terrible para expresar delegación ( nota al margen: ¡también lo es la classsintaxis de ES6 !).

OLOO simplemente está eliminando al intermediario.

Aquí hay otra comparación de classvs OLOO.

Kyle Simpson
fuente
2
Encontré realmente interesante su respuesta y la idea de OLOO descrita en sus libros, me gustaría recibir sus comentarios sobre esta pregunta: stackoverflow.com/questions/40395762/… Especialmente si encuentra que esta implementación es correcta y cómo resolver el problema relacionado con el acceso miembro privado. Gracias por su tiempo de antemano y enhorabuena por su último libro.
GibboK
Pero Object.create(...)es muchas veces más lento que new. jsperf.com/object-create-vs-crockford-vs-jorge-vs-constructor/…
Muelle
3
@Pier, el rendimiento no es realmente un gran problema. Se corrigió el enlace de la publicación del blog roto sobre la cordura verificando el rendimiento de la creación de objetos, lo que explica cómo pensar adecuadamente en esto.
Kyle Simpson
2
Y jQuery es más lento que la API DOM, ¿verdad? Pero, es el año en curso, hombre, prefiero escribir con elegancia y sencillez que preocuparme por optimizar. Si necesito micro-optimizar más tarde, me preocuparé cuando llegue el momento.
Eirik Birkeland
6
Me gustaría agregar que ahora, poco más de un año después, Object.create () está muy optimizado en Chrome, y jsperf lo muestra: es una de las opciones más rápidas ahora. Esto muestra exactamente por qué no debería preocuparse por tales microoptimizaciones y, en su lugar, escribir código sólido algorítmicamente.
Kyle Baker
25

Leí el libro de Kyle y lo encontré realmente informativo, particularmente los detalles sobre cómo this está encuadernado.

Pros:

Para mí, hay un par de grandes ventajas de OLOO:

1. Sencillez

OLOO confía en Object.create()crear un nuevo objeto que está [[prototype]]vinculado a otro objeto. No es necesario que comprenda que las funciones tienen unprototype propiedad o preocuparse por cualquiera de los posibles errores relacionados que surgen de su modificación.

2. Sintaxis más limpia

Esto es discutible, pero creo que la sintaxis de OLOO es (en muchos casos) más ordenada y concisa que el enfoque javascript 'estándar', particularmente cuando se trata de polimorfismo ( superllamadas de estilo).

Contras:

Creo que hay un poco de diseño cuestionable (uno que en realidad contribuye al punto 2 anterior), y eso tiene que ver con el sombreado:

En la delegación de comportamiento, evitamos si es posible nombrar cosas iguales en diferentes niveles de la [[Prototype]]cadena.

La idea detrás de esto es que los objetos tienen sus propias funciones más específicas que luego delegan internamente a funciones más abajo en la cadena. Por ejemplo, puede tener un resourceobjeto con una save()función en él que envía una versión JSON del objeto al servidor, pero también puede tener un clientResourceobjeto que tiene unstripAndSave() función, que primero elimina las propiedades que no deberían enviarse al servidor. .

El problema potencial es: si alguien más llega y decide hacer un specialResourceobjeto, sin estar completamente al tanto de toda la cadena del prototipo, podría razonablemente * decidir guardar una marca de tiempo para el último guardado bajo una propiedad llamada save, que oculta la save()funcionalidad base en el resourceobjeto dos eslabones hacia abajo en la cadena del prototipo:

var resource = {
  save: function () { 
    console.log('Saving');
  }
};

var clientResource = Object.create(resource);

clientResource.stripAndSave = function () {
  // Do something else, then delegate
  console.log('Stripping unwanted properties');
  this.save();
};

var specialResource = Object.create( clientResource );

specialResource.timeStampedSave = function () {
  // Set the timestamp of the last save
  this.save = Date.now();
  this.stripAndSave();
};

a = Object.create(clientResource);
b = Object.create(specialResource);

a.stripAndSave();    // "Stripping unwanted properties" & "Saving".
b.timeStampedSave(); // Error!

Este es un ejemplo particularmente elaborado, pero el punto es que específicamente no sombrear otras propiedades puede llevar a algunas situaciones incómodas y al uso intensivo de un diccionario de sinónimos.

Quizás una mejor ilustración de esto sería un initmétodo, particularmente conmovedor ya que OOLO evita las funciones de tipo constructor. Dado que todos los objetos relacionados probablemente necesitarán dicha función, puede ser un ejercicio tedioso nombrarlos adecuadamente, y la singularidad puede hacer que sea difícil recordar cuál usar.

* En realidad, no es particularmente razonable ( lastSavedsería mucho mejor, pero es solo un ejemplo).

Ed Hinchliffe
fuente
23
Estoy de acuerdo en que la posibilidad de colisiones de nombres es un inconveniente ... pero en realidad es un inconveniente del [[Prototype]]sistema en sí, no OLOO específicamente.
Kyle Simpson
¿Quizás eso también debería haber sido mencionado en el libro?
alquila
No estoy realmente seguro de que esto sea realmente una solución al problema que describe @Ed Hinchliffe, ya que simplemente mueve save () a su propio espacio de nombres, pero funciona codepen.io/tforward/pen/govEPr?editors=1010
Tristan Forward
Creo que @ ed-hinchliffe quiso decir en b.timeStampedSave();lugar de a.timeStampedSave();en la última línea del fragmento de código.
amangpt777
1
@ tristan-forward ¡gracias por traer a Rick y Morty a esto!
Eric Bishard
13

La discusión en "You Don't Know JS: this & Object Prototypes" y la presentación de OLOO es estimulante y he aprendido mucho leyendo el libro. Los méritos del patrón OLOO están bien descritos en las otras respuestas; sin embargo, tengo las siguientes quejas de mascotas (o me falta algo que me impide aplicarlo de manera efectiva):

1

Cuando una "clase" "hereda" otra "clase" en el patrón clásico, las dos funciones pueden declararse con sintaxis similar ( "declaración de función" o "declaración de función" ):

function Point(x,y) {
    this.x = x;
    this.y = y;
};

function Point3D(x,y,z) {
    Point.call(this, x,y);
    this.z = z;
};

Point3D.prototype = Object.create(Point.prototype);

Por el contrario, en el patrón OLOO, se utilizan diferentes formas sintácticas para definir la base y los objetos derivados:

var Point = {
    init  : function(x,y) {
        this.x = x;
        this.y = y;
    }
};


var Point3D = Object.create(Point);
Point3D.init = function(x,y,z) {
    Point.init.call(this, x, y);
    this.z = z;
};

Como puede ver en el ejemplo anterior, el objeto base se puede definir usando la notación literal de objeto, mientras que la misma notación no se puede usar para el objeto derivado. Esta asimetría me molesta.

2

En el patrón OLOO, la creación de un objeto consta de dos pasos:

  1. llamada Object.create
  2. Llame a algún método personalizado no estándar para inicializar el objeto (que debe recordar, ya que puede variar de un objeto a otro):

     var p2a = Object.create(Point);
    
     p2a.init(1,1);

Por el contrario, en el patrón de prototipo, utiliza el operador estándar new:

var p2a = new Point(1,1);

3

En el patrón clásico, puedo crear funciones de utilidad "estáticas" que no se aplican directamente a un "instante" asignándolas directamente a la función de "clase" (a diferencia de su .prototype). Por ejemplo, como función squareen el siguiente código:

Point.square = function(x) {return x*x;};

Point.prototype.length = function() {
    return Math.sqrt(Point.square(this.x)+Point.square(this.y));
};

Por el contrario, en el patrón OLOO todas las funciones "estáticas" están disponibles (a través de la cadena [[prototype]]) en las instancias del objeto también:

var Point = {
    init  : function(x,y) {
        this.x = x;
        this.y = y;
    },
    square: function(x) {return x*x;},
    length: function() {return Math.sqrt(Point.square(this.x)+Point.square(this.y));}
};
Marco Junio ​​Bruto
fuente
2
No hay literales en su primer ejemplo de código. Probablemente esté usando mal el término "literal" dándole otro significado. Solo digo ...
Ivan Kleshnin
2
Con respecto al segundo punto, el autor sostiene que es una "mejor" separación de preocupaciones tener la creación y la inicialización separadas y cita que podría haber algún caso de uso poco común en el que esto pueda brillar (por ejemplo, un grupo de objetos). Encuentro el argumento terriblemente débil.
alquila el
2
Nuevamente con respecto al segundo punto, con OLOO, puede crear sus objetos a la vez y esperar para inicializar, mientras que con el constructor, debe inicializar en la creación, por lo que Kyle considera esto como un beneficio.
taco
5

"Pensé que hacerlo hace que cada objeto dependa del otro"

Como explica Kyle cuando dos objetos están [[Prototype]]vinculados, en realidad no dependen el uno del otro; en cambio, son objeto individual. Está vinculando un objeto a otro con un [[Prototype]]vínculo que puede cambiar en cualquier momento que desee. Si toma dos [[Prototype]]objetos vinculados creados a través del estilo OLOO como dependientes entre sí, también debe pensar lo mismo sobre los creados a través de constructorllamadas.

var foo= {},
    bar= Object.create(foo),
    baz= Object.create(bar);


console.log(Object.getPrototypeOf(foo)) //Object.prototype

console.log(Object.getPrototypeOf(bar)) //foo

console.log(Object.getPrototypeOf(baz)) //bar

Ahora piensa por un segundo, ¿piensas foo barybaz como dependientes el uno del otro?

Ahora hagamos lo mismo con este constructorcódigo de estilo.

function Foo() {}

function Bar() {}

function Baz() {}

Bar.prototype= Object.create(Foo);
Baz.prototype= Object.create(Bar);

var foo= new Foo(),
    bar= new Bar().
    baz= new Baz();

console.log(Object.getPrototypeOf(foo)) //Foo.prototype
console.log(Object.getPrototypeOf(Foo.prototype)) //Object.prototype

console.log(Object.getPrototypeOf(bar)) //Bar.prototype
console.log(Object.getPrototypeOf(Bar.prototype)) //Foo.prototype

console.log(Object.getPrototypeOf(baz)) //Baz.prototype
console.log(Object.getPrototypeOf(Baz.prototype)) //Bar.prototype

La única diferencia b / w este último y el código anterior es que en este último uno foo, bar, bazbbjects están vinculados a cada-otra a través de objetos arbitrarios de su constructorfunción ( Foo.prototype, Bar.prototype, Baz.prototype), pero en el anterior ( OLOOestilo) que están vinculados directamente. Ambas formas que sólo va a asociar foo, bar, bazuno con el otro, situado en la anterior e indirectamente en el último. Pero, en ambos casos, los objetos son independientes entre sí porque no es realmente como una instancia de ninguna clase que, una vez instanciada, no se puede hacer heredar de alguna otra clase. Siempre puede cambiar qué objeto debe delegar un objeto también.

var anotherObj= {};
Object.setPrototypeOf(foo, anotherObj);

Entonces todos son independientes entre sí.

"Tenía la esperanza de OLOOresolver el problema en el que cada objeto no sabe nada sobre el otro".

Sí, eso es posible

Usemos Techcomo un objeto de utilidad

 var Tech= {
     tag: "technology",
     setName= function(name) {
              this.name= name;
}
}

cree tantos objetos como desee vinculados Tech-

var html= Object.create(Tech),
     css= Object.create(Tech),
     js= Object.create(Tech);

Some checking (avoiding console.log)- 

    html.isPrototypeOf(css); //false
    html.isPrototypeOf(js); //false

    css.isPrototypeOf(html); //false
    css.isPrototypeOf(js); //false

    js.isPrototypeOf(html); //false
    js.isPrototypwOf(css); //false

    Tech.isPrototypeOf(html); //true
    Tech.isPrototypeOf(css); //true
    Tech.isPrototypeOf(js); //true

¿Cree que html, css, jsobjetos están conectados entre sí-? No, no lo son. Ahora veamos cómo pudimos haber hecho eso con la constructorfunción

function Tech() { }

Tech.prototype.tag= "technology";

Tech.prototype.setName=  function(name) {
              this.name= name;
}

cree tantos objetos como desee vinculados Tech.proptotype-

var html= new Tech(),
     css= new Tech(),
      js= new Tech();

Algunas comprobaciones (evitando console.log) -

html.isPrototypeOf(css); //false
html.isPrototypeOf(js); //false

css.isPrototypeOf(html); //false
css.isPrototypeOf(js); //false

js.isPrototypeOf(html); //false
js.isPrototypeOf(css); //false

Tech.prototype.isPrototypeOf(html); //true
Tech.prototype.isPrototypeOf(css); //true
Tech.prototype.isPrototypeOf(js); //true

¿Cómo cree que estas constructoral estilo de objetos ( html, css, js) objetos difieren del OLOOcódigo de estilo? De hecho, tienen el mismo propósito. En el OLOOestilo uno los objetos delegan a Tech(la delegación se estableció explícitamente) mientras que en el constructorestilo uno los objetos delegan a Tech.prototype(la delegación se estableció implícitamente). En última instancia, termina vinculando los tres objetos, sin ningún vínculo entre sí, con un objeto, usando directamente OLOO-style, indirectamente usando constructor-style.

"Tal como está, ObjB debe crearse desde ObjA .. Object.create (ObjB), etc."

No, ObjBaquí no es como una instancia (en lenguajes de base clásica) de ninguna clase ObjA. Debería decirse que el objBobjeto se hace delegado a ObjAobjeto en el momento de su creación " . Si hubiera usado el constructor, habría hecho el mismo 'acoplamiento', aunque indirectamente haciendo uso de .prototypes.

Abhishek Sachan
fuente
3

@Marcus @bholben

Quizás podamos hacer algo como esto.

    const Point = {

        statics(m) { if (this !== Point) { throw Error(m); }},

        create (x, y) {
            this.statics();
            var P = Object.create(Point);
            P.init(x, y);
            return P;
        },

        init(x=0, y=0) {
            this.x = x;
            this.y = y;
        }
    };


    const Point3D = {

        __proto__: Point,

        statics(m) { if (this !== Point3D) { throw Error(m); }},

        create (x, y, z) {
            this.statics();
            var P = Object.create(Point3D);
            P.init(x, y, z);
            return P;
        },

        init (x=0, y=0, z=0) {
            super.init(x, y);
            this.z = z;
        }
    }; 

Por supuesto, crear un objeto Point3D que se vincule al prototipo de un objeto Point2D es un poco tonto, pero eso no viene al caso (quería ser coherente con su ejemplo). De todos modos, en lo que respecta a las quejas:

  1. La asimetría se puede arreglar con Object.setPrototypeOf de ES6 o el más mal visto __proto__ = ...que yo uso. También podemos usar super en objetos regulares ahora, como se ve en Point3D.init(). Otra forma sería hacer algo como

    const Point3D = Object.assign(Object.create(Point), {  
        ...  
    }   

    aunque no me gusta particularmente la sintaxis.


  1. Siempre podemos simplemente envolver p = Object.create(Point)y luego p.init()en un constructor. ej Point.create(x,y). Usando el código anterior podemos crear una Point3D"instancia" de la siguiente manera.

    var b = Point3D.create(1,2,3);
    console.log(b);                         // { x:1, y:2, z:3 }
    console.log(Point.isPrototypeOf(b));    // true
    console.log(Point3D.isPrototypeOf(b))   // true

  1. Se me ocurrió este truco para emular métodos estáticos en OLOO. No estoy seguro de si me gusta o no. Requiere llamar a una propiedad especial en la parte superior de cualquier método "estático". Por ejemplo, hice que el Point.create()método fuera estático.

        var p = Point.create(1,2);
        var q = p.create(4,1);          // Error!  

Alternativamente, con los símbolos ES6 puede extender de forma segura las clases base de Javascript. Así que podría guardarse algo de código y definir la propiedad especial en Object.prototype. Por ejemplo,

    const extendedJS = {};  

    ( function(extension) {

        const statics = Symbol('static');

        Object.defineProperty(Object.prototype, statics, {
            writable: true,
            enumerable: false,
            configurable: true,
            value(obj, message) {
                if (this !== obj)
                    throw Error(message);
            }
        });

        Object.assign(extension, {statics});

    })(extendedJS);


    const Point = {
        create (x, y) {
            this[extendedJS.statics](Point);
            ...

Andrew Szymczak
fuente
2

@james emanon - Entonces, te refieres a la herencia múltiple (discutida en la página 75 en el libro "No conoces JS: esto y prototipos de objetos"). Y ese mecanismo lo podemos encontrar en la función "extender" de subrayado, por ejemplo. Los nombres de los objetos que mencionaste en tu ejemplo son una mezcla de manzanas, naranjas y dulces, pero entiendo el punto detrás. Desde mi experiencia, esta sería la versión OOLO:

var ObjA = {
  setA: function(a) {
    this.a = a;
  },
  outputA: function() {
    console.log("Invoking outputA - A: ", this.a);
  }
};

// 'ObjB' links/delegates to 'ObjA'
var ObjB = Object.create( ObjA );

ObjB.setB = function(b) {
   this.b = b;
}

ObjB.setA_B = function(a, b) {
    this.setA( a ); // This is obvious. 'setA' is not found in 'ObjB' so by prototype chain it's found in 'ObjA'
    this.setB( b );
    console.log("Invoking setA_B - A: ", this.a, " B: ", this.b);
};

// 'ObjC' links/delegates to 'ObjB'
var ObjC = Object.create( ObjB );

ObjC.setC = function(c) {
    this.c = c;  
};

ObjC.setA_C = function(a, c) {
    this.setA( a ); // Invoking 'setA' that is clearly not in ObjC shows that prototype chaining goes through ObjB all the way to the ObjA
    this.setC( c );
    console.log("Invoking setA_C - A: ", this.a, " C: ", this.c);
};

ObjC.setA_B_C = function(a, b, c){
    this.setA( a ); // Invoking 'setA' that is clearly not in ObjC nor ObjB shows that prototype chaining got all the way to the ObjA
    this.setB( b );
    this.setC( c );
    console.log("Invoking setA_B_C - A: ", this.a, " B: ", this.b, " C: ", this.c);
};

ObjA.setA("A1");
ObjA.outputA(); // Invoking outputA - A:  A1

ObjB.setA_B("A2", "B1"); // Invoking setA_B - A:  A2  B:  B1

ObjC.setA_C("A3", "C1"); // Invoking setA_C - A:  A3  C:  C1
ObjC.setA_B_C("A4", "B2", "C1"); // Invoking setA_B_C - A:  A4  B:  B2  C:  C1

Es un ejemplo simple, pero el punto que se muestra es que solo estamos encadenando objetos en una estructura / formación bastante plana y todavía tenemos la posibilidad de usar métodos y propiedades de múltiples objetos. Logramos lo mismo que con el enfoque de clase / "copiar las propiedades". Resumido por Kyle (página 114, "esto y prototipos de objetos"):

En otras palabras, el mecanismo real, la esencia de lo que es importante para la funcionalidad que podemos aprovechar en JavaScript, se trata de que los objetos estén vinculados a otros objetos .

Entiendo que la forma más natural para usted sería establecer todos los objetos "padre" (cuidado :)) en un lugar / llamada de función en lugar de modelar toda la cadena.

Lo que requiere es un cambio en el pensamiento y el modelado de problemas en nuestras aplicaciones de acuerdo con eso. También me estoy acostumbrando. Espero que ayude y el veredicto final del propio Kyle sería genial. :)

NenadPavlov
fuente
Sí, gracias, pero esperaba alejarme de esta metodología porque la forma en que la tienes y la forma en que imaginé hacerlo hace que cada obj dependa del otro. Esperaba que OLOO resolviera el problema en el que cada objeto no sabe nada del otro. Como está, objB tiene que ser creado a partir de ObjA .. Object.create (ObjB) etc. que está demasiado acoplado. ¿algunas ideas?
james emanon
-1

@Marcus, al igual que tú, me ha gustado OLOO y tampoco me gusta la asimetría descrita en tu primer punto. He estado jugando con una abstracción para recuperar la simetría. Puede crear una link()función que se utilice en lugar de Object.create(). Cuando se usa, su código podría verse así ...

var Point = {
    init  : function(x,y) {
        this.x = x;
        this.y = y;
    }
};


var Point3D = link(Point, {
    init: function(x,y,z) {
        Point.init.call(this, x, y);
        this.z = z;
    }
});

Recuerde que Object.create()tiene un segundo parámetro que se puede pasar. Aquí está la función de enlace que aprovecha el segundo parámetro. También permite un poco de configuración personalizada ...

function link(delegate, props, propsConfig) {
  props = props || {};
  propsConfig = propsConfig || {};

  var obj = {};
  Object.keys(props).forEach(function (key) {
    obj[key] = {
      value: props[key],
      enumerable: propsConfig.isEnumerable || true,
      writable: propsConfig.isWritable || true,
      configurable: propsConfig.isConfigurable || true
    };
  });

  return Object.create(delegate, obj);
}

Por supuesto, creo que @Kyle no respaldaría el sombreado de la init()función en el objeto Point3D. ;-)

bholben
fuente
Al mirar hacia atrás a través de esto, ahora creo que al combinar Object.assign()con Object.create(), podemos simplificar enormemente la link()función anterior. En su lugar, se podría utilizar esto: function create(delegate, props) { return Object.assign(Object.create(delegate), props); }. O mejor aún, podemos usar subrayado o Lodash para que sea realmente concisa: _.create(delegate, props).
bholben
-1

¿Hay alguna manera de OLOO más de "dos" objetos ... todos los ejemplos consisten en el ejemplo basado (ver el ejemplo de OP). Digamos que tenemos los siguientes objetos, ¿cómo podemos crear un "cuarto" objeto que tenga los atributos de los "otros" tres? ala ...

var Button = {
     init: function(name, cost) {
       this.buttonName = name;
       this.buttonCost = cost;
     }
}

var Shoe = {
     speed: 100
}

var Bike = {
     range: '4 miles'
}

estos objetos son arbitrarios y pueden abarcar todo tipo de comportamientos. Pero la esencia es que tenemos 'n' número de objetos, y nuestro nuevo objeto necesita algo de los tres.

en lugar de los ejemplos dados ala:

var newObj = Object.create(oneSingularObject);
    newObj.whatever..

PERO, nuestro newObject = (Botón, Bicicleta, Zapato) ......

¿Cuál es el patrón para que esto funcione en OLOO?

james emanon
fuente
1
Esto suena a "favorecer la composición sobre la herencia", una gran estrategia. En ES6, puede usar Object.assign()- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . Si escribe en ES5, puede utilizar Underscore's _.extend()o Lodash's _.assign(). Aquí hay un excelente video para explicar ... youtu.be/wfMtDGfHWpA . Si tiene propiedades en colisión, gana la última, por lo que el orden es importante.
bholben