MongoDB 2.4 中的 JavaScript 更改

在本页面

考虑V8 JavaScript 引擎在 MongoDB 2.4 中的以下影响:

Tip

mongo shell 中使用新的interpreterVersion()方法,在db.serverBuildInfo()的输出中使用javascriptEngine字段,以确定 MongoDB 二进制文件使用哪个 JavaScript 引擎。

Improved Concurrency

以前,需要 JavaScript 解释器的 MongoDB 操作必须获得一个锁,并且一个mongod一次只能运行一个 JavaScript 操作。切换到 V8 通过允许同时运行多个 JavaScript 操作来提高并发性。

现代化的 JavaScript 实现(ES5)

ECMAscript的第五版(缩写为 ES5)增加了许多新的语言功能,包括:

使用 V8,MongoDB 支持 Javascript 的 ES5 实现,但以下情况除外。

Note

以下功能在 从 MongoDB 查询返回的文档 中无法正常工作:

  • Object.seal()从 MongoDB 查询返回的文档上引发异常。

  • Object.freeze()从 MongoDB 查询返回的文档上引发异常。

  • Object.preventExtensions()错误地允许在从 MongoDB 查询返回的文档中添加新属性。

  • enumerable属性,当添加到 MongoDB 查询返回的文档中时,在写操作期间不会保存。

有关更多信息,请参见SERVER-8216SERVER-8223SERVER-8215SERVER-8214

对于尚未从 MongoDB 查询返回的对象,这些功能将按预期工作。

删除了非标准 SpiderMonkey 功能

V8 不支持以下非标准的SpiderMonkey JavaScript 扩展,以前由 MongoDB 使用 SpiderMonkey 作为其 JavaScript 引擎来支持。

E4X Extensions

V8 不支持非标准 E4Xextensions。 E4X 为 JavaScript 语言提供了本机XML对象,并添加了将 LiteralsXML 文档嵌入 JavaScript 代码中的语法。

如果使用以下任何构造函数/方法,则需要使用替代 XML 处理:

Destructuring Assignment

V8 不支持非标准的销毁分配。解构分配“使用镜像数组和对象常量的语法从数组或对象中提取数据”。 -Mozilla docs

Example

以下解构分配对于 V8 来说是“无效”的,并抛出SyntaxError

original = [4, 8, 15];
var [b, ,c] = a;  // <== destructuring assignment
print(b) // 4
print(c) // 15

Iterator(),StopIteration()和 Generators

V8 不支持Iterator(),StopIteration()和生成器

InternalError()

V8 不支持InternalError()。请改用Error()

每个...在构造中

V8 不支持使用for each…in构造。请改用for (var x in y)构造。

Example

以下for each (var x in y)构造对于 V8 是**无效的:

var o = { name: 'MongoDB', version: 2.4 };

for each (var value in o) {
print(value);
}

相反,在版本 2.4 中,可以使用for (var x in y)构造:

var o = { name: 'MongoDB', version: 2.4 };

for (var prop in o) {
var value = o[prop];
print(value);
}

您还可以将数组* instance *方法forEach()与 ES5 方法Object.keys()结合使用:

Object.keys(o).forEach(function (key) {
var value = o[key];
print(value);
});

Array Comprehension

V8 不支持Array comprehensions

使用其他方法,例如Array实例方法map()filter()forEach()

Example

对于 V8,以下数组推导是 无效的

var a = { w: 1, x: 2, y: 3, z: 4 }

var arr = [i * i for each (i in a) if (i > 2)]
printjson(arr)

相反,您可以使用Array * instance *方法forEach()和 ES5 方法Object.keys()来实现:

var a = { w: 1, x: 2, y: 3, z: 4 }

var arr = [];
Object.keys(a).forEach(function (key) {
var val = a[key];
if (val > 2) arr.push(val * val);
})
printjson(arr)

Note

新逻辑使用Array * instance 方法forEach()而不是 generic *方法Array.forEach(); V8 不支持Array通用方法。有关更多信息,请参见数组通用方法

多个捕获块

V8 不支持多个catch块,将抛出SyntaxError

Example

以下多个 catch 块在 V8 上是“无效”的,将抛出"SyntaxError: Unexpected token if"

try {
something()
} catch (err if err instanceof SomeError) {
print('some error')
} catch (err) {
print('standard error')
}

条件函数定义

V8 会产生与 SpiderMonkey 条件函数定义不同的结果。

Example

以下条件函数定义在 SpiderMonkey 与 V8 中产生不同的结果:

function test () {
if (false) {
function go () {};
}
print(typeof go)
}

对于 SpiderMonkey,条件函数输出undefined,而对于 V8,条件函数输出function

如果您的代码以这种方式定义函数,则强烈建议您重构代码。以下示例重构了条件函数定义,使其可同时在 SpiderMonkey 和 V8 中使用。

function test () {
var go;
if (false) {
go = function () {}
}
print(typeof go)
}

重构的代码在 SpiderMonkey 和 V8 中都输出undefined

Note

ECMAscript 禁止条件函数定义。强制 V8 抛出Error启用严格模式

function test () {
'use strict';

if (false) {
function go () {}
}
}

JavaScript 代码引发以下语法错误:

SyntaxError: In strict mode code, functions can only be declared at top level or immediately within another function.

字符串通用方法

V8 不支持String generics。字符串泛型是String类上反映实例方法的一组方法。

Example

通用方法String.toLowerCase()的以下用法在 V8 中“无效”:

var name = 'MongoDB';

var lower = String.toLowerCase(name);

在 V8 中,请使用String类的* instance *可用的String实例方法toLowerCase()

var name = 'MongoDB';

var lower = name.toLowerCase();
print(name + ' becomes ' + lower);

在 V8 中,请使用String * instance 方法而不是以下 generic *方法:

String.charAt() String.quote() String.toLocaleLowerCase()
String.charCodeAt() String.replace() String.toLocaleUpperCase()
String.concat() String.search() String.toLowerCase()
String.endsWith() String.slice() String.toUpperCase()
String.indexOf() String.split() String.trim()
String.lastIndexOf() String.startsWith() String.trimLeft()
String.localeCompare() String.substr() String.trimRight()
String.match() String.substring()

数组通用方法

V8 不支持数组通用方法。数组泛型是Array类上反映实例方法的一组方法。

Example

通用方法Array.every()的以下用法在 V8 中“无效”:

var arr = [4, 8, 15, 16, 23, 42];

function isEven (val) {
return 0 === val % 2;
}

var allEven = Array.every(arr, isEven);
print(allEven);

在 V8 中,请使用Array类的* instance *可用的Array实例方法every()

var allEven = arr.every(isEven);
print(allEven);

在 V8 中,请使用Array * instance 方法而不是以下 generic *方法:

Array.concat() Array.lastIndexOf() Array.slice()
Array.every() Array.map() Array.some()
Array.filter() Array.pop() Array.sort()
Array.forEach() Array.push() Array.splice()
Array.indexOf() Array.reverse() Array.unshift()
Array.join() Array.shift()

数组实例方法 toSource()

V8 不支持Array实例方法toSource()。请改用Array实例方法toString()

uneval()

V8 不支持非标准方法uneval()。请改用标准化的JSON.stringify()方法。

首页