我在箭头函数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);
但我不确定这在不同的浏览器和平台上是否一致。任何人都可以对这种行为给出明确的答案吗?
答案 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 did,y
中的x = y
如何匹配 AssignmentExpression 给定上面的定义,因为y
显然是一个Identifier,看起来它们都不会导致生成 Identifier 。这就是规格真的难以阅读的地方。事实证明,如果你继续这样做,你会到达那里走得很远。路径是(深呼吸):AssignmentExpression→
ConditionalExpression→
LogicalORExpression→
LogicalANDExpression→
BitwiseORExpression→
BitwiseXORExpression→
BitwiseANDExpression→
EqualityExpression→
RelationalExpression→
ShiftExpression→
AdditiveExpression→
MultiplicativeExpression→
ExponentiationExpression→
UnaryExpression→
UpdateExpression→
LeftHandSideExpression→
NewExpression→
MemberExpression→
PrimaryExpression→
IdentifierReference→
Identifier - 哇! [mops brow] 。谢谢Oriol!)
答案 1 :(得分:3)
它没有进一步阐述特殊的解析规则。
他们不是特殊,他们只是不同。 function
表达式是所谓的主表达式,可以出现在代码中的任何位置。它的语法形式function …(…) {…}
非常清楚它包含哪些元素,明确地分隔开始和结束。
相比之下,箭头函数可以使用简洁的主体而不使用块,因此它不会显式分隔。因此,我们需要限制箭头函数体内可能出现的内容以及哪些内容不能解决,以解决包含=>
的标记序列中的歧义。
所以我的问题是,关于箭头函数的优先规则是什么?
基本上,=>
具有相同的"优先级"作为=
赋值运算符。
(我们只是不想调用=>
一个运算符,因为它构造了一个值,而不是在计算运算符后计算结果)
这意味着我们可以在任何可能发生分配的地方放置箭头功能:
这些都是毫不含糊的。模糊的案例更有趣:
yield
运营商必须将箭头函数放在赋值有效的位置也意味着我们不能将它(直接,不分组)作为任何其他(更高优先级)运算符的操作数 - 最值得注意的是not as an operand of logical expressions (||
, &&
)。
箭头函数的主体可以是赋值表达式(包括任何更高优先级),因此=>
是右关联的(就像=
)。将贪婪地解析正文(表达式尽可能长),以便它基本上包含=>
右侧的所有表达式。
唯一不能形成箭头函数的简洁体是yield
表达式(不允许在生成器函数之外)和逗号表达式。