Crockford recommends este tipo de Object.create
cuña:
if (typeof Object.create != "function") {
Object.create = function (o) {
function F(){}
F.prototype = o;
return new F;
};
}
Pero por favor no hacen esto.
El problema con este enfoque es que ES5 Object.create
tiene una firma de 2 argumentos: primero - un objeto a heredar de, y segundos (opcional) - un objeto que representa las propiedades (o más bien, los descriptores) para añadir a recién objeto creado
Object.create(O[, Properties]); // see 15.2.3.5, ECMA-262 5th ed.
Lo que tenemos es un aplicación inconsistente con 2 comportamientos diferentes. En entornos con Object.create
nativo, el método sabe cómo manejar el segundo argumento; en entornos sin Object.create
nativo, no es así.
¿Cuáles son las implicaciones prácticas?
Bueno, si hay algo de código (por ejemplo, un tercer guión del partido) que quiere usar Object.create
, es bastante razonable para que el código para hacer esto:
if (Object.create) {
var child = Object.create(parent, properties);
}
- esencialmente, asumiendo que si Object.create
existe, debe cumplir con las especificaciones: acepte el segundo argumento y agregue las propiedades correspondientes a un objeto.
Pero, con la cuña mencionada anteriormente, el segundo argumento simplemente se ignora. Ni siquiera hay una indicación de que algo va erróneo de manera diferente. Una falla silenciosa, por así decirlo, algo que es bastante doloroso de detectar y corregir.
¿Podemos hacerlo mejor?
Bueno, en realidad es imposible de crear una cuña Object.create
totalmente conformes usando solo (estándar) ES3 instalaciones. La mejor solución es crear un método de contenedor personalizado.
Hay, sin embargo, pocas alternativas (menos de óptimos) cosas que puede probar:
1) Notificar al usuario sobre la incapacidad para trabajar con el segundo argumento
if (!Object.create) {
Object.create = function (o) {
if (arguments.length > 1) {
throw Error('second argument is not supported');
}
// ... proceed ...
};
}
2) tratar de manejar segundo argumento :
if (!Object.create) {
Object.create = function (parent, properties) {
function F(){}
F.prototype = parent;
var obj = new F;
if (properties) {
// ... augment obj ...
}
return obj;
};
}
Tenga en cuenta que las "propiedades" es un objeto que representa descriptores de propiedades, no sólo los nombres de las propiedades/val ues, y es algo que no es muy trivial para el apoyo (algunas cosas no son aún posibles, tales como el control de enumerability de una propiedad):
Object.create(parent, {
foo: {
value: 'bar',
writable: true
},
baz: {
get: function(){ return 'baz getter'; },
set: function(value){ return 'baz setter'; },
enumerable: true
}
});
La otra inconsistencia en la cuña original es que no se ocupa de objeto principal siendo null
.
var foo = Object.create(null);
Esto crea un objeto cuya [[Prototype]] es null
; en otras palabras, objeto que no hereda de nada, ni siquiera Object.prototype
(del cual heredan todos los objetos nativos en ECMAScript).
foo.toString; // undefined
foo.constructor; // undefined
// etc.
Esto es, por cierto, útil para crear tablas hash "adecuadas" en ECMAScript.
Es posible emular este comportamiento, pero solo utilizando extensiones no estándar, como la propiedad "mágica" __proto__
(por lo que la implementación no sería muy portátil o robusta). La solución a este problema es similar: emule completamente la implementación de ES5 o notifique la incoherencia/falla.
Vea también http://stackoverflow.com/questions/1890464/is-there-a-library-which-implements-new-javascript-ecmascript-5-methods-for-older/2916063#2916063 –