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.create
crea 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,
o
hereda directamente deSomeConstructor.prototype
.Hay una diferencia aquí, con
Object.create
usted 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.create
mé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,hasOwnProperty
ya 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 X
esObject.create(X.prototype)
con ejecutar adicionalmente laconstructor
función. (Y dando laconstructor
oportunidad alreturn
objeto 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
new
ninguno 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.prototype
return Test.call(obj) || obj; // normally obj is returned but constructors in JS can return a value
Object.create( Test.prototype )
new Object()
objobj.__proto__
enTest.prototype
return obj;
Entonces, básicamente
Object.create
, no ejecuta el constructor.fuente
new
básicamente tiene todas las funciones duplicadas, mientrasObject.create
que no.Déjame intentar explicar (más en el blog ):
Car
constructorvar Car = function(){}
, así es como son las cosas internamente: Tenemos un{prototype}
vínculo oculto aFunction.prototype
que no es accesible y unprototype
enlace aCar.prototype
la que es accesible y tiene un realconstructor
deCar
. Tanto Function.prototype como Car.prototype tienen enlaces ocultosObject.prototype
.Cuando queremos crear dos objetos equivalentes utilizando el
new
operador y elcreate
método, tenemos que hacerlo así:Honda = new Car();
yMaruti = Object.create(Car.prototype)
. ¿Qué está pasando?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 denull
la 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
a
yb
.Ahora, supongamos que
a
tiene algunos métodos a los queb
también quiere acceder. Para eso, requerimos la herencia de objetos (a
debe ser el prototipo deb
solo si queremos acceder a esos métodos). Si verificamos los prototipos dea
yb
luego descubriremos que comparten el prototipoObject.prototype
.Problema: queremos un objeto
a
como prototipob
, pero aquí creamos un objetob
con el prototipoObject.prototype
. Solución: se introdujo ECMAScript 5Object.create()
para lograr fácilmente dicha herencia. Si creamos un objetob
como 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áfalse
lo correcto, porque ambos Objetos son diferentes y apuntan a una memoria diferente. La forma correcta de hacer esto con elnew
operador está aquí. - jsfiddle.net/167onunp .Esta:
y
son bastante parecidos Una diferencia importante es que
new Foo
realmente ejecuta código de constructor, mientrasObject.create
que 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.create
en 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
new
palabra clave hay dos cosas a tener en cuenta;a) la función se usa como constructor
b) el
function.prototype
objeto 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.create
hace esto:La sintaxis simplemente elimina la ilusión de que JavaScript usa herencia clásica.
fuente
Object.create
mé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
new
palabra clave de video, lo siguiente es lo siguiente:Crea un nuevo objeto.
Vincula un nuevo objeto a la función constructora (
prototype
).Hace
this
punto 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.create
realiza solo1st
y2nd
pasos !!!fuente