函数名可以在node.js中配置吗?

Can function names be configured in node.js?

本文关键字:配置 js node 函数      更新时间:2023-09-26

我想写一些javascript来运行客户端和服务器端。我想动态地重命名函数(以帮助调试等)。我有以下代码:

function genericFunction() {}
Object.defineProperty(genericFunction, 'name', {writable: true});
genericFunction.name = 'specificFunction';
console.log(genericFunction.name);

在chrome (v43)这输出"specificFunction"如预期。然而,在node.js (v0.10)中,我得到:

TypeError: Cannot redefined property: name

我做了一些调试,这似乎归结为

的输出之间的差异
console.log(Object.getOwnPropertyDescriptor(function () {}, 'name').configurable);

在chrome上是true,但是node.js输出false。

我对规范的(非常有限的)理解是,对于函数名,可配置的应该总是正确的。我在阅读说明书的时候错过了什么吗?node.js是否使用不同的规范来说明名称不应该是可配置的?还是我偶然发现了一个真正的bug?

Function对象上的.name属性不能在节点v.0.12.2中更改,因为Function对象上的name属性默认为writable: falseconfigurable: false,因此没有办法使其可写。

这与ES6不一致。由于Chrome当前的实现在这方面与ES6一致,我们可以假设node只是落后于V8引擎版本,未来的某个版本将修复这个问题。注意:带有node的--harmony标志也不会改变此行为。


node 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属性,也不能将其重新配置为可写。


在Chrome 44.0.2403.130 m中,你得到这个:

{"value":"f","writable":false,"enumerable":false,"configurable":true }

默认情况下不能写入,但由于它是可配置的,因此可以将其更改为可写,然后在此之后更改name属性。


这可能是因为Chrome运行的是V8引擎的最新版本。根据ES6规范描述,Chrome配置看起来像正确的默认配置。


如果你在最新的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属性在许多引擎中是一个非标准的特性,这使得该属性不可写且不可配置。

在ECMAScript的第6版中,这种情况发生了变化,.name现在是函数实例的正式指定属性。然而,许多引擎还没有采用这种改变。

它可以在你的Chrome浏览器中工作,这表明V8的一个新版本支持这个。考虑更新你的node.js,或者切换到io.js。


函数名可以在node.js中配置吗?

如您所述,没有(或至少目前没有)。

我对规范的(非常有限的)理解是,对于函数名,可配置的应该总是为真。

是的。

我在阅读说明书时错过了什么吗?

node.js使用不同的规范说名称不应该是可配置的吗?

还是我碰到了一个真正的bug?

我会称之为"缺失的功能",而不是bug。Node还没有声称支持ES6,所以虽然他们计划在未来支持,但目前还不是一个真正的bug。