如何判断函数对象是否使用胖箭头表达式?

时间:2018-02-18 23:42:55

标签: javascript

我正在创建一个将对象作为参数的函数,并使用存储在该对象中的数据执行操作。我想做的一些涉及该对象的功能。我想将它们中的大多数绑定到各种对象,但这对于使用fat arrow syntax创建的任何函数都不起作用。所以,我想做些与他们不同的事情。我怎么能分开呢?

注意:我知道正常的函数有一个原型但是由胖箭头语法制作的函数没有,但是我不能使用它,因为用method syntax创建的函数也没有。有一个原型,但它们可以绑定,所以我想像其他功能一样对待它们。

1 个答案:

答案 0 :(得分:3)

您可以使用Function#toString()检查函数的源代码,看看它是否被定义为箭头函数。

const foo = () => {};
const fooStr = Function.prototype.toString.call(foo);
const isArrow = fooStr.includes(') => {');

请注意,上述实现对于大多数用例来说可能过于天真,因为它有一些误报和否定。对于初学者,如果isArrow是包含箭头功能的正常函数(或者在其中的任何位置具有该特定字符串,例如注释等),则true将为foo

我们可以通过尝试特别匹配函数定义的头来改进这一点。下面,我通过搜索大括号{的第一次出现来做到这一点,这对于箭头和非箭头函数都是通用的。

const foo = () => {};
const fooStr = Function.prototype.toString.call(foo);
const curlyIndex = fooStr.indexOf('{');
const head = fooStr.substring(0, Math.max(curlyIndex, 0));
const isArrow = head.endsWith(') => {');

不幸的是,对于我们来说,圆形和花括号实际上都是箭头功能的可选项,它们甚至不需要任何空格。理想情况下,我们需要在foox=>x时才有效的内容。

const foo = x=>x;
const fooStr = Function.prototype.toString.call(foo);
const curlyIndex = fooStr.indexOf('{');
let isArrow = true;
if (curlyIndex >= 0) {
    const head = fooStr.substring(0, curlyIndex);
    isArrow = head.replace(/\s/g, '').endsWith('=>{');
}

上述实现方式中等,但当foo类似于x => x + '{'时,它仍然存在误报。还有其他陷阱,所以不要认为它在那里结束。字符串分析很难,特别是当语法是可选的时。

您可以使用EsprimaAcornCherow这样的库来解析字符串,并更完美地识别代码是否为箭头函数,但这可能是过度的你。

为了让您了解它的外观,下面是我输入空箭头功能时Cherow demo的输出:

{
    "type": "Program",
    "sourceType": "script",
    "body": [
        {
            "type": "ExpressionStatement",
            "expression": {
                "type": "ArrowFunctionExpression",
                "body": {
                    "type": "BlockStatement",
                    "body": []
                },
                "params": [],
                "id": null,
                "async": false,
                "generator": false,
                "expression": false
            }
        }
    ]
}