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.
Siehe auch http://stackoverflow.com/questions/1890464/is-there-a-library-which-implements-new-jascript-ecmascript-5-methods-for-older/2916063#2916063 –