【问题标题】:EcmaScript 6 Map() vs new Map()EcmaScript 6 Map() 与新 Map()
【发布时间】:2014-08-15 08:07:36
【问题描述】:

在 ES6 中创建地图,你应该说Map() 还是new Map()

两者在node --harmony 中似乎都可以正常工作。

草案规范说“Map 构造函数是 %Map% 内在对象和全局对象的 Map 属性的初始值。当 Map 作为函数而不是构造函数调用时,它会使用以下方法初始化其 this 值支持 Map.prototype 内置方法所需的内部状态。”这似乎也表明它们都应该起作用。

鉴于此,Map() 看起来会更好,因为它更短,尽管这是一个主观判断;客观上它们似乎可以互换?

【问题讨论】:

标签: javascript ecmascript-harmony ecmascript-6


【解决方案1】:

虽然当前的浏览器似乎允许在没有new 的情况下使用Map()(如@RobG 的回答所示),但这实际上是不正确的。

由于a stability issue,Node.js v0.10 使用旧版本的 V8(Node.js 中的 JavaScript 引擎),如果您使用 Map(),则不会抛出异常。

Node.js v0.10 使用 V8 v3.14.5,但 the issue with Map() not throwing 仅在 v3.20.12 中修复。

Chrome 使用较新版本的 V8,如果您不使用 new,则会引发错误。我不确定为什么 Firefox 不会抛出错误。


根据目前的草案规范,没有new应该是不可能调用Map()的:

  1. map 成为 this 值。
  2. 如果 Type(map) 不是 Object,则抛出 TypeError 异常。
  3. 如果 map 没有 [[MapData]] 内部槽,则抛出 TypeError 异常。
  4. 如果 map 的 [[MapData]] 内部槽不是未定义的,则抛出 TypeError 异常。

通常在构造函数中,应该创建的对象是this。它要求传递的对象是Map 的一个实例,并且它还没有被初始化([[MapData]] 必须是未定义的)。

显然这是因为it hinders the subclassing of native constructors,这在 ES6 中是可能的。

【讨论】:

  • 对我来说,(草案)规范在 §23.1.1 说:“当 Map 被称为函数而不是构造函数时,它初始化它的 this 值具有支持 Map.prototype 内置方法所需的内部状态”。这不是说它创建了一个Map 的实例吗?如果作为函数调用而不设置它的this,它不是设置为全局对象吗?我不知道。但它确实说“如果 iter 未定义,则返回 map”,并且调用 Map() 返回一个实例。考虑到他们在 ES6 中的影响力和参与度,我怀疑 Mozilla 会搞砸他们的实现,但是……
  • @RobG:本机函数使用的“this”值不会将 undefined/null 转换为全局对象,因此默认为undefined。它所说的在技术上是正确的,但是如果“this”值是由构造函数创建的未初始化的Map 实例,它只会首先运行。我同意 ES6 规范语言不是特别容易阅读,尤其是与 ES5 规范相比。
  • @RobG 如果您阅读github.com/rwaldron/tc39-notes/blob/master/es6/2013-07/…,这会更清楚
  • +1 最后一条评论应该在答案中找到它的方式
【解决方案2】:

编辑

从 ECMAScript 2015(第 6 版)开始,将 Map 作为函数调用(即没有 new)应该会引发错误:

Map 不打算作为函数调用,它会抛出一个 以这种方式调用时出现异常。

ECMA-262 ed 6 §23.1.1

后人的原始答案。

鉴于:

if (typeof Map != 'undefined') {
  var x = Map();
  var y = new Map();

  // x and y have same [[Prototype]]
  console.log(Object.getPrototypeOf(x) === Object.getPrototypeOf(y)); // true

  // x and y have same constructor
  console.log(x.constructor === y.constructor); // true

  // x [[Prototype]] is Map.prototype
  console.log(Object.getPrototypeOf(x) === Map.prototype); // true

  // x.constructor is Map
  console.log(x.constructor === Map); // true
}

在支持 Map 的浏览器中返回 true,看起来两者都返回 Map 的实例,尽管规范可能会超出此范围用更简单的语言来怀疑。

似乎在提供参数时区别很明显:作为函数调用时,参数应该是可迭代对象,而作为构造函数调用时,可以提供多个参数并调用内部[[Construct]] 方法。

编辑

鉴于 ES6 仍处于草案阶段(并且可能会持续一段时间),这种行为可能会改变。在 2013 年 7 月 25 日的 TC39 会议上,讨论了即使在没有 new (Anti–pattern to call a constructor without new) 的情况下调用构造函数时也可以像构造函数一样工作,这不是一个好主意,因此将来可能会对其进行修改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 2018-10-21
    • 2015-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多