龙空技术网

Javascript代码中究竟使用还是不使用分号之一

计算机科学技术 992

前言:

现在同学们对“js自执行函数需要返回值吗为什么”可能比较关切,你们都需要了解一些“js自执行函数需要返回值吗为什么”的相关文章。那么小编在网络上网罗了一些有关“js自执行函数需要返回值吗为什么””的相关资讯,希望同学们能喜欢,同学们一起来学习一下吧!

Javascript开发者中一直都存在两种代码书写风格:一部分人在代码中使用分号作为终止符,而另一部分则拒绝在代码中加入分号。两种不同的风格各有各自的理由和习惯。比如:有过Java或C++开发经验的开发者则认为使用分号程序更为严谨,符合常用编程语言的风格;而不使用分号的开发者则认为分号导致了代码的不清洁,引入了不必要的视觉干扰。本文将用实例演示那些使用或不使用分号容易导致的问题,弄清楚这些问题之后,我们再回过头来看看是否需要添加分号。

依据ECMA-262标准,大部分ECMAScript的语句和声明是需要显式地使用分号作为终止符,但是,为了方便,在解析源码生成token流时,某些场景下又会自动插入分号,这种技术被称为自动分号插入功能(Automatic Semicolon Insertion,简称ASI),本文将演示那些解释器在什么情况下或错误地了插入分号或缺少了本应该有的分号。

自动添加分号

Javascript解释器在大部分的情况下可以按照开发者的意愿自动添加分号,而无需开发者主动输入,本节将演示那些解释器添加分号出错时的情景。

return语句

return语句为Javascript语言函数中的返回语句,函数在Javascript中是不需要指定其返回类型的,不像Java或C++编程语言一样,如果实际返回值的类型与函数定义的返回值类型不匹配,那么编译器就会给出错误,从而导致编译错误,这样很容易帮助开发者发现和定位问题。但是,Javascript的函数返回值类型可以是任意类型,因此,如果期望这个函数返回一个对象或数值,实际上这个函数返回一个undefine或其它类型,这对于Javascript解释器来说都是正确的,它不会给出任何错误。下面图1中的代码,定义了一个函数f,它的原意是希望能够返回一个含有name和age属性的对象,但是呢?实际上它给出的返回值为undefined。

图1

同理,下图2中的函数原以为这个函数返回值会是5,而实际上,这个返回值也是undefined

图2

为什么会有这样的结果呢?原因在于图1中第3行代码和图2中第12行代码,这一行代码中使用了return,并将其独立地放置在了一行上,这对于Javascript函数来说是一个合理且合法的语句,表示返回一个undefined这个值。图1第4-7行代码和图2第13行代码就不会被执行。

如何解决这个问题呢?在return关键字所在的行构建一个不完整的语法表达式!如图3所示,我们可以使用左括号表示当前行中的内容并非一个完成的Javascript表达式,解释器在遇到这个字符”(“后会继续处理后面的内容,直至解析到对应的右括号“)”,那么最终这个表达式的数值就变为了5,同时通过return语句将其返回。

图3

除了使用左括号之外,我们还可以采用其它的方式构建不完整表达式,比如下面图4中,使用了一个对数值运算无影响的加号“+”,对于这个数值表达式,它同样可以避免return返回一个undefined值。

图4

如果你觉得这样做是使用了一个多余的加号字符,那么同样可以对需要返回的表达式做处理,将其一部分内容书写在与return同一行上,下图5中第38行代码则是将表达式中的“3+”与return放置在同一行,最后的字符加号”+“和下一行的内容依旧可以正确的构建成一个计算表达式。

图5

自增或递减

变量的递增与递减操作符和变量之间如果在书写时被分别书写到了不同的行上,如图6所示,第52行代码是这个变量的名称,第53行代码为递增操作符,那么在第52行代码的结尾,解释器同样会自动加入一个分号,运行此代码后,会提示图7所示的错误。

图6

图7

对于这样的错误处理方式是将变量与递增符书写在同一行。

break和continue

break和continue对于ASI的处理方式相同,我们本例就以break为例进行说明,如图8中的代码第63行使用了break语句,且它独自位于一行,代码中第59行定义了一个end标签,原意表示当j的值为3时直接跳转至这个end标签处执行代码,期望执行3次第66行的代码。但是,在代码第63行break与第64行,二者之间含有一个换行符,那么,正是由于ASI的原因,在break之后插入了一个分号,导致第64行代码完全被忽略,致使外层循环执行了10次,break只是作用域内部循环。

图8

这个问题在与上一个问题所不同的是,它不是个语法错误,属于代码的逻辑错误,很难定位。修改的方式是将break与end放置在同一行上,避免自动在break后插入分号。

throw

throw语句用以抛出一个异常对象,图9中的代码,原意是使用throw语句抛出一个对象,只是在代码第74行和75行代码处多出了一个换行符,解释器同样也会为其添加一个分号终止符,程序在执行时会给出图10所示的错误信息。

图9

图10

所幸的是,代码编辑器在格式化代码时会自动修复此错误,修改后的内容如下图11所示,图11中第74行代码末尾使用了左大括号“{“,也使其在throw所在的行构成一个不完整表达式。

图11

arrow函数

arrow函数的参数和符号“=>”之间如果出现了换行符,那么在函数参数列表之后和“=>”符号之间同样会被解释器加入分号终止符,如下图12所示,第84行和85行代码之间会自动插入一个分号,导致程序在执行时会出现图13所示的错误

图12

图13

图13中的错误信息提示比较明确,表示符号”=>“和参数列表应该位于同一行内。如何修改这样的错误呢?下面提供了三种方式,第一种图14所示为推荐使用的方式

图14

图14中将函数的参数列表和符号”=>“放置在同一行内,那么它们中间就不会再自动插入分号了。第二种修改方法是将参数分为两部分,一部分参数位于一行内,另一部分参数与符号“=>”位于同一行内,如图15所示第101行为函数的第一个参数所在的行,第102行为第二个参数和符号“=>”所在的行

图15

yield表达式

yield表达式与return表达式对于ASI使用场景是一样的,处理yield的ASI问题时,可以直接将其视为return,按照上述return的处理方式即可解决问题,如图16为含有问题的yield表达式,第121行和122行代码之间多出了一个换行符

图16

处理此问题的方法推荐图17中所示代码,第134行代码将yield关键字与表达式放置在同一行内,避免在关键字yield和表达式之间自动插入分号。如果表达式比较复杂,那么可以采用图18中的做法。

图17

图18

图18中在yield和表达式之间添加了括号,即将整个表达式放入一个括号内,这个括号的左括号与yield位于同一行,见图18中第134行代码,这样做的结果就是ASI机制无法在左括号后直接加入一个分号,只是yield和左括号及其下一行中的表达式作为一个完成的表达式。最后一个可以使用的方法是将待返回的表达式分为两部分,如图19所示,第一部分与yield位于同一行内,第二部分位于另外一行,第一部分和第二部分之间使用了加号“+”进行连接,解释器遇到加号“+”便继续构建表达式,而不是自动插入一个分号。

图19

本文演示了Javascript的自动添加分号但是其效果却不是开发者所期望的功能不一致而导致的问题,我们首先给出了每一个场景的错误代码,之后根据每一个实例的不同给出了对应的解决方法,有的解决方法不止一种。但原理一致,都是要保证解释器能够正确地处理表达式,下一篇文章我们将介绍Javascript的应该自动添加分号但是它恰恰相反而没有做的功能,谢谢阅读,我们下一篇文章见。

标签: #js自执行函数需要返回值吗为什么