Recientemente me topé con el Object.create()método en JavaScript, y estoy tratando de deducir cómo es diferente de crear una nueva instancia de un objeto new SomeFunction()y cuándo querría usar uno sobre el otro.
Considere el siguiente ejemplo:
var test = {
val: 1,
func: function() {
return this.val;
}
};
var testA = Object.create(test);
testA.val = 2;
console.log(test.func()); // 1
console.log(testA.func()); // 2
console.log('other test');
var otherTest = function() {
this.val = 1;
this.func = function() {
return this.val;
};
};
var otherTestA = new otherTest();
var otherTestB = new otherTest();
otherTestB.val = 2;
console.log(otherTestA.val); // 1
console.log(otherTestB.val); // 2
console.log(otherTestA.func()); // 1
console.log(otherTestB.func()); // 2
Observe que se observa el mismo comportamiento en ambos casos. Me parece que las principales diferencias entre estos dos escenarios son:
- El objeto utilizado en
Object.create()realidad forma el prototipo del nuevo objeto, mientras que en lasnew Function()propiedades / funciones declaradas no forman el prototipo. - No puede crear cierres con la
Object.create()sintaxis como lo haría con la sintaxis funcional. Esto es lógico dado el alcance de tipo léxico (vs bloque) de JavaScript.
¿Son correctas las declaraciones anteriores? ¿Y me estoy perdiendo algo? ¿Cuándo usarías uno sobre el otro?
EDITAR: enlace a la versión jsfiddle del ejemplo de código anterior: http://jsfiddle.net/rZfYL/

Respuestas:
Sí,
Object.createcrea un objeto que hereda directamente del que pasó como primer argumento.Con las funciones de constructor, el objeto recién creado hereda del prototipo del constructor, por ejemplo:
En el ejemplo anterior,
ohereda directamente deSomeConstructor.prototype.Hay una diferencia aquí, con
Object.createusted puede crear un objeto que no herede de nadaObject.create(null);, por otro lado, si estableceSomeConstructor.prototype = null;el objeto recién creado heredará deObject.prototype.Bueno, puede crear cierres, por ejemplo, utilizando el argumento de descriptores de propiedad:
Tenga en cuenta que estoy hablando del
Object.createmétodo ECMAScript 5th Edition , no de la cuña de Crockford.El método está comenzando a implementarse de forma nativa en los últimos navegadores, consulte esta tabla de compatibilidad .
fuente
foo;se resuelve en el entorno léxico actual . 2) Para proporcionar una manera fácil de implementar la herencia, es una construcción realmente poderosa. En mi opinión, lo usaría porque es realmente simple y liviano, pero para el código de producción, todavía tenemos que esperar un tiempo hasta que ES5 sea ampliamente compatible. Sobre las características faltantes, faltaba el hecho de crear un objeto "prístino",Object.create(null);es realmente útil implementar objetos confiables similares a tablas hash ...Object.create(null)significa que no tienes que usarhasOwnProperty()basura cuando iteras porque no hereda ninguno? Me gusta eso, gracias. Por supuesto, todo el mundo lo seguirá haciendo,hasOwnPropertyya que no todos lo usarán,Object.create(null)así que no estoy seguro de que sea un beneficio real ... Hasta ahora, he encontrado los otros "beneficios" deObject.create()no ser convincentes.Muy simplemente dicho,
new XesObject.create(X.prototype)con ejecutar adicionalmente laconstructorfunción. (Y dando laconstructoroportunidad alreturnobjeto real que debería ser el resultado de la expresión en lugar dethis).Eso es. :)
El resto de las respuestas son simplemente confusas, porque aparentemente nadie más lee la definición de
newninguno de los dos. ;)fuente
Estos son los pasos que ocurren internamente para ambas llamadas:
(Sugerencia: la única diferencia está en el paso 3)
new Test():new Object()objobj.__proto__enTest.prototypereturn Test.call(obj) || obj; // normally obj is returned but constructors in JS can return a valueObject.create( Test.prototype )new Object()objobj.__proto__enTest.prototypereturn obj;Entonces, básicamente
Object.create, no ejecuta el constructor.fuente
newbásicamente tiene todas las funciones duplicadas, mientrasObject.createque no.Déjame intentar explicar (más en el blog ):
Carconstructorvar Car = function(){}, así es como son las cosas internamente:{prototype}vínculo oculto aFunction.prototypeque no es accesible y unprototypeenlace aCar.prototypela que es accesible y tiene un realconstructordeCar. Tanto Function.prototype como Car.prototype tienen enlaces ocultosObject.prototype.Cuando queremos crear dos objetos equivalentes utilizando el
¿Qué está pasando?
newoperador y elcreatemétodo, tenemos que hacerlo así:Honda = new Car();yMaruti = Object.create(Car.prototype).Honda = new Car();- Cuando crea un objeto como este{prototype}, se apunta a la propiedad ocultaCar.prototype. Entonces, aquí, el{prototype}objeto Honda siempre seráCar.prototype: no tenemos ninguna opción para cambiar la{prototype}propiedad del objeto. ¿Qué sucede si quiero cambiar el prototipo de nuestro objeto recién creado?Maruti = Object.create(Car.prototype)- Cuando crea un objeto como este, tiene una opción adicional para elegir la{prototype}propiedad de su objeto . Si desea Car.prototype como el{prototype}entonces páselo como un parámetro en la función. Si no desea ninguna{prototype}para su objeto entonces puede pasar denullla siguiente manera:Maruti = Object.create(null).Conclusión: al utilizar el método
Object.create, tiene la libertad de elegir la{prototype}propiedad de su objeto . Ennew Car();, no tienes esa libertad.Forma preferida en OO JavaScript:
Supongamos que tenemos dos objetos
ayb.Ahora, supongamos que
atiene algunos métodos a los quebtambién quiere acceder. Para eso, requerimos la herencia de objetos (adebe ser el prototipo debsolo si queremos acceder a esos métodos). Si verificamos los prototipos deaybluego descubriremos que comparten el prototipoObject.prototype.Problema: queremos un objeto
acomo prototipob, pero aquí creamos un objetobcon el prototipoObject.prototype. Solución: se introdujo ECMAScript 5Object.create()para lograr fácilmente dicha herencia. Si creamos un objetobcomo este:entonces,
Entonces, si está haciendo secuencias de comandos orientadas a objetos, entonces
Object.create()es muy útil para la herencia.fuente
a.isPrototypeOf(b);devolveráfalselo correcto, porque ambos Objetos son diferentes y apuntan a una memoria diferente. La forma correcta de hacer esto con elnewoperador está aquí. - jsfiddle.net/167onunp .Esta:
y
son bastante parecidos Una diferencia importante es que
new Foorealmente ejecuta código de constructor, mientrasObject.createque no ejecutará código comoTenga en cuenta que si usa la versión de dos parámetros de
Object.create()entonces puede hacer cosas mucho más poderosas.fuente
Object.createen su forma más simple como esta le permite omitir funciones de constructor de su código mientras aprovecha la herencia del prototipo.La diferencia es la llamada "herencia pseudoclásica versus prototípica". La sugerencia es usar solo un tipo en su código, no mezclar los dos.
En la herencia pseudoclásica (con el operador "nuevo"), imagine que primero define una pseudoclase y luego crea objetos a partir de esa clase. Por ejemplo, defina una pseudo-clase "Persona", y luego cree "Alice" y "Bob" a partir de "Persona".
En la herencia de prototipos (usando Object.create), crea directamente una persona específica "Alice", y luego crea otra persona "Bob" usando "Alice" como prototipo. No hay "clase" aquí; Todos son objetos.
Internamente, JavaScript utiliza "herencia prototípica"; la forma "pseudoclásica" es solo un poco de azúcar.
Vea este enlace para una comparación de las dos formas.
fuente
Resumen:
1) con la
newpalabra clave hay dos cosas a tener en cuenta;a) la función se usa como constructor
b) el
function.prototypeobjeto se pasa a la__proto__propiedad ... o donde__proto__no es compatible, es el segundo lugar donde el nuevo objeto busca encontrar propiedades2) con
Object.create(obj.prototype)usted está construyendo un objeto (obj.prototype) y pasándolo al objeto deseado ... con la diferencia de que ahora los objetos nuevos__proto__también apuntan a obj.prototype (refire por xj9 para eso)fuente
Variantes de creación de objetos.
Variante 1 : ' new Object () ' -> Constructor de objetos sin argumentos.
Variante 2 : ' nuevo Objeto (persona) ' -> Constructor de objetos con argumento.
Variante 3.1 : ' Object.create (persona) '. Use Object.create con el objeto simple 'persona'. 'Object.create (persona)' creará (y devolverá) un nuevo objeto vacío y agregará la propiedad '__proto__' al mismo nuevo objeto vacío. Esta propiedad '__proto__' apuntará al objeto 'persona'.
Variante 3.2 : ' Object.create (Object.prototype) '. Use Object.create con el objeto incorporado -> 'Object.prototype'. 'Object.create (Object.prototype)' creará (y devolverá) un nuevo objeto vacío y agregará la propiedad '__proto__' al mismo nuevo objeto vacío. Esta propiedad '__proto__' apuntará al objeto 'Object.prototype'.
Variante 4 : ' nueva SomeFunction () '
fuente
Internamente
Object.createhace esto:La sintaxis simplemente elimina la ilusión de que JavaScript usa herencia clásica.
fuente
Object.createmétodo ECMAScript 5 hace mucho más que eso, puede definir propiedades por descriptores de propiedad y puede crear un objeto que no herede de nada (Object.create(null);), este tipo de calzas se debe evitar porque realmente no puede emular eso comportamiento en ES3. Más informaciónObject.create.De acuerdo con esta respuesta y con esta
newpalabra clave de video, lo siguiente es lo siguiente:Crea un nuevo objeto.
Vincula un nuevo objeto a la función constructora (
prototype).Hace
thispunto variable al nuevo objeto.Ejecuta la función de constructor utilizando el nuevo objeto y la ejecución implícita
return this;Asigna el nombre de la función del constructor a la propiedad del nuevo objeto
constructor.Object.createrealiza solo1sty2ndpasos !!!fuente