在JavaScript中设置运行时函数的名称

时间:2015-03-04 18:20:18

标签: javascript

是否可以在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 }

2 个答案:

答案 0 :(得分:3)

name只是某些浏览器支持的非标准版。

现在,它已经在ECMAScript 6中标准化了:

  

19.2.4.2 name

     

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'
}