ES6立即调用箭头function
为什么在Node.js
控制台(在4.1.1和5.3.0中testing)中工作,但在浏览器中不工作(在Chrome中testing)? 这个代码块应该创build并调用一个loggingOk
的匿名函数。
() => { console.log('Ok'); }()
另外,虽然上述在Node中工作,但这不起作用:
n => { console.log('Ok'); }()
也不是这样:
(n) => { console.log('Ok'); }()
奇怪的是,当参数被添加时,它实际上会在立即调用的部分抛出一个SyntaxError
。
你需要使它成为一个函数expression式,而不是函数定义 ,它不需要名称,并使其成为一个有效的JavaScript。
(() => { console.log('Ok'); })()
相当于IIFE
(function(){ console.log('Ok') })();
为什么在Node.js中工作,而不是在chrome中可能的原因是它的parsing器把它解释为一个自我执行的函数,因为这个
function() { console.log('hello'); }();
在Node.js
工作正常这是一个函数expression式,并且chrome和firefox和大部分浏览器都是这样解释的。 你需要手动调用它。
告诉parsing器预期函数expression式的最普遍的方法就是将其包装在parens中,因为在JavaScript中,parens不能包含语句。 此时,当parsing器遇到函数关键字时,它知道将其parsing为函数expression式而不是函数声明。
关于参数化版本 ,这将工作。
((n) => { console.log('Ok'); })()
这些都不应该没有括号。
为什么?
因为根据规范:
- ArrowFunction 列在AssignmentExpression下
- CallExpression的LHS必须是MemberExpression , SuperCall或CallExpression
所以一个ArrowFunction不能在CallExpression的LHS上。
这应该如何解释这个有效的含义,就是它和赋值运算符=
, +=
等一样。
含义
-
x => {foo}()
不会变成(x => {foo})()
- 解释器试图把它解释为
x => ({foo}())
- 因此它仍然是一个SyntaxError
- 所以解释器决定
(
必须是错误的并抛出一个SyntaxError
巴贝尔在这里也有一个错误。
你看到这样的问题的原因是控制台本身试图模拟你目前的上下文的全球范围。 它还会尝试捕获您在控制台中编写的语句和expression式的返回值,以便将结果显示出来。 拿,例如:
> 3 + 2 < 5
在这里,它就好像是一个expression式一样执行,但是你把它写成了一个声明。 在普通的脚本中,这个值会被丢弃,但是在这里,代码必须在内部被破坏(比如用函数上下文和return
语句来包装整个语句),这会导致各种奇怪的效果,包括你遇到的问题。
这也是为什么一些在脚本中裸露的ES6代码正常工作的原因之一,但不在Chrome开发工具控制台中。
尝试在Node和Chrome控制台中执行此操作:
{ let a = 3 }
在Node或<script>
标记中,它工作得很好,但是在控制台中,它提供了Uncaught SyntaxError: Unexpected identifier
。 它还以VMxxx:1
的forms为您提供了源代码的链接,您可以单击该链接来检查评估的源代码,显示为:
({ let a = 3 })
那为什么要这样做?
答案是,它需要将您的代码转换为expression式,以便将结果返回给调用者并显示在控制台中。 您可以通过将语句包装在括号中来做到这一点,这使得它成为一个expression式,但是它也使语句上的语句不正确(expression式不能有块声明)。
控制台确实试图通过聪明的代码来修复这些边缘情况,但是我认为这超出了这个答案的范围。 你可以提交一个bug,看看他们是否会考虑修复。
这里有一个非常相似的例子:
https://stackoverflow.com/a/28431346/46588
确保代码正常工作的最安全的方法是确保它可以作为expression式运行,并检查SyntaxError
源代码链接以查看实际的执行代码,并从中反向devise解决scheme。 通常这意味着一对有战略意义的圆括号。
简而言之:控制台尽可能准确地模拟全局执行上下文,但是由于与v8引擎和JavaScript语义的交互限制,这有时很难或根本无法解决。