Warum ist Map in Chrome / Node nicht unterklassifizierbar?

So ES 6 bringt uns Maps (und keine zu früh). Um Map für meine eigenen schändlichen Zwecke zu unterteilen, habe ich Folgendes versucht (aus Gründen der Klarheit abgekürzt):

function Foo() {
    return Map.apply(this, [].slice.call(arguments));
}

var bar = new Foo();

n V8-Umgebungen wird der Fehler "Map-Konstruktor nicht mit 'new' aufgerufen" ausgegeben. Warum? SpiderMonkey erhält dieses "Recht":

Map.call({}, [['foo', 'bar']]).get('foo');

wird, wie erwartet, "bar" ergeben. Versuchen Sie in SpiderMonkey und V8 etwas wie

function Foo() {};
Foo.prototype = new Map();
var bar = new Foo();
bar.set('foo', 'bar');

wird fehlschlagen: 'Methodensatz für inkompatibles Objekt aufgerufen'. So geht es das Vererbungsmuster. Soweit ich das am @ erkennen ka spec (Ich habe nicht viel spec-foo), tatsächliche Map-Objekte haben interne Eigenschaften, auf die nicht zugegriffen werden kann, damit sie ordnungsgemäß funktionieren. Aber warum wirft V8 einen Fehler auf das erste Muster? Dies scheint eine seltsame Entscheidung zu sein, besonders wenn es in FF wie erwartet funktioniert.

UPDATE: Mir ist aufgefallen, dass sowohl FF als auch Chrome @ habeObject.setPrototypeOf implementiert. Nur für den Fall, dass jemand darüber stolpert und darüber nachdenkt, kann ich Ihnen sagen, dass es fehlschlägt. Beide der folgenden Probleme schlagen aus unterschiedlichen Gründen fehl:

//this totally fails, even for custom constructors/objects
var Foo = function(){};
Object.setPrototypeOf(Foo, Map.prototype);
var bar = new Foo(); //bar doesn't have any of the Map properties/methods

//this one has the methods but still throws the 'incompatible object'
//err. Also fails with new Map() instead of Map.prototype
var bar = Object.setPrototypeOf({}, Map.prototype); 
TL; DR

Es gibt grundsätzlich vier Möglichkeiten, die Karte zu erweitern (einige von Antworten / Kommentaren unten):

Füge Methoden zu Map.prototype hinzu (schade um dich). Factory / constructor erstellt Objekte mit einer internen Map-Instanz, die Sie an @ delegiereMixin fn, das Eigenschaften auf Maps kopiert:
function Foo(){this.bar = 'boo!'}
var baz = new Map();
Foo.call(baz);
baz.bar; //yields 'boo!'
baz.set('5', 5).get('5'); //yields 5

Oder warten Sie einfach, bis die ES 6-Klassen die Plattform (en) erreichen, die Ihnen am Herzen liegen.

Antworten auf die Frage(8)

Ihre Antwort auf die Frage