javascript - ¿Qué scripts de modernización existen para las nuevas funciones de ECMAScript 5?
cross-browser backwards-compatibility (4)
Si no le importa aprender la biblioteca y escribir algún código usted mismo, puede encontrar algunas implementaciones de código de la biblioteca ECMAScript 5 en
https://developer.mozilla.org/En/JavaScript/ECMAScript_5_support_in_Mozilla
Por ejemplo, el código para Array.filter
Y luego Crockford tiene JSON.parse / stringify en json2.js
ECMAScript 5 tiene algunas adiciones agradables. John Resig tiene una buena visión general aquí . Aquí hay una buena tabla de compatibilidad ECMAScript 5 .
Muchas de estas cosas pueden ser "falsificadas" para los navegadores que aún no admiten estas funciones. ¿Conoces algún script que pueda hacer esto? Estoy particularmente interesado en Object.create.
Por ejemplo, el script JSON de Douglas Crockford comprueba si existen funciones JSON antes de crearlas.
Si hubiera más como el JSON, podríamos incluirlos cuando necesitemos usar las nuevas funciones.
es5-shim http://github.com/kriskowal/es5-shim/
Esto formaba parte del entorno de JavaScript independiente Narwhal, pero se ha descifrado por sí solo. Es bastante maduro y preciso.
es5 - JavaScript / EcmaScript 5 en 3 es una colección compartida en BitBucket. Object.create
en particular es fácil de falsificar , popularizado por Crockford et al, pero mejorado aquí por Justin Love , centrado en muchas partes de ES5.
Crockford recomienda este tipo de Object.create
shim:
if (typeof Object.create != "function") {
Object.create = function (o) {
function F(){}
F.prototype = o;
return new F;
};
}
Pero por favor no hagas esto .
El problema con este enfoque es que ES5 Object.create
tiene una firma de 2 argumentos : primero - un objeto para heredar, y segundo (opcional) - un objeto que representa propiedades (o más bien, descriptores) para agregar al objeto recién creado.
Object.create(O[, Properties]); // see 15.2.3.5, ECMA-262 5th ed.
Lo que tenemos es una implementació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 lo hace.
¿Cuáles son las implicaciones prácticas?
Bueno, si hay algún código (por ejemplo, un script de un tercero) que quiere usar Object.create
, es bastante razonable que ese código haga esto:
if (Object.create) {
var child = Object.create(parent, properties);
}
- asumiendo esencialmente que si Object.create
existe, debe cumplir con las especificaciones - acepte el segundo argumento y agregue las propiedades correspondientes a un objeto.
Pero, con el calce mencionado anteriormente, el segundo argumento simplemente se ignora. Ni siquiera hay una indicación de que algo va incorrecto diferentemente. Un fallo silencioso, por así decirlo, algo que es bastante doloroso de detectar y solucionar.
¿Podemos hacerlo mejor?
Bueno, en realidad es imposible crear un objeto Object.create
totalmente Object.create
usando solo las instalaciones de ES3 (estándar) . La mejor solución es crear un método de envoltorio personalizado.
Sin embargo, hay algunas alternativas (menos que óptimas) que puedes 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) Trate de manejar el 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 "propiedades" es un objeto que representa descriptores de propiedad , no solo nombres / valores de propiedad, y es algo que no es muy trivial de admitir (algunas cosas ni siquiera son posibles, como controlar la posibilidad de enumeración 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 incoherencia en el shim original es que no se ocupa de que el objeto principal sea null
.
var foo = Object.create(null);
Esto crea un objeto cuyo [[Prototipo]] es null
; en otras palabras, objeto que no se hereda de nada, ni siquiera Object.prototype
(del cual Object.prototype
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 __proto__
"mágica" (por lo que la implementación no sería muy portátil o robusta). La solución a este problema es similar: emule la implementación de ES5 completamente o notifique sobre la inconsistencia / falla.