16

ECMAScript 5 tiene algunas buenas adiciones. John Resig has a good overview here. Aquí hay un buen ECMAScript 5 compatibility table.¿Qué scripts de modernizador existen para las nuevas funciones de 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, Douglas Crockford's JSON script comprueba si las funciones JSON existen antes de crearlas.

Si hubiera más como el JSON, podríamos incluirlos cuando necesitemos usar las nuevas funciones.

+0

Vea también http://stackoverflow.com/questions/1890464/is-there-a-library-which-implements-new-javascript-ecmascript-5-methods-for-older/2916063#2916063 –

Respuesta

40

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.

+1

Mi [Xccessors JavaScript library ] (http://github.com/eligrey/Xccessors) proporciona las funciones 'Object.defineProperty' y' Object.defineProperties' que puede usar para la solución n. ° 2. –

+10

Eso está muy bien visto y su conocimiento de ES5 es obviamente sólido, pero creo que vale la pena señalar que el código de Crockford es anterior a ES5 por bastante tiempo: primera versión alrededor de 2006 y la última, principios de 2008. Así que es un poco falso sugerir él "recomienda" esta solución para calzar ES5. – neonski

+7

La última vez que vi a Doug hablar sobre esta versión fue hace 3 meses: http: //www.slideshare.net/douglascrockford/javascript-the-good-parts-3292746/36 Eso es aproximadamente 4 meses después de que ES5 se estandarizó oficialmente (en diciembre de 2009) y es definitivamente posterior a 2008. Pero no quiero culpar a nadie (lo siento si salió de esa manera). Todos cometemos errores. La idea es recomendar en contra de ** el enfoque ** y explicar por qué. – kangax

Cuestiones relacionadas