为什么在chrome / node中不是Map可分类? [英] Why isn't Map subclassable in chrome/node?

查看:101
本文介绍了为什么在chrome / node中不是Map可分类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以ES 6正在带给我们地图(而且也不会太快)。希望为我自己的恶意目的子类化Map,我尝试了以下(缩写为清楚):

So ES 6 is bringing us Maps (and none too soon). Wishing to subclass Map for my own nefarious purposes, I tried the following (abbreviated for clarity):

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

var bar = new Foo();

在V8环境中,这会抛出一个错误地图构造函数未使用'new'调用。为什么? SpiderMonkey得到这个正确:

In V8 environments this throws an Error "Map constructor not called with 'new'". Why? SpiderMonkey gets this 'right':

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

将按预期产生bar。在SpiderMonkey和V8中,尝试像

will, as expected, yield 'bar'. In both SpiderMonkey and V8 attempting something like

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

将失败:在不兼容的对象上调用方法集。那就是继承模式。据我所知,从规范(我没有太多的spec-foo),实际的Map对象具有不可访问的内部属性,这些属性是他们正常工作所必需的。但为什么V8会在第一个模式上抛出错误?这似乎是一个奇怪的决定,特别是当它按照预期在FF工作时。

will fail: 'method set called on incompatible object'. So there goes that inheritance pattern. As far as I can tell from the spec (I don't have much spec-foo), actual Map objects have internal properties that are not accessible that are required for them to work properly. But why does V8 throw an error on the first pattern? This seems like an odd decision, especially when it works as expected in FF.

更新:我注意到FF和chrome都有 Object.setPrototypeOf 实现。为了防止任何人绊倒,想到这一点,我可以告诉你它失败了。以下两个失败原因不同:

UPDATE: I noticed that FF and chrome both have Object.setPrototypeOf implemented. Just in case anyone stumbles across this and thinks of that, I can tell you it fails. Both of the following fail for different reasons:

//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



扩展地图的四种方法(一些来自以下答案/评论):

TL;DR

There are basically four ways to extend map (some from answers/comments below):


  1. 添加Map.prototype(羞耻)的方法。 li>
  2. 工厂/构造函数使对象具有您委托给

  3. 将属性复制到地图上的内部Map实例:



function Foo(){this.bar = 'boo!'}
var baz = new Map();
Foo.call(baz);
baz.bar; //yields 'boo!'
baz.set('5', 5).get('5'); //yields 5

或者只是等待ES 6类打到你关心的平台

Or just wait for ES 6 classes to hit the platform(s) you care about

推荐答案


在V8环境中,会抛出一个错误地图构造函数未使用'new'调用。为什么?

In V8 environments this throws an Error "Map constructor not called with 'new'". Why?

因为新的ES6类(包括内置的)应该只能使用 new

Because new ES6 classes (including builtin ones) are supposed to be only constructable with new.


SpiderMonkey得到这个正确

SpiderMonkey gets this 'right'

不完全是规格明确表示


映射不是作为一个函数调用,并在调用时抛出异常这种方式。

Map is not intended to be called as a function and will throw an exception when called in that manner.


希望子类Map

Wishing to subclass Map

是的,这是适当的:


Map 构造函数被设计为子类化。它可以用作定义的 extends 子句中的值。打算继承指定的 Map 行为的子类构造函数必须包含一个 super 调用Map构造函数来创建和初始化具有支持 Map.prototype 内置方法所需的内部状态的子类实例。

The Map constructor is designed to be subclassable. It may be used as the value in an extends clause of a class definition. Subclass constructors that intend to inherit the specified Map behaviour must include a super call to the Map constructor to create and initialize the subclass instance with the internal state necessary to support the Map.prototype built-in methods.

所以你需要使用

class Foo extends Map {
    // default constructor
}
var bar = new Foo();
bar.set('foo', 'bar');

这篇关于为什么在chrome / node中不是Map可分类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆