美文网首页
你所不知道的 JavaScript 分号

你所不知道的 JavaScript 分号

作者: PushMeTop | 来源:发表于2019-03-03 19:50 被阅读0次

    前言

    程序猿的世界中存在着各种 争论,有缩进长度之争、缩进使用空格或tab之争等。在 JavaScript 中还存在着 分号 使用和不使用之争。

    这是一段不使用分号的代码,看起来有点点优雅:

    var play = (lyric) => console.log(lyric)
    
    ['来啊', '造作啊', '反正有大把时光'].forEach(play)
    

    JavaScript 会根据上下文分析,使用 自动分号插入 来将分号有效插入到程序中。但是,所谓的 自动分号插入 怎么判断改在哪里插入?

    基础

    我们知道加分号是正确的,那我们将对下面的代码慢慢去除分号,来看看哪里可以省略哪里不可以省略。

    代码:

    (function () {
      var player, echo, lyric;
        
      lyric = ['来啊', '造作啊', '反正有大把时光'];
        
      echo =  function (lyric) {
        console.log(lyric);
        return true;
      }
    
      player = () => lyric.forEach(echo);
      
      console.group('测试播放音乐'); 
      player();
      console.groupEnd(); 
    
      console.group('测试返回值');  
      console.log(echo('test'));
      console.groupEnd();
    })();
    

    输出:

    base-00.png

    测试一:去除分号

    代码:

    (function () {
      var player, echo, lyric
        
      lyric = ['来啊', '造作啊', '反正有大把时光']
        
      echo =  function (lyric) {
        console.log(lyric)
        return true
      }
    
      player = () => lyric.forEach(echo)
      
      console.group('测试播放音乐') 
      player()
      console.groupEnd() 
    
      console.group('测试返回值')  
      console.log(echo('test'))
      console.groupEnd()
    })();
    

    输出:

    base-01.png

    总结:
    根据这个结果,我们可以得到一个结论 自动分号插入, 会在语句的结尾处插入 ;, 但是不会在 } 后插入 ;

    测试二:增加换行符

    在strlimit
    代码:

    (function () {
      var player,
        echo, 
        lyric
        
      lyric = [
        '来啊',
        '造作啊',
        '反正有大把时光'
      ]
        
      echo =  function (lyric) {
        console.log(lyric)
        return
          true
      }
    
      player = () => lyric.forEach(echo)
      
      console.group('测试播放音乐') 
      player()
      console.groupEnd() 
    
      console.group('测试返回值')  
      console.log(echo('test'))
      console.groupEnd()
    })();
    

    输出

    base-02.png

    这个时候,可以观察到 测试返回值 中 true 变为了 undefined,而其他的数据并没有出错。这是为什么了呢?

    解答

    // 自动分号插入前
    echo =  function (lyric) {
     console.log(lyric)
     return
       true
    }
    
    // 自动分号插入后
    echo =  function (lyric) {
     console.log(lyric)
     return ;
     true;
    }
    

    显然,return ; 返回了一个 undefined 值而不是 true。会产生这种插入问题的,除了 return 外还有:

    1. throw 语句。
    2. 带有跳转标签 的 breakcontinue

    总结

    • 自动分号插入 会对一行或者多行语句的结尾插入 分号。
    • 不会在 } 后插入分号,但是会在 } 前插入分号。
    • 对于一些特殊的关键字不允许其换行 return 语句, throw 语句, 带有跳转标签 的 breakcontinue

    拼接

    测试 1

    代码:

    var b
    b = [1,2,3,4,5]
    b[1, 2, 3, 4] = 6
    console.log(b)
    

    输出:
    对于 b[1, 2, 3, 4] = 6 相当于 b[4] = 6[]中间相当于一个逗号表达式,所以数组中的结果如下。

    concat-01.png

    测试 2

    代码变形:
    我们给上面的代码加点料,并加上分号,看看会发生什么事情:

    (function() {
      var a, b;
    
      b = [1, 2, 3, 4, 5];
      
      console.group('测试 forEach');
      a = b;
      [1, 2, 3, 4].forEach((value) => console.log(value));
      console.groupEnd();
    
      console.group('测试 a 的值');
      console.log(a);
      console.groupEnd();
    })();
    

    输出:

    concat-02.png

    测试 3

    代码:
    我们再把上面代码中的分号去除掉进行观察:

    (function() {
      var a, b
    
      b = [1, 2, 3, 4, 5]
      
      console.group('测试 forEach')
      a = b
      [1, 2, 3, 4].forEach((value) => console.log(value))
      console.groupEnd()
    
      console.group('测试 a 的值')
      console.log(a)
      console.groupEnd()
    })()
    

    输出:

    concat-03.png

    输出结果显示 TypeError,这是因为 自动分号插入 相当于把 a = b 识别成了 a = b[1, 2, 3, 4].forEach(..)。然后 b[1, 2, 3, 4] 返回值是 5 并不能使用 forEach 函数。

    结论:
    JavaScript 自动分号插入 会在换行后,解析语法错误时插入。当他在读取 a = b [1, 2, 3, 4] 时,语法并没有出现错误,所以将继续读取下去,并在 a = b[1, 2, 3, 4].forEach((value) => console.log(...)); 插入分号。

    其他测试例子

    类似于 [ 的 还有 (, +, -, / 符号。

    例子1:

    // 预期值
    b = () => console.log('我是b');
    a = b();
    (()=>console.log('我是酱油'));
    
    // 插入前
    b = () => console.log('我是b')
    a = b()
    (()=>console.log('我是酱油'))
    
    // 插入后
    b = () => console.log('我是b')
    a = b()(()=>console.log('我是酱油'));
    

    例子2:

    // 预期值
    var a = 1, b = 2;
    b = a;
    +b;
    console.log(b);
    
    // 插入前
    var a = 1, b = 2
    b = a
    +b
    console.log(b)
    
    // 插入后
    var a = 1, b = 2;
    b = a+b;
    console.log(b);
    

    例子3:

    // 预期值
    var a = 1, hello = 2;
    b = a;
    /hello/i.test("hello");
    
    // 插入前
    var a = 1, hello = 2
    b = a
    /hello/i.test("hello")
    
    // 插入后
    var a = 1, hello = 2;
    b = a / hello / i.test("hello");
    

    例子4:

    // 预期值
    (() => console.log(1))();
    (() => console.log(2))();
    
    // 插入前
    (() => console.log(1))()
    (() => console.log(2))()
    
    // 插入后
    (() => console.log(1))()(() => console.log(2))()
    

    总结

    • 自动分号插入 会逐行 读取 和 拼接语句,当下一条语句出现拼接错误后,才会在当前语句尾部增加 ;
    • 注意下一行开头的字符有 5 个需要留意的,分别是 [, (, +, -, /

    其他

    我们除了在语句结尾使用分号外,在循环语句中也会使用到。

    例子 1

    // 喵的,显然不能省略啊!!!
    for(i = 0; i < 10; i++) {
      console.log(i);
    }
    

    例子 2

    // 喵的,你运行给我看看!!!
    (function () {
      while(true)
    })
    
    // 汪的,要这样写啊!!!!!
    (function () {
      while(true);
    })
    

    总结

    • 我们在讨论是否是使用 分号 的时候,也应该了解,使用与否所可能带来的问题。
    • 自动分号插入会对一行或者多行语句的结尾插入分号。
    • 不会在 } 后插入分号,但是会在 } 前插入分号。
    • 对于一些特殊的关键字 return, throw, 带标签的 breakcontinue 不允许其换行。
    • 自动分号插入 会逐行 读取 和 拼接语句,当下一条语句出现拼接错误后,才会在当前语句尾部增加 ;
    • 注意下一行开头的字符有 5 个需要留意的,分别是 [, (, +, -, /
    • 为了安全,可以考虑在文件开头或立即函数开头 补一个 ;
    • 分号不是你想省,想省就能省!!!
    • 多读书,多看报,少吃零食,多睡觉。

    参考

    • 《Effective JavaScript》

    打赏&联系

    如果您感觉有收获,欢迎给我打赏,以激励我输出更多的优质内容。

    打赏&联系

    本文原稿来自 PushMeTop

    相关文章

      网友评论

          本文标题:你所不知道的 JavaScript 分号

          本文链接:https://www.haomeiwen.com/subject/tvcmsqtx.html