16

ECMAScript 5 hat einige nette Ergänzungen. John Resig has a good overview here. Hier ist eine gute ECMAScript 5 compatibility table.Welche Modernisierungsskripte existieren für die neuen ECMAScript 5-Funktionen?

Viele dieser Sachen können für Browser, die diese Funktionen noch nicht unterstützen, "gefälscht" werden. Kennen Sie Skripte, die das können? Ich bin besonders an Object.create interessiert.

Zum Beispiel prüft Douglas Crockford's JSON script, ob JSON-Funktionen vorhanden sind, bevor sie erstellt werden.

Wenn es mehr wie das JSON gäbe, könnten wir sie aufnehmen, wenn wir die neuen Funktionen verwenden müssen.

+0

Siehe auch http://stackoverflow.com/questions/1890464/is-there-a-library-which-implements-new-jascript-ecmascript-5-methods-for-older/2916063#2916063 –

Antwort

40

Crockford recommends diese Art von Object.create Shim:

if (typeof Object.create != "function") { 
    Object.create = function (o) { 
    function F(){} 
    F.prototype = o; 
    return new F; 
    }; 
} 

Aber bitte Sie diese nicht tun.

Das Problem bei diesem Ansatz ist, dass ES5 Object.create eine Signatur von 2 Argumenten hat: Erstens - ein Objekt aus zu erben, und die zweite (optional) - ein Objekt darstellt Eigenschaften (oder besser gesagt, Deskriptoren) neu hinzufügen erstelltes Objekt

Object.create(O[, Properties]); // see 15.2.3.5, ECMA-262 5th ed. 

Was wir haben, ist eine uneinheitliche Umsetzung mit 2 verschiedenen Verhaltensweisen. In Umgebungen mit dem systemeigenen Code Object.create kann die Methode das zweite Argument behandeln. in Umgebungen ohne native Object.create, tut es nicht.

Was sind die praktischen Auswirkungen?

Nun, wenn es ein Code ist (sagen wir, ein Dritter-Skript), die will Object.create verwenden, es ist eher zumutbar, dass Code, dies zu tun:

if (Object.create) { 
    var child = Object.create(parent, properties); 
} 

- im Wesentlichen davon aus, dass, wenn Object.create existiert, muss Spezifikationen entsprechen - zweites Argument akzeptieren und einem Objekt entsprechende Eigenschaften hinzufügen.

Aber mit der oben genannten Shim, zweites Argument wird einfach ignoriert. Es gibt nicht einmal einen Hinweis auf etwas falsch anders. Ein stiller Fehler, sozusagen - etwas, das ziemlich schmerzhaft zu erkennen und zu beheben ist.

Können wir es besser machen?

Nun, es ist eigentlich unmöglich, eine vollständig konforme Object.create Shim mit nur (Standard) ES3-Einrichtungen zu erstellen. Die beste Lösung besteht darin, eine benutzerdefinierte Wrappermethode zu erstellen.

Es gibt jedoch einige alternative (suboptimal) Dinge, die Sie ausprobieren können:

1) Benutzer benachrichtigen über Unfähigkeit mit dem zweiten Argument zu arbeiten

if (!Object.create) { 
    Object.create = function (o) { 
    if (arguments.length > 1) { 
     throw Error('second argument is not supported'); 
    } 
    // ... proceed ... 
    }; 
} 

2) Versuchen zweites Argument zu handhaben :

if (!Object.create) { 
    Object.create = function (parent, properties) { 
    function F(){} 
    F.prototype = parent; 
    var obj = new F; 
    if (properties) { 
     // ... augment obj ... 
    } 
    return obj; 
    }; 
} 

Beachten Sie, dass „Eigenschaften“ ein Objekt Eigenschaftendeskriptoren, nicht nur Eigenschaftsnamen/val darstellen ues, und ist etwas, das zu Unterstützung nicht sehr trivial ist (einige Dinge sind nicht einmal möglich, wie Aufzählbarkeit einer Eigenschaft Controlling):

Object.create(parent, { 
    foo: { 
    value: 'bar', 
    writable: true 
    }, 
    baz: { 
    get: function(){ return 'baz getter'; }, 
    set: function(value){ return 'baz setter'; }, 
    enumerable: true 
    } 
}); 

Die andere Unstimmigkeit in der ursprünglichen Shim ist, dass sie kümmert sich nicht nehmen von übergeordnetes Objekt ist null.

var foo = Object.create(null); 

Dies erzeugt ein Objekt, das [[Prototyp]] ist null; mit anderen Worten, Objekt, das nichts erbt, nicht einmal Object.prototype (von dem alle nativen Objekte in ECMAScript erben).

foo.toString; // undefined 
foo.constructor; // undefined 
// etc. 

Dies ist übrigens nützlich, um "richtige" Hash-Tabellen in ECMAScript zu erstellen.

Es ist möglich, dieses Verhalten zu emulieren, aber nur nicht-standardmäßige Erweiterungen wie "magische" __proto__ Eigenschaft (so Implementierung wäre nicht sehr portabel oder robust). Die Lösung für dieses Problem ist ähnlich: emulieren Sie entweder die ES5-Implementierung vollständig oder informieren Sie über Inkonsistenz/Fehler.

+1

Meine [Xccessors JavaScript-Bibliothek ] (http://github.com/eligrey/Xccessors) stellt die Funktionen "Object.defineProperty" und "Object.defineProperties" zur Verfügung, die Sie für Lösung 2 verwenden können. –

+10

Das ist sehr gut entdeckt und Ihr Wissen über ES5 ist offensichtlich solide, aber ich denke, es ist erwähnenswert, dass der Code von Crockford schon eine ganze Weile vor ES5 liegt: erste Version circa 2006 und die letzte, Anfang 2008. Es ist also ein wenig unaufrichtig, das zu vermuten Er empfiehlt diese Lösung, um ES5 zu überlagern. – neonski

+7

Das letzte Mal habe ich Doug über dieses Shim sprechen vor 3 Monaten gesehen - http: //www.slideshare.net/douglascrockford/javascript-the-good-parts-3292746/36 Das ist etwa 4 Monate nach ES5 wurde offiziell standardisiert (im Dezember 09) und ist definitiv später als 2008. Aber ich will niemanden beschuldigen (sorry wenn es kam so heraus). Wir alle machen Fehler. Die Idee ist, ** den Ansatz ** zu empfehlen und zu erklären warum. – kangax

8

ES5-Shim http://github.com/kriskowal/es5-shim/

Dies war Teil der Narwal Stand-alone-JavaScript-Umgebung, wurde aber auf seinem eigenen ausgebrochen. Es ist ziemlich verdammt reif und präzise.