是否可以在JavaScript中设置运行时的函数名称?
var ctor = function() {}; // Anonymous function because I don't know the name ahead of runtime.
ctor.name = 'foo'; // Pseudocode - this is effectively what I want to do
我希望以上内容相当于:
var ctor = function foo() {};
修改
以下是一个用例示例:
function mix(fn1, fn2, name) {
var ctor = function() {};
ctor.name = name; // Vain attempt to set the name of the function.
ctor.prototype = Object.create(fn1.prototype);
Object.keys(fn2.prototype).map(function(k) {
ctor.prototype[k] = fn2.prototype[k];
});
// Return a constructor function with the prototype configured.
return ctor;
}
function Foo() {}
Foo.prototype.foo = function(){};
function Bar(){}
Bar.prototype.bar = function() {};
var Foobar = mix(Foo, Bar, 'Foobar');
console.log(new Foobar()); // ctor {bar: function, foo: function} (in Chrome) - I wanted Foobar { bar: function, foo: function }
答案 0 :(得分:3)
name
只是某些浏览器支持的非标准版。
现在,它已经在ECMAScript 6中标准化了:
name
属性的值是一个描述的属性的String 功能。该名称没有语义意义,但通常是一个 变量或属性名称,用于引用其中的函数 ECMAScript代码中的定义点。这家酒店有 属性{[[可写]]:错误,[[可枚举]]:错误, [[Configurable]]: true }。匿名函数没有上下文名称的对象 与此规范相关联的没有
name
拥有 property,但继承%FunctionPrototype%。{/ p>的name
属性
因此,您的代码将适用于不支持name
的浏览器,但新属性将是可写且可枚举的。在支持它的浏览器上,您的代码无法正常工作,因为name
不可写。
因此,更好的等效代码将是
Object.defineProperty(ctor, 'name', {
value: 'foo',
configurable: true
});
答案 1 :(得分:0)
免责声明:对于那些喜欢其代码安全且可预测的人来说,这可能会让您感到不安。
当然,你实际上不会这样做,因为你是明智的,对吗?
function rename(fn, name) {
var fnStr = fn.toString().replace(/function/, 'function ' + name);
eval.call(window, fnStr);
return window[name];
}
var tmp = function(a, b) { return a + b; };
rename(tmp, 'add');
add(3, 4); // 7
当然,根据您需要(如果使用eval不是很好)的表现,你可以(但你不会)走一步进一步。
Function.prototype.rename = function(name) {
return rename(this, name);
};
在实际代码中执行此操作,人们会讨厌你,但是没关系,因为你不会。
与定义函数的范围有一些小问题(可能还有一些破坏边缘情况)。 Eval使用this的上下文来决定在哪个范围内操作,因此传递window对象意味着重命名的函数将始终在window对象中定义。
相当人为的例子,但它应该让你对陷阱有所了解。
function init() {
function go() {
return 'go';
};
var ctor = function() {
return 'ctor';
};
rename(ctor, 'go');
go(); // 'go'
next();
}
function next() {
go(); // 'ctor'
}