为什么在chrome / node中不是Map可分类? [英] Why isn't Map subclassable in chrome/node?
问题描述
所以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):
- 添加Map.prototype(羞耻)的方法。 li>
- 工厂/构造函数使对象具有您委托给
- 将属性复制到地图上的内部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 anextends
clause of aclass
definition. Subclass constructors that intend to inherit the specifiedMap
behaviour must include asuper
call to the Map constructor to create and initialize the subclass instance with the internal state necessary to support theMap.prototype
built-in methods.
所以你需要使用
class Foo extends Map {
// default constructor
}
var bar = new Foo();
bar.set('foo', 'bar');
这篇关于为什么在chrome / node中不是Map可分类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!