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 · 317 天前 · 3251 次点击
    这是一个创建于 317 天前的主题,其中的信息可能已经有所发展或是发生改变。

    demo 在 jsfiddle

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

    29 条回复    2023-06-16 15:32:43 +08:00
    vinsony
        1
    vinsony  
       317 天前   ❤️ 1
    下面一行是括号,不加分号会被识别成函数执行
    rocmax
        2
    rocmax  
       317 天前 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  
       317 天前 via Android   ❤️ 1
    function test(a) {
    return b => c => b(a,c);
    }

    test(1)(function (b,c){return b+c})(3)
    rekulas
        4
    rekulas  
       317 天前
    我猜你应该年龄不大,因为上古时期的程序员写 js 都是加了分号的,省略分号是最近 10 年流行起来的
    由于始终存在一些例外,所以我其实还是偏向于加分号,因为我喜欢统一
    不过做项目的话个人喜好放一边,还是得跟着项目规范走
    lujiaxing
        5
    lujiaxing  
       317 天前   ❤️ 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  
       317 天前   ❤️ 1
    var name = hello
    (function () {})()

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

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

    f(1)(2)

    因为匿名函数有可能再返回一个函数
    flyqie
        10
    flyqie  
       317 天前
    @rekulas #4

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

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

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

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

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

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

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