Comprender la diferencia entre Object.create() y new SomeFunction()
Recientemente me topé con el Object.create()
método en JavaScript y estoy tratando de deducir en qué se diferencia de crear una nueva instancia de un objeto con new SomeFunction()
y cuándo querrías 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 del tipo léxico (vs bloque) de JavaScript.
¿Son correctas las afirmaciones anteriores? ¿Y me falta 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/
En pocas palabras, new X
se trata Object.create(X.prototype)
de ejecutar adicionalmente la constructor
función. (Y dándole la constructor
oportunidad al return
objeto real de que debería ser el resultado de la expresión en lugar de this
).
Eso es todo. :)
El resto de las respuestas son simplemente confusas, porque aparentemente nadie más lee la definición de nuevo tampoco. ;)
El objeto utilizado en Object.create en realidad forma el prototipo del nuevo objeto, mientras que en la nueva forma Function() las propiedades/funciones declaradas no forman el prototipo.
Sí, Object.create
construye un objeto que hereda directamente del que se pasó como primer argumento.
Con las funciones constructoras, el objeto recién creado hereda del prototipo del constructor, por ejemplo:
var o = new SomeConstructor();
En el ejemplo anterior, o
hereda directamente de SomeConstructor.prototype
.
Aquí hay una diferencia: Object.create
puedes crear un objeto que no hereda de nada, Object.create(null);
por otro lado, si configuras SomeConstructor.prototype = null;
el objeto recién creado heredará de Object.prototype
.
No puede crear cierres con la sintaxis Object.create como lo haría con la sintaxis funcional. Esto es lógico dado el alcance del tipo léxico (vs bloque) de JavaScript.
Bueno, puedes crear cierres, por ejemplo, usando el argumento de descriptores de propiedad:
var o = Object.create({inherited: 1}, {
foo: {
get: (function () { // a closure
var closured = 'foo';
return function () {
return closured+'bar';
};
})()
}
});
o.foo; // "foobar"
Tenga en cuenta que estoy hablando del Object.create
método ECMAScript 5.ª edición, no del calce de Crockford.
El método está comenzando a implementarse de forma nativa en los navegadores más recientes; consulte esta tabla de compatibilidad .
Estos son los pasos que ocurren internamente para ambas llamadas:
(Pista: la única diferencia está en el paso 3)
new Test()
:
- crear
new Object()
objeto - ajustado
obj.__proto__
aTest.prototype
return Test.call(obj) || obj; // normally obj is returned but constructors in JS can return a value
Object.create( Test.prototype )
- crear
new Object()
objeto - ajustado
obj.__proto__
aTest.prototype
return obj;
Básicamente, Object.create
no ejecuta el constructor.