Javascript中箭头函数(胖箭头=>)的确切解析优先级是什么?

时间:2018-05-22 07:13:09

标签: javascript ecmascript-6

我在箭头函数eslint documentation上看到了一个示例:

// The intent is not clear
var x = a => 1 ? 2 : 3;

所以我研究了一下箭头函数的优先级。似乎=>不被视为运算符,因为它不能在table of operator precedence on MDN上找到。从页面arrow functions,它说

  

箭头函数具有特殊的解析规则,与常规函数相比,它们与运算符优先级的交互方式不同。

但它没有进一步阐述特殊解析规则。所以我的问题是,关于箭头函数的优先规则是什么?

根据我的测试,似乎它的优先级高于赋值,但低于条件(三元)运算符?

var x = 0, a = 5;
console.log(x = a => 1 ? 2 : 3);
// same as x = (a => (1 ? 2 : 3))
console.log(x);
console.log(a);

但我不确定这在不同的浏览器和平台上是否一致。任何人都可以对这种行为给出明确的答案吗?

2 个答案:

答案 0 :(得分:6)

正如您所说,=>不是运营商。箭头函数是主要语法。

规则中定义了它们的规则,从ArrowFunction production开始。您使用ConciseBody询问表单,=> 之后的第一个非空白标记不是 {(表示详细信息)身体)。 ConciseBody 定义非常简单:与AssignmentExpression匹配的任何内容。

这使我们进入了一个非常熟悉的领域,因为 AssignmentExpression 是赋值(或变量初始值设定项)右侧的语法,数组初始值设定项中的条目,属性的值部分初始化程序,函数的参数等等。所以无论如何,简洁体中的=>都具有与我们在AssignmentExpression所在的位置相同的解析规则:

x = AssignmentExpression;
y = AssignmentExpression, z = AssignmentExpression;
a1 = [AssignmentExpression];
a2 = [AssignmentExpression, AssignmentExpression];
o1 = {foo: AssignmentExpression};
o2 = {foo: AssignmentExpression, bar: AssignmentExpression};
doSomething(AssignmentExpression);
doSomething(AssignmentExpression, AssignmentExpression);

仅供参考, AssignmentExpression 是以下任何一种:

(您可能想知道,as I didy中的x = y如何匹配 AssignmentExpression 给定上面的定义,因为y显然是一个Identifier,看起来它们都不会导致生成 Identifier 。这就是规格真的难以阅读的地方。事实证明,如果你继续这样做,你会到达那里走得很远。路径是(深呼吸):AssignmentExpressionConditionalExpressionLogicalORExpressionLogicalANDExpressionBitwiseORExpressionBitwiseXORExpressionBitwiseANDExpressionEqualityExpressionRelationalExpressionShiftExpressionAdditiveExpressionMultiplicativeExpressionExponentiationExpressionUnaryExpressionUpdateExpressionLeftHandSideExpressionNewExpressionMemberExpressionPrimaryExpressionIdentifierReferenceIdentifier - 哇! [mops brow] 。谢谢Oriol!)

答案 1 :(得分:3)

  

它没有进一步阐述特殊的解析规则。

他们不是特殊,他们只是不同。 function表达式是所谓的主表达式,可以出现在代码中的任何位置。它的语法形式function …(…) {…}非常清楚它包含哪些元素,明确地分隔开始和结束。

相比之下,箭头函数可以使用简洁的主体而不使用块,因此它不会显式分隔。因此,我们需要限制箭头函数体内可能出现的内容以及哪些内容不能解决,以解决包含=>的标记序列中的歧义。

  

所以我的问题是,关于箭头函数的优先规则是什么?

基本上,=>具有相同的"优先级"作为=赋值运算符。
(我们只是不想调用=>一个运算符,因为它构造了一个值,而不是在计算运算符后计算结果)

这意味着我们可以在任何可能发生分配的地方放置箭头功能:

  • 作为数组或对象文字中的元素值
  • 作为默认初始化程序(解构,函数参数)
  • 作为变量初始化程序
  • 作为表达式语句或循环标题
  • 作为函数参数
  • 作为分组表达式

这些都是毫不含糊的。模糊的案例更有趣:

  • 在作业的右侧
  • 位于条件运算符的右侧
  • 位于yield运营商
  • 的右侧
  • 在逗号运算符的任何一侧

必须将箭头函数放在赋值有效的位置也意味着我们不能将它(直接,不分组)作为任何其他(更高优先级)运算符的操作数 - 最值得注意的是not as an operand of logical expressions (||, &&)

箭头函数的主体可以是赋值表达式(包括任何更高优先级),因此=>是右关联的(就像=)。将贪婪地解析正文(表达式尽可能长),以便它基本上包含=>右侧的所有表达式。

唯一不能形成箭头函数的简洁体是yield表达式(不允许在生成器函数之外)和逗号表达式。