Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于要不要写分号 #16

Open
K-Kevin opened this issue Mar 14, 2020 · 0 comments
Open

关于要不要写分号 #16

K-Kevin opened this issue Mar 14, 2020 · 0 comments

Comments

@K-Kevin
Copy link
Owner

K-Kevin commented Mar 14, 2020

ref:《重学前端》

我们写代码要不要写分号?

自动插入分号规则

  • 要有换行符,且下一个符号是不符合语法的,那么就尝试插入分号。
  • 有换行符,且语法中规定此处不能有换行符,那么就自动插入分号。
  • 源代码结束处,不能形成完整的脚本或者模块结构,那么就自动插入分号。
let a = 1
void function(a){
    console.log(a);
}(a);

第一行后有换行符,接下来 void 跟在 1 之后是不合法的,所以第一条规则符合插入换行符;

var a = 1, b = 1, c = 1;
a
++
b
++
c

第二行 a 之后有换行符,后面有 ++ 运算符,a 后面跟着 ++ 是合法的,按理说插入换行符,ab 为 2,c 等于 1,但是实际上结果却是 bc 为 2,a 是 1,因为下面提到的[no LineTerminator here]

UpdateExpression[Yield, Await]:
    LeftHandSideExpression[?Yield, ?Await]
    LeftHandSideExpression[?Yield, ?Await][no LineTerminator here]++
    LeftHandSideExpression[?Yield, ?Await][no LineTerminator here]--
    ++UnaryExpression[?Yield, ?Await]
    --UnaryExpression[?Yield, ?Await]
(function(a){
    console.log(a);
})()
(function(a){
    console.log(a);
})()

上面是两个 IIFE 立即执行函数表达式,我们看第三行 () 结束,js 引擎认为函数返回的可能是个函数,那么后面再跟上括号则形成了函数的调用,那么也是合理的,所以也应该换行符,但是实际上这么运行是会报错的。所以在 IIFE 函数时必须再行首加分号的原因就是因此。

function f(){
    return/*
        This is a return value.
    */1;
}
f();

在这 return 和 1 被注释分开了。根据 JavaScript 自动插入分号规则,带换行符的注释也被认为是有换行符,return 同样也有 [no LineTerminator here] 规则要求。所以这里 return 后会自动插入分号,返回是 undefined。

no LineTerminator here 规则

[no LineTerminator here] 规则表示它所在的结构中的这一位置不能插入换行符。

下图列出了所有标准中的规则。
image

所以上面 ++ -- 后自增和后自减运算符为什么插入换行符就知道为什么了。

不写分号需要注意的情况

以括号开头的
(function(a){
    console.log(a);
})()/* 这里没有被自动插入分号 */
(function(a){
    console.log(a);
})()

所以 IIFE 函数要注意。

以数组开头的语句
var a = [[]]/* 这里没有被自动插入分号 */
[3, 2, 1, 0].forEach(e => console.log(e))

这段代码本意是一个变量 a 赋值,然后对一个数组执行forEach,但是因为没有自动插入分号,被理解为下标运算符和逗号表达式,不会抛出错误。

以正则表达式开头的语句
var x = 1, g = {test:()=>0}, b = 1/* 这里没有被自动插入分号 */
/(a)/g.test("abc")
console.log(RegExp.$1)

正则的第一个斜杠被理解成了除号,后面的意思就都变了

以Template开头的语句
var f = function(){
  return "";
}
var g = f/* 这里没有被自动插入分号 */
`Template`.match(/(a)/);
console.log(RegExp.$1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant