V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
lxy42
V2EX  ›  JavaScript

遇到一个 JS 语法错误, 加了分号就可以运行

  •  
  •   lxy42 · 2023-06-15 16:21:14 +08:00 · 3624 次点击
    这是一个创建于 555 天前的主题,其中的信息可能已经有所发展或是发生改变。

    demo 在 jsfiddle

    对 JS 不太熟悉, Google 上搜了一些关键词(semicolon anonymous function syntax error)没找到答案. 为什么一定要在调用匿名函数的上一行语句添加加分号?

    29 条回复    2023-06-16 15:32:43 +08:00
    vinsony
        1
    vinsony  
       2023-06-15 16:26:09 +08:00   ❤️ 1
    下面一行是括号,不加分号会被识别成函数执行
    rocmax
        2
    rocmax  
       2023-06-15 16:28:29 +08:00 via Android   ❤️ 8
    Write semicolons in ONLY 5 cases
    ;-less // line starts with unary - operator
    ;+less // line starts with unary + opeartor
    ;/less/ // line starts with regexp literal
    ;[less] // line starts with array initializer
    ;(less) // line starts with grouping operator, such as IIFE
    NOTE: In real-world, only the last case is common.
    chnwillliu
        3
    chnwillliu  
       2023-06-15 16:32:55 +08:00 via Android   ❤️ 1
    function test(a) {
    return b => c => b(a,c);
    }

    test(1)(function (b,c){return b+c})(3)
    rekulas
        4
    rekulas  
       2023-06-15 16:34:47 +08:00
    我猜你应该年龄不大,因为上古时期的程序员写 js 都是加了分号的,省略分号是最近 10 年流行起来的
    由于始终存在一些例外,所以我其实还是偏向于加分号,因为我喜欢统一
    不过做项目的话个人喜好放一边,还是得跟着项目规范走
    lujiaxing
        5
    lujiaxing  
       2023-06-15 16:36:22 +08:00   ❤️ 1
    它给理解成了
    console.log 返回了个函数, 然后后面的括号是在试图调用 console.log 所返回的函数并将括号中的 function 作为 console.log 所返回的函数的参数... 那当然会报错.

    本质上, 你的代码等效于:
    ```
    const console = {
    log: (str) => (func) => (func(), window.console.log(str))
    };

    console.log("hello")(() => alert("It's worked!!!"))
    ```
    foolnius
        6
    foolnius  
       2023-06-15 16:37:03 +08:00   ❤️ 1
    var name = hello
    (function () {})()

    var name = hello(function () {})()

    请问这两者怎么区分
    lujiaxing
        7
    lujiaxing  
       2023-06-15 16:39:10 +08:00
    @rekulas 是的. 现在我司的前端代码规范就是要求语句后没有分号.
    谁加分号 `npm run build` 铁报错. jslint 都过去不.
    lxy42
        8
    lxy42  
    OP
       2023-06-15 16:40:21 +08:00
    谢谢各位, 知道原因了.
    chengxy
        9
    chengxy  
       2023-06-15 16:41:27 +08:00
    const f = (a) => {
    return (b) => {
    return a + b
    }
    }

    f(1)(2)

    因为匿名函数有可能再返回一个函数
    flyqie
        10
    flyqie  
       2023-06-15 18:40:06 +08:00
    @rekulas #4

    虽然现在主要写 go ,但还是不太习惯不加分号。

    加分号在某些时候可以使得语句更加清晰明了,也方便排查问题。

    真的,不加分号的语言略微有点异端。。
    enchilada2020
        11
    enchilada2020  
       2023-06-15 19:09:03 +08:00 via Android
    JS 的话 写不写分号全看个人偏好 我选择两个都要 不会去手打 但必须得有 这种事让编辑器给我补全就行了 这语言本来需要注意的地方就多 对省略分号的支持又不完美 没有分号还得时刻留意这种必须加的情况
    不加分号党的理由主要有两个 一是每行多打一个字符 麻烦 还有一个是行尾有分号不美观
    因为是编辑器补全的 所以第一点不成立 至于是否美观 全凭个人喜好 还有人觉得行尾没了分号 整行代码都不完整呢…
    makelove
        12
    makelove  
       2023-06-15 19:13:38 +08:00
    @flyqie 现在普及了工具强制代码风格不加分号完全不是问题,且少了些没用符号干扰代码看上去更干净清晰
    makelove
        13
    makelove  
       2023-06-15 19:16:16 +08:00
    @enchilada2020 然而并没有“时刻留意这种必须加的情况”,因为不加都不行现在各类 lint 工具都直接对那些情况报错
    enchilada2020
        14
    enchilada2020  
       2023-06-15 19:59:37 +08:00 via Android
    @makelove 正是因为楼主踩了这个坑 所以才有的这贴 楼主这样对 JS 本身都不熟的使用者 连什么时候必须加分号都不知道 你还指望一个新手去研究怎么配语言生态链上的 lint 工具来防止自己踩坑吗。。
    luwang
        15
    luwang  
       2023-06-15 22:02:42 +08:00
    @rocmax 哈哈,只遇到过后面三种,之前最常见的就是 `;(function(){})()` 、`!(function(){})()` 了
    tonytonychopper
        16
    tonytonychopper  
       2023-06-15 22:09:58 +08:00
    加不加分号其实无所谓吧,可以用 lint 来偷懒
    IamJ
        17
    IamJ  
       2023-06-15 22:12:25 +08:00
    如果一行代码中开头是( ,很多时候会加一个分号写成 ;( 来避免这问题🤣
    IvanLi127
        18
    IvanLi127  
       2023-06-15 22:49:27 +08:00 via Android
    如果问这个问题,那么以后一定不要省略分号。。。没有现代工具的情况下,js 不适合省略分号,哪天解决一次冲突都可能人麻掉
    Shy07
        19
    Shy07  
       2023-06-15 23:03:06 +08:00 via iPhone
    js 开头加分号规则很好记:[、(、` 作为行开头,前面加分号,防止歧义
    dcsuibian
        20
    dcsuibian  
       2023-06-15 23:11:14 +08:00
    实际上不加分号才是大势所趋。我以前也是加分号党,因为可读性强。后来嘛,懒战胜了一切。

    尤其是看了尤雨溪的说法:
    至于说 “很难总结什么时候加不加”,其实真的很简单。真正会导致上下行解析出问题的 token 有 5 个:括号,方括号,正则开头的斜杠,加号,减号。我还从没见过实际代码中用正则、加号、减号作为行首的情况,所以总结下来就是一句话:
    一行开头是括号或者方括号的时候加上分号就可以了,其他时候全部不需要。
    其实即使是这两种情况,在实际代码中也颇为少见。
    rekulas
        21
    rekulas  
       2023-06-15 23:13:54 +08:00
    @flyqie 我写 go 一直都不加分号,大部分人也是吧
    其实加不加我都能接受
    但是 js 这种各种项目加与不加夹杂一起的看着就非常难受
    autoxbc
        22
    autoxbc  
       2023-06-16 02:41:41 +08:00
    感觉不是那几种 token 少见,而是不加分号党会有意避开

    我日常加分号,以 [ 或者 ( 开头的代码就很多:
    1. 同步函数中的异步部分,如果不需要等待结果,就用一个立即执行的异步函数套起来,开头就是 ( async () => ;
    2. 对已有变量解构赋值,就要用 ( { foo } = obj ) 的写法;
    3. 对三目运算的结果调用方法,要用括号包起来 ( a ? b : c ).fn();
    4. 数组字面量调用方法,[...obj].forEach ;
    5. 对象字面量调用方法 ({ a: fn1 , b: fn2 })[v]() ;

    随手一找就一堆,这些都不算真实世界的代码呗
    lilei2023
        23
    lilei2023  
       2023-06-16 07:54:11 +08:00
    远古时期都是这个干的,防止压缩后出问题
    xuanbg
        24
    xuanbg  
       2023-06-16 07:59:28 +08:00
    对于不加分号的逻辑我实在是理解不能。这个分号是能让你代码产生歧义还是能让代码运行不能?
    laoyutang
        25
    laoyutang  
       2023-06-16 09:09:41 +08:00 via Android
    不加分号有歧义,但是这不是 ide 自动就会给你加上的,哪里还能让他报出错来
    huijiewei
        26
    huijiewei  
       2023-06-16 09:24:25 +08:00
    JS 的风格之路是这样的:
    远古时期都加分号的
    然后开始不加分号的风格,但是在某些特殊语句前加分号,所以你会看到很多库第一个字符就是分号
    然后现在又流行加分号了
    jinliming2
        27
    jinliming2  
       2023-06-16 10:22:22 +08:00 via iPhone
    @dcsuibian #20 > 我还从没见过实际代码中用正则、加号、减号作为行首的情况

    如果是懒癌的话,应该这种情况很常见吧?举个正则的例子:
    /xxx/.test(variable) && callFunc();
    就是用正则判断一个字符串是否匹配,然后调一个函数,当然是可以改成 if 语句的,但是这样更简洁。
    + 和 - 到确实是不多,- 能想到的也是行首这个 负数与一个变量的判断,比如
    -5 === variable || callFunc ();
    但是交换一下等号两边,也是可以避免,也不会带来复杂性提升。
    至于 + 号,见过有人用这个放在变量前来转数据类型的,但我是不这么用的
    jackytsu
        28
    jackytsu  
       2023-06-16 11:08:14 +08:00
    不加分号可以这样写:
    const foo = `bar`
    console.log('hello') // add ; to fix syntax error
    !function () {
    alert("It's worked!!!")
    }();
    solitary830
        29
    solitary830  
       2023-06-16 15:32:43 +08:00
    就我个人理解而言其实与前方那个将函数一起运行的相似,首先你这个是自执行函数,如果不加分号的话会认为是一体的,我也刚开始前端,知道的不深刻,总直是如果是自执行函数的话最好是前方加一个分号去区分
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2517 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 04:17 · PVG 12:17 · LAX 20:17 · JFK 23:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.