函数名可以在node.js中configuration吗?
我试图写一些JavaScript来运行客户端和服务器端。 我想dynamic重命名函数(以帮助debugging等)。 我有以下代码:
function genericFunction() {} Object.defineProperty(genericFunction, 'name', {writable: true}); genericFunction.name = 'specificFunction'; console.log(genericFunction.name);
在铬(v43)中,如预期的那样输出“特定function”。 但是,在node.js(v0.10)中,我得到:
TypeError:无法重新定义属性:名称
我已经做了一些debugging,这似乎是不同的输出之间的差异
console.log(Object.getOwnPropertyDescriptor(function () {}, 'name').configurable);
在铬是真的,但node.js输出false。
我对规范的理解(非常有限)是对于函数名称,可configuration应该始终为真。 我在阅读规范时错过了什么? node.js是否使用不同的规范说,名称不应该是可configuration的? 还是我绊倒了一个真正的bug?
Function对象的.name
属性在节点v.0.12.2中不能被改变,因为Function对象的name属性默认是writable: false
和可configurable: false
所以没有办法使它成为可写的。
这不符合ES6。 由于目前Chrome的实现与ES6在这方面是一致的,所以我们可以假设节点刚刚落后于V8引擎版本,而一些未来的版本将会解决这个问题。 注意:带节点的--harmony
标志也不会改变这种行为。
以下是节点v.0.12.2和Chrome 44.0.2403.130 m之间的技术差异。
在节点v.0.12.2中,如果你这样做:
function f() {} console.log(Object.getOwnPropertyDescriptor(f, "name"));
它输出:
{value: 'f', writable: false, enumerable: false, configurable: false}
正如你所看到的,你不能写入.name
属性,你不能重新configuration它是可写的。
在Chrome 44.0.2403.130米,你得到这个:
{"value":"f","writable":false,"enumerable":false,"configurable":true }
您不能默认写入,但是由于它是可configuration的,您可以将其更改为可写,然后在此之后更改name属性。
这大概是因为Chrome正在运行更新版本的V8引擎。 根据ES6规范描述 ,Chromeconfiguration看起来像正确的默认设置。
如果你在最新的Chrome中运行这个代码,你可以看到它的工作原理:
function f() {} var alias = f; log(Object.getOwnPropertyDescriptor(f, "name")); // this name change will not work because writable === false log(alias.name); f.name = "foo"; log(alias.name); // change writable to true Object.defineProperty(f, "name", {writable: true}); log(Object.getOwnPropertyDescriptor(f, "name")); // this name change will work f.name = "foo"; log(alias.name); // utility function to put output into main window for snippet function log(args) { var str = ""; for (var i = 0; i < arguments.length; i++) { if (typeof arguments[i] === "object") { str += JSON.stringify(arguments[i]); } else { str += arguments[i]; } } var div = document.createElement("div"); div.innerHTML = str; var target = log.id ? document.getElementById(log.id) : document.body; target.appendChild(div); }
虽然以前没有指定,但是函数的.name
属性在许多引擎中是非标准的特性,这使得该属性不可写和不可configuration。
随着ECMAScript的第六版,这已经改变了,而.name
现在是函数实例的一个正式指定的属性。 但是,很多引擎还没有采用这种变化。
它可以在Chrome浏览器中运行,这意味着V8的一个新版本支持这一点。 考虑更新你的node.js,或切换到io.js.
函数名可以在node.js中configuration吗?
正如你所build立的,没有(或至less不是现在)。
我对规范的理解(非常有限)是对于函数名称,可configuration应该始终为真。
是。
我在阅读规范时错过了什么?
没有。
node.js是否使用不同的规范说,名称不应该是可configuration的?
没有。
还是我绊倒了一个真正的bug?
我把它称为“缺less的function”,而不是一个错误。 Node并没有声称支持ES6,所以虽然他们打算今后做,但目前并不是一个真正的bug。