IE 不支持 function.name。

IT技术 javascript
2021-03-04 12:46:05

最近,我已经成为该function.name物业的忠实粉丝

例如,我编写了一个用于扩展原型的函数。

它的工作方式是..

Array.give(
    function forEach() { ... }
);

..这会让你做..

['a', 'b', 'c'].forEach(function () { ... });

这段代码在 Chrome、Safari、Firefox 和 Opera 中运行良好,但不适用于 IE。

经过一点点挖掘,我意识到给函数,function.name只是返回undefined,而在其他一切中它返回"forEach"

有没有其他方法可以在 IE 中获得这个名字,还是我应该对这个美妙的属性失去兴趣?

5个回答

您可以使用 Object.defineProperty 在 IE9+ 上添加对它的支持

// Fix Function#name on browsers that do not support it (IE):
if (!(function f() {}).name) {
    Object.defineProperty(Function.prototype, 'name', {
        get: function() {
            var name = (this.toString().match(/^function\s*([^\s(]+)/) || [])[1];
            // For better performance only parse once, and then cache the
            // result through a new accessor for repeated access.
            Object.defineProperty(this, 'name', { value: name });
            return name;
        }
    });
}
如果函数名称有 unicode 字符,您可能想要使用 \S* 而不是 \w*
2021-04-25 12:46:05
@alex 我不知道函数名可以有 unicode 名称。你确定是这样吗?
2021-04-28 12:46:05
我已将正则表达式更改为在所有这些情况下都能正常工作:function() {}、function () {}、function test() {}、function test () {}
2021-04-30 12:46:05
@JohnArcher 我已经调整了代码以适应这种情况。谢谢你指出!
2021-05-06 12:46:05
函数名是一个标识符,标识符符合 7.6 ES5 规范,其中包括 unicode。此外,jquery 有 '$' 作为函数名,而 \w 也不会匹配它。
2021-05-16 12:46:05

您也许可以通过调用function.toString [docs]来解析函数名称function.name不是一个标准特性

var name = func.toString().match(/^function\s*([^\s(]+)/)[1];

正如评论中所说,这不一定是可靠的方式。Imo 传递一个对象会更容易阅读,你可以一次传递几个方法:

Array.give({
    forEach: function() { ... },
    somethingElse: function() {...}
});
@TimDown 为什么它不起作用?如果发现之间没有名字function(,则名称可以被假定为""是相同的结果与(function() {}).name在系统中Function.name 支持。这似乎可以在 100% 的时间内工作(尽管对于大型功能来说可能会很慢)。是否存在结果Function.toString()不包含的系统"function ...()"
2021-04-23 12:46:05
我强烈建议不要通过解析函数toString()方法的输出来获取名称。没有任何保证。
2021-05-01 12:46:05
@ricosrealm:我更新了表达式以忽略空白字符。
2021-05-11 12:46:05
我认为从 IE 的 toString 表示中可靠地解析 func 名称并不难。空白不能是函数标签的一部分。
2021-05-12 12:46:05
@Tim:这就是我说可能的原因;) 但无论如何,规范说:返回函数的依赖于实现的表示。此表示具有 FunctionDeclaration 的语法。请特别注意,表示字符串中空格、行终止符和分号的使用和放置取决于实现。因此,至少根据规范,该toString方法将函数声明作为字符串返回,这意味着有一些保证。我猜可以处理空白区域...
2021-05-19 12:46:05

我认为您的.give()解决方案有点……冗长。有什么问题:

Array.prototype.forEach = function () { ... };

?

但是,实际上,您应该在提供自己的方法之前检查这种方法是否存在:

Array.prototype.forEach = Array.prototype.forEach || function () { ... };

由于其他人会被function.name带到这里想知道,所以有一种方法可以获取名称(显然,它不适用于匿名函数):

function getFnName(fn) {
    return (fn.toString().match(/function (.+?)\(/)||[,''])[1];
}
Array.prototype.forEach || ( Array.prototype.forEach = function () { ... } );
2021-04-21 12:46:05
我从来没有问过任何关于扩展原型的问题。这只是 function.name 如何有用的一个例子。而已。整个事情中唯一的问题是询问您可以在 IE 中使用的替代方案,这意味着您的答案应该涵盖所有内容。如果我想覆盖本地人,我会,因为这是我自己的编码风格。你没有理由反对。
2021-04-22 12:46:05
泰勒,我想有一种方法可以在不谈论你的Object.prototype.give增强的情况下问这个问题,而只是坚持这个Fn.name部分。你有点想它来了。(你甚至知道它并说“继续,开枪打我”......)我认为你不能指望开发人员不会用这样的东西开枪打你。:)
2021-05-06 12:46:05
@tylerwashburn,我只是想帮忙。把你的愤怒带到别处。
2021-05-12 12:46:05
这实际上与实际问题无关。-1
2021-05-18 12:46:05

对于那些在同一条船上的人,请查看 JamesMGreene 的Function.name polyfill 这看起来是一个很好的解决方案。

老问题,我不知道这是否适用于本机 IE 7 和 8 浏览器(我使用的是开发人员工具模拟器),但我之前在构造函数上为函数提供了一个名称属性,用于诱导 IE 代码。 ...

function sayMyName(func){
    var name=func.name || func.constructor.name
    alert(name);

}

var ieGivesMeNightTerrors=function(){
    //there there, these ugly workarounds aren't your fault
};
ieGivesMeNightTerrors.constructor.name=ieGivesMeNightTerrors;
sayMyName(myFunc);
“sayMyName”...大声笑
2021-04-22 12:46:05