javascript初级问题

YoloMonkey 2016年10月23日提问
0

javascript对标点的要求,有时候少一个分号 ; 就不行,有时候没加引号 “” ,又不行,那么到底这些标点如何判断加不加?有没有要遵循的基本原则?

查看全部 14 个回答

0

看到大家回应分号(;)问题觉得有趣,个人是"不用分号作语句结尾流派",也回一下提供另种参考。

先说明我并没有要大家都来不加分号,而是回答这个问题"为什么可以不加分号",或者是问"为何分号是选项可有可无?",或是"不加分号是在何时可以不加?何时又一定要加?何时又算多加了?"

"不用分号作语句结尾流派"并不是"完全不使用分号流派",而是该加的时候加,不该加的时候不加,大部份时候不用分号作为语句结尾。我如果在改写别人的旧代码或是像原本函式库(如jquery)的风格是有用分号(;)时,也是会加的,基本上自己写的就不用分号(;)结尾。

分号(;)是个议题,正反方都有。但这也不是标新立异、节省空间偷懒少打字,是有一些理由的,能真的这样灵活用,代表你真的理解在这是在作什么。下面说明有太多细节,有错请再提示提示。

用回车(\n)或断行来作为语句的结尾,与四种例外情况

分号(;)在其他语言就不说了,这里纯讨论js,在js里的分号(;)是什么作用?它既是语句(表达式)的分隔,也可以作为语句的结尾。纯粹认为分号(;)就一定是语句的结尾是有疑问的,下面这两个例子就是典型范例,也是很常见的错误:

//有问题的例子
function add() {
  var a = 1, b = 2;
  return
    a + b;
}

或是像下面这个,也是很常见的错误示范:

//有问题的例子
function test() {
  return
    {
      test: true
    };
}

这两例的函数回传值必为undefined,而不是应该回传的值3与物件。为何?因为你有看到return先换行,再接著要回传的值了吗?也就是说这两个代码在执行时,相当于下面这样的代码(我只写一个出来,另一例相同):

function test() {
  return;
  { test: true };
}

return因为先换行,视为语句结尾,所以根本没有可回传的值,也就是在上例子中,回车(\n)先把return结尾掉了,后面你加的分号(;)是结尾到下一行的。这逻辑代表回车(\n)在这一句语句结尾这功用上,比分号(;)还优先。

回车(\n)或空一行,为什么可以作为语句的结尾,来源是由于ECMAScript的自动插入分号(Automatic Semicolon Insertion)的标准。不过这标准是有特例的,在以下的4种情况是用回车(\n)或空一行是不会作自动插入分号来让语句作结尾,讲是说"特例",但大概也是每天都用到,只是常不知道为何是这样而已。大致说明如下:

1. 当这一行的语句是没关闭的情况,例如阵列、物件字面、圆括号之类,或是最后是个点号(.)或逗号(,)时,也就是如果把这行结尾,就会产生不合法语句的情况。

(注: 遇到等号(=)算未完整表述式如果指定值在下一行会略过自动结尾作用)

这种例子很常见,通常是在分开内容太长的语句,或是让值写得清楚的地方。我举下面的两个合法语法范例,你会很容易理解回车(\n)会在何时自动结尾,虽然这些例子都不好阅读:

//第一例
var a =
[ 1,
2,
3,
] 

//第二例
function test(a,
b,
c){
console.log(a,b,c
)
}

2. 这一行是++或--

这规则满怪异,从来没看过有人这样写过。js会认为++与--在这一行是要准备来运算执行下一行的值,所以不结尾。下面合法范例:

a=1
--
a
console.log(a)

3. 这一行是for()、while()、do、if()或else,但没有用花括号({})

这简写语法常见,每天都会用到。

if(null==undefined)
   console.log(true)
else
   console.log(false)

4. 下一行的开头是([)、(()、(+)、(*)、(/)、(-)、(,)、(.),或二进位运算子(例如~ & |),可以与这行组成一个表达式时。

function test(){
  return 1
         +2
         -3
}
console.log(test())        

下面这个例子刚好与第一点颠倒

var a = 
[1
,2
,] 

以上为用回车(n)作为自动插入分号(;)的4个特例。其他都会自动帮你作结尾。所以依这个逻辑,为何上面的return多了一行就会产生错误,另外与return有同样情况的还有几个,像continuebreakthrow,先回车然后在下一行再加分号也会已经自动插入分号。

[追加]第5情况: 空白语句。空白语句不会自动结尾。这与上面第3点相关是常见的错误。

//错误例子,不论if这行与else这行间有没有空一行都不会自动结尾
var i = 10

if (i === 5)

else  console.log(false)

你可以加上分号在if这行,会让语法合法可执行。个人有见过但相当少数。

//合法例子,但没人这样用的
var i = 10

if (i === 5);

else  console.log(false)

一定要使用分号的情况

分号(;)的用处不是只有语句结尾,它在某些语法有分隔表述式或语句的功用。以下情况必用分号(;),无论什么流派。

1. 最常见的是for语句中的三个表述式之间:

for(var i=0 ; i<10 ; i++)
{
 //... 
}

2. 在同一行写两个语句在一起,中间需要分号(;)。所以像case中如果break(或continue)写在同一行时,break前必加分号(;)

//第一例
var i = 0; i++ 

//第二例
case 'foo': doSomething(); break

3. 以[(开头的行,前面需要加分号(;)。这十分特别,这是一种保护防范的语法,有时候解译器或压缩工具会误认为开头()是要作函数呼叫或阵列或[]物件存取属性。另一情况是IIFE会认为是同一语句,IIFE刚好也是用(开头,所以这两种必加分号(;)在前面。参考: http://stackoverflow.com/ques...

//第一例
;(x || y).doSomething()
;[a, b, c].forEach(doSomething)

//第二例
var x = 42
;(function () { })()

"不需要"与"一定不能"使用分号的情况

接著要理解,什么时候必"不需要"与"一定不能"使用分号(;),这也很容易理解的。如果你是都要用分号来作每行语句的结尾,你应该了解一下。

1. for语句的最后一个(第三个)表达式后面。画蛇添足不多说。

//错误语法
for (var i=0; i < 10; i++;){}

2. 花括号的结尾(})的后面。但有例外,赋值时可以加分号(;)是对的语法。这个规则理论上应该是不需要加而已,经测试在chrome上也不会出错误讯息。这也画蛇添足不多说。

//不建议语法
function a(){};
if(){};

//正确语法,赋值时使用
var obj = {a:1};
var fun = function(){};

//正确语法,do...while
do {...} while (...);

3. 在if、for、while、或switch的圆括号结尾后面加上分号(;),这个合法语法,对照到最上面一节的第5例看看。

//错误例子,不过它合法
if (0 === 1); { alert("hi") }

//上例相当于下面这样
if (0 === 1);
alert("hi");

结语

要不要用分号(;)作为语句的结尾,就看个人习惯或组织团队规定的撰写风格了。不管如何,你应该理解为何分号(;)是选项而非必要的原因,不要因为大神说要加该加,就埋头拼命加,而不去理解为何要加。真实情况是并不是所有的情况分号作为语句都是选项,是有规则标准的。js程式语言虽然常常有坑与例外,但本质上是死的东西,上面的规则学好足以应付9成情况。

题外话是,开源专案中真的完全不使用分号(;)的专案虽不常见,最有名的是大家每天都在用的npm,还有最近比较火红的redux

最后1个小例子是请问下面这个合法的代码,它是相当于x;++y;还是x++;y;?三秒内说得出来代表你有认真看这篇回答。

x 
++ 
y

内容很多参考下面这两则文章来的,里面对js大神有批评的,不喜勿看:

推荐答案

1

简要规范是应该遵守的,否认少了个螺丝的车子总会散架的.这个和js,php等什么语言无关.

SegmentFault

一起探索更多未知

下载 App