你所不知道的 JavaScript 分号

前言

程序猿的世界中存在着各种 争论,有缩进长度之争、缩进使用空格或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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,165评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,503评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,295评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,589评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,439评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,342评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,749评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,397评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,700评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,740评论 2 313
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,523评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,364评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,755评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,024评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,297评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,721评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,918评论 2 336

推荐阅读更多精彩内容

  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,689评论 0 10
  • 前端07班 王语句JavaScript程序的执行单位为行(line),也就是一行一行地执行。一般情况下,每一行就是...
    ea203453e188阅读 877评论 0 4
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,068评论 1 32
  • 前期必备知识 熟悉react,nextjs(是一个react的后台渲染框架) 目录 什么是ssr 什么是seo n...
    lazyTai阅读 5,169评论 4 0
  • 你还是儿时的身形 不想承认 你比我漂亮很多 脸上的雀斑飞去哪了 是心里那块糖治愈了吗 味道 早已斑驳 时光回不去 ...
    留不住的搁浅阅读 168评论 2 7