调用js文件中的函数函数前加分号和感叹号是什么意思?有什么用

js语法问题:为什么下面的函数里用 分号 或 逗号都可以,而在prototype属性里,只能用逗号?
按投票排序
跟函数、prototype属性啥的没关系。只跟逗号、分号出现在什么上下文里有关。第一个用的是逗号运算符(comma operator),分隔了多个赋值表达式。如果用分号来分隔,那么每个this.x = y;
都会被看作一个表达式语句,里面是赋值表达式。第二个用的是对象字面量(object literal),或者叫对象初始化器(object initializer),里面只能用逗号来分隔成员的声明。为了预防题主弄混逗号运算符与函数调用的参数列表里的逗号,送上传送门一个:===================================================题主例子里的代码:function Person(name, age, job) {
this.name = name,
this.age = age;
this.job = job,
this.friends = ["Shelby", "Court"];
Person.prototype = {
constructor: Person,
sayName: function () {
alert(this.name);
这段代码对应的抽象语法树(AST),其中逗号运算符对应的表达式是 SequenceExpression:{
"type": "Program",
"type": "FunctionDeclaration",
"type": "Identifier",
"name": "Person"
"params": [
"type": "Identifier",
"name": "name"
"type": "Identifier",
"name": "age"
"type": "Identifier",
"name": "job"
"defaults": [],
"type": "BlockStatement",
"type": "ExpressionStatement",
"expression": {
"type": "SequenceExpression",
"expressions": [
"type": "AssignmentExpression",
"operator": "=",
"type": "MemberExpression",
"computed": false,
"object": {
"type": "ThisExpression"
"property": {
"type": "Identifier",
"name": "name"
"right": {
"type": "Identifier",
"name": "name"
"type": "AssignmentExpression",
"operator": "=",
"type": "MemberExpression",
"computed": false,
"object": {
"type": "ThisExpression"
"property": {
"type": "Identifier",
"name": "age"
"right": {
"type": "Identifier",
"name": "age"
"type": "ExpressionStatement",
"expression": {
"type": "SequenceExpression",
"expressions": [
"type": "AssignmentExpression",
"operator": "=",
"type": "MemberExpression",
"computed": false,
"object": {
"type": "ThisExpression"
"property": {
"type": "Identifier",
"name": "job"
"right": {
"type": "Identifier",
"name": "job"
"type": "AssignmentExpression",
"operator": "=",
"type": "MemberExpression",
"computed": false,
"object": {
"type": "ThisExpression"
"property": {
"type": "Identifier",
"name": "friends"
"right": {
"type": "ArrayExpression",
"elements": [
"type": "Literal",
"value": "Shelby",
"raw": "\"Shelby\""
"type": "Literal",
"value": "Court",
"raw": "\"Court\""
"generator": false,
"expression": false
"type": "ExpressionStatement",
"expression": {
"type": "AssignmentExpression",
"operator": "=",
"type": "MemberExpression",
"computed": false,
"object": {
"type": "Identifier",
"name": "Person"
"property": {
"type": "Identifier",
"name": "prototype"
"right": {
"type": "ObjectExpression",
"properties": [
"type": "Property",
"type": "Identifier",
"name": "constructor"
"computed": false,
"value": {
"type": "Identifier",
"name": "Person"
"kind": "init",
"method": false,
"shorthand": false
"type": "Property",
"type": "Identifier",
"name": "sayName"
"computed": false,
"value": {
"type": "FunctionExpression",
"id": null,
"params": [],
"defaults": [],
"type": "BlockStatement",
"type": "ExpressionStatement",
"expression": {
"type": "CallExpression",
"callee": {
"type": "Identifier",
"name": "alert"
"arguments": [
"type": "MemberExpression",
"computed": false,
"object": {
"type": "ThisExpression"
"property": {
"type": "Identifier",
"name": "name"
"generator": false,
"expression": false
"kind": "init",
"method": false,
"shorthand": false
与是否是prototyprpe无关,只要是object声明都是逗号
第一个是函数,里面是语句,逗号不代表语句结束,分号之后才结束。至于后面那个,对象申明属性,肯定不能用分号啦~
少年还是安心把语言本身学好吧。这是最基础的【语法问题】了,跟什么语言,什么系统都没关系,语法都是【规定】出来的。
已有帐号?
无法登录?
社交帐号登录JavaScript 语句后应该加分号么?
按投票排序
没有应该不应该,只有你自己喜欢不喜欢。JavaScript 语法长得 C-like 不代表它本质上和 C 是一类语言,所有直觉性的 “当然应该加分号” 都是保守的、未经深入思考的草率结论。后来新设计的语言里可选分号的多得去了,光是 “可以加分号但是大家都不加” 的语言就有:Go, Scala, Ruby, Python, Swift, Groovy...至于说 “很难总结什么时候加不加”,其实真的很简单。真正会导致上下行解析出问题的 token 有 5 个:括号,方括号,正则开头的斜杠,加号,减号。我还从没见过实际代码中用正则、加号、减号作为行首的情况,所以总结下来就是一句话:一行开头是括号或者方括号的时候加上分号就可以了,其他时候全部不需要。其实即使是这两种情况,在实际代码中也颇为少见。另外,restricted production 这个东西(也就是导致 return 后面换行会自动插入分号的机制),不管你加不加分号你都是得搞懂了才能不被坑的,和加不加分号没有什么关系。更多细节,可以看我曾经给过的一个 talk:最后,上点代码好了,Vue.js 的代码全部不带分号:另外说到工具,我确实写了一个,全自动帮你批量添加或者删除分号: 做成 Git pre-commit hook,选择你自己喜欢的风格就可以。
正巧参加了2012的Backbone.js conference,现场很多大神也都讨论了这个非常火热的话题。最后大家公认的结论是这样的:加与不加是风格问题,风格争议不需要有个定论。关键的问题在于如何“争论”,处理好冲突,学会组织语言减少争议是最重要的。因为分号问题在社区内部造成了很多况日持久的口水战,这些口水战是社区的损失……因为大家在这个时候可以写更多的代码带来更多的功能。类似的问题还有AMD的module,有的库选择兼容AMD,有的人不愿意。公认结论是应该尊重作者的选择,不要因为这些风格问题而fork。module loader应该设法绕过这些问题,提供兼容的解决方案。How not to argue about semicolons?Andrew Dupont的Slides在这里,欢迎阅读:
【2014年1月更新】当初鉴于本答案过长而可能导致部分“分号党”无法catch到我的主要论点,原本打算重新修订本答案。但是因时间精力因素未予重写,且从本答案的支持来看,为分号正本清源的目的已经达到,所以不再修订本答案。这里仅总结下“分号党”推崇的“总是写分号”风格的最主要缺陷:1. 人总是有可能忘记写分号。ASI导致无法区分是无意中忘记还是有意不写(代码折行)。2. “总是写分号”并不能完全解决ASI缺陷(如return后换行会自动插入分号)。3. “}”后是否要加分号需要回溯到对应“{”之前进行语义判断(是否是函数表达式),成本远高于前置分号判断(只要对行首字符进行token判断:是否是 [ ( + - / 五个符号之一)。【以下为原答案】受邀回答。首先,加还是不加,这是一个书写风格问题。而书写风格通常有一些外在的考量,比如团队所建立的规则或习惯。@玉伯
的答案就是基于此。我对此基本赞同,不过这其实有点避重就轻,呵呵。另外,即使团队有这样的规则,也未必要通过强制在写代码的时候就要这样写,而可以通过工具达成。比如在源码管理工具上挂上钩子,对提交的源代码自动整理格式。其次,很多人提到代码压缩问题。我觉得这是非常扯淡的理由。如果2012年的今天一个JS压缩器还不能正确处理分号,这只能说明这个JS压缩器没有达到基本的质量要求,根本不值得信任。@冯超 和 @CSS魔法 提到的jslint也是一个工具的反面例子。工具是帮助人的,而不应该是强迫人的。不明白这一点,你就不会理解为什么在已经有jslint很多年的情况下,还会出现jshint。jshint对于不写分号会报warn,但可以通过asi选项关闭(在文件头加上/* jshint asi:true */即可)。在asi选项说明里,jshint的文档是这样写的:There is a lot of FUD
(fear, uncertainty and doubt) spread about semicolon
spreaded by quite a few people
in the community. The common myths are that semicolons
are required all the time (they are not) and that they are unreliable.
JavaScript has rules about semicolons which are
followed by all browsers so it is up to you to decide whether you
should or should not use semicolons in your code.翻译如下(【】里是我添加的说明):关于分号有大量的FUD,且是由社区里的一小撮人【你知道是指谁】散布的。一个常见的流言是必须写分号,不写分号不可靠【流言的意思是不写分号会导致代码行为不确定】。实际上JS有明确的分号规则,并且所有浏览器【居然】都忠实遵守了规则。所以是否应该在你的代码里使用分号,完全可以由你自己决定【而不是由一小撮流言散布者或二逼工具强加于你】。所以对于可不可以不加分号这个问题,社区是有结论的。然后所谓“应该不应该”,就只是利弊分析,而不是非黑即白。其中也必定有一些如“可维护性”、“可理解性”甚至“代码美感”之类的貌似“贱人贱智”的问题。不过我相信有经验的程序员还是会在大多数问题上找到共识的。这个世界上有许多语言。大量语言是不用分号作为EOS(End of Statement)的。有些偏执狂认为不用分号的语言都是垃圾,对此我没啥好说的。有些语言也是可选分号,比如python。python是可以加分号作为语句结束的。当然绝大多数python程序员是不会加分号的(除了在一行里写多个语句)。所以python和js一样是可选分号!并且python的习惯是不写分号(仅在极少数情况下写)!也有不少人会指摘python的语法太特殊,比如缩进啥的……不能算是c-style的。不过即使是C风格的语言,也有不写分号的,比如groovy。groovy和js一样是可选分号!并且groovy的习惯是不写分号(仅在极少数情况下写)!所以至少从同样两个是可选分号的语言来看,不写分号在实践上是可行的。毕竟,既然被设计为可选,那么合理的推断是:语言的设计初衷是倾向于鼓励不写分号。实际上,不少人(包括我)认为,c-style的分号本来就是多余的。为什么这么说?因为明确的EOS只是给编译器的提示而已。如果漏了分号,编译器会报错。既然它都报错了,显然它知道这里应该有EOS。既然它知道,那么干嘛还要我写?给编译器以hint,这在几十年前是一个平衡编译器和用户成本的设计。某些语言(如Fortran、Basic等)选择用换行来作为EOS,这样每行只能一个语句,并且一个语句折行必须用特殊的接续符号。某些语言(如C)则选择了通过分号来达成,这样每行可以多个语句,并且一个语句也可以分布在多行。平心而论,我更喜欢前一种策略。不过现实是c-style的语法流传更广,至少当前的工业主流语言都是c-style的。在c-style语言中,如果既要允许自由折行,又要避免额外的EOS(分号),编译器会较为复杂,光靠看token是不能确定语句是否结束的(即换行处有可能是语句结束,也有可能不是)——尽管在实践中只需要很少的规则,人就能一目了然的看清语句是否结束,但是parser要处理一切的极端情况,例如在换行前插入注释到底怎么算。而C的设计是遵循所谓worse is better的哲学,非常强调实现简单,一个明确的EOS对于编译器来说绝对是简单的。当初如果有人找K&R去要求应该由编译器判断这里该不该是语句结束,我打包票肯定被K&R扁死。有趣的是,lisp那一帮人更极端,如果你抱怨括号实在太密密麻麻的了,一定有人语重心长的告诉你S表达式才是王道。其实像C++编译器也已经复杂到超乎想象,按理说可选分号真是小事一桩,但它因为要保持对C的完全兼容,所以还是必须写分号。python和groovy的parser则都是有名的复杂。这并不完全由允许分号可选造成,但是可选的分号其实是整个语法设计哲学的一环。如Groovy的哲学是PHIM——Parse how I mean。话说python的语法设计真的非常有意思。它也有问题,比如tab和空格混合,计算机之子@程劭非 曾经惊叹,居然有语言能通过改变注释(注释中可定义tabsize)就改变了语义和行为,真是极品。当然后来者会吸取教训,比如coffeescript和jade之类的,也都是依赖缩进,但是都不允许tab和空格混用。所以tab/sp这是python的坑。Guido Van Rossum现在就后悔了。从某种程度上说,JavaScript的分号就有点类似python的tab/sp问题。正如混合tab/sp是出自GVR的良好初衷(让你们想用啥就用啥),可选分号也是出自BE的良好初衷(随便你写不写)。也如同tab/sp一样,良好的初衷并不代表就没有隐患。之所以python、groovy就没有可选分号的争议,而js就有争议,其实正说明js存在一些问题。其实Groovy历史上也是有关于可选分号争议的,参见: 。不幸的的是,与Groovy早期经过社区激烈的讨论才得到稳定语法不同,JS是一门早熟的语言,一些早期的设计失误没有机会被修复。自动分号插入算法就是其中之一。总体上,自动分号插入算法还算正常,但是在一些小地方留下了不易发觉的坑。比如return语句。return{
a:1}在return后会自动插入分号,导致完全违背期望的结果。这一古怪行为往往被解释为在JS中应采用一行内跟随大括号的书写风格(即Java的风格,或者说是K&R的C的原初风格,而不是C#风格),其实追根述源,问题还是出在分号上。不要插分号的地方被插了分号,这挺坑爹了,但更更坑爹的是想要插的结果没插。这就是括号的问题。如果下一行的开始是 ( 、 [ 上一行的结尾不会被加上 ; 。如:a = b(function(){...})()会被解释为 a = b(function(){...})()其实如果我们真想表达上述代码,通常会这样写:a = b(function(){ ... })()再如:a = b[1,2,3].forEach(function(e){
console.log(e)})实际效果等价于a = b[3].forEach(function(e){
console.log(e) })坑爹的是,搞不好这代码说不定还能运行!你要事后通过调试发现这些错误是相当滴痛苦啊。当然这也不能全赖BE。在JS的早期,还没有数组迭代方法 Array.prototype.forEach/map/filter...等,也没有今天常见的(function(){...})()惯用法,所以这个问题其实很不明显。但是到了今天,这些坑爹的问题就都冒出来了。实际上,+/-也有问题,但是我们几乎不会在实践中遇到。因为你根本不可能会写行首以 + / - 开始的语句,除了 ++i 之类的语句(但是其实我们都会写成 i++ )。不过这些问题的解决方案其实也很简单。只要在 [ 、 ( 、 + 、 - 之前加分号就可以了:a = b ;(function(){ ... })() a = b ;[1,2,3].forEach(function(e){
console.log(e) }) 有些同学觉得这样很丑。没问题,你可以用void替代; 。也有不少人觉得这是一种“不一致”,需要记住额外的法则。我承认采取这样一种方法你必须记住一些特例。但是几乎所有的语言都有一些历史原因导致的坑,并且JS也不止这一个坑。更关键的是即使你采用了总是写;的方法,仍然是有关于EOS的坑,因为造成问题的asi特性仍然存在。比如之前提到的return后面会自动插分号。总是写分号,相比不写分号但是edge case要在行首加分号,看上去要更“简单”,但这只是描述简单,实际做起来未必更简单。比如你必须要记得,function表达式后面也要写“;” !如:function a() {
...}[1,2,3].forEach(...)这代码是没问题的,但是你改成var a = function () {
... } [1,2,3].forEach(...)就有问题了!这坑爹!对于“始终加分号派”来说,结果就会变成函数后面也一定要加分号。(你分得清函数声明和函数表达式吗?坑爹啊,不如都加!)但是为什么函数就加而 if ... {} 或 for (...) {...} 结构里的大括号后面就不加分号呢?这不是也不一致嘛。而且,同样是一条特殊规则,行首加分号的规则比函数表达式后面加分号的规则其实要简单!var a = function () {
... } [1,2,3].forEach(...)还是以上面代码为例。行首是否要加分号,我只要看本行的第一个字符就可以了。因为对于object[prop]这样的意图,其实没有程序员会写出object[prop]这样的代码。如果他要折行,一定是写成object[
prop]所以行首第一个字符如果是括号,毋庸置疑的,这一定是一个新语句的开始。反过来,你如果要判断 } 后面是否要加 ; ,你得向上回溯,看清楚整段代码是一个结构呢?还是一个函数?如果是函数的话,是函数声明呢?还是函数表达式!许多时候,你可能向上翻几页还没找到对应的 { !或者已经忘记了是几层缩进了!人不是机器,总有可能忘记写分号。上面的分析说明,对于人来说,行首特例加分号的策略其实更简单易行。而总是加分号的策略听上去简单,执行起来却难!(除非你的策略最后变成了所有 } 之后都加分号——我真见过有人这么做的。) 对人是这样,下面再来看看对机器(引入工具)的情形。特别的,因为有不少人表示他遵循总是写分号的方式是因为他严重依赖jslint。所以我就拿jslint开刀。对于总是加分号的策略,你希望工具能提示你哪里缺少分号。但是实际情况是,你必须尽量避免写出有歧义的跨行语句,因为工具很难判断是有意为之,还是忘记写“;”。比如: a = b (function(){ ... })();这代码在jslint的提示是:Expected '(' at column 5, not column 1.请问你是应该真的按照它的提示把括号移动到b后面吗??仔细考虑一下,你就知道这个问题不好回答。因为jslint给出的建议其实是基于“这是合法的代码,只是格式不妥”。虽然我们都知道这更可能是忘记写分号。再来一个更坑爹的例子:/*jslint white: true */var a,b,c,d,e,f,g,h,i,j,k,l,m,o,s;a=b+c*d-e
/f/g-h*i/j/f/g.exec(s).map(f);这段代码在jslint里是不报错的!!!但是我们是可以看出来这代码很有可能是缺少分号。这里可以看出,如果排除了whitespace的格式提示(这事儿还是挺常见的,毕竟许多人不喜欢被强制加那么多空格规则),jslint其实无法在我们最需要帮助的时候帮到我们!因为它无法判断这个地方到底是有意为之(不用;而跨行),还是忘记写; 。反过来说,如果采取行首特例加;的习惯,其实工具是很容易判断你是否忘记加了分号。如果加上一些对缩进信息的判断来排除极少数不良的折行习惯(出warn即可),工具甚至能自动把所有这类分号都加上。两种策略:1. 我总是写分号,让工具告诉我哪里我忘记写了(但是有时候可能还报不出来,或报了个其他信息)2. 我总是不写分号,让工具自动把(由于语言设计缺陷所要求的)必须的分号加上去哪种更好?总结:我所推荐的不写分号的方式,其实不仅是不写分号,而是同时采用更严格的跨行策略,即只允许在当前行处于未完成状态时跨行(就像你在jsshell中输入代码一样)。这条规则其实并不需要特别强制,因为绝大多数程序员一直就是这样在执行。诚然,存在少数人习惯写这样有歧义的折行代码:a = b + c
+ g但是这个习惯是很容易纠正。并且工具根据缩进等信息是完全能检测到的。说到这里,也许有些同志认为这只能说明jslint太挫,不能证明到处写 ; 的风格不好。因为工具也可以同时加上其他限制嘛。不过你仔细想想,可以发现这是一个悖论。如果jslint够智能,引入了其他与分号无关的代码风格要求,比如空格和缩进,还有折行风格,确实也可以更精确的找到所有漏掉分号的地方。但是那无非再次证明了一点:编译器(代码分析器)完全可以知道哪里应该有EOS。既然所有的分号其实可以由机器自行加上,那么我们自己还要手写所有分号的意义到底在哪里?!以上。
看项目,如果是不加的项目,则不加,比如 zepto如果是加的项目,则加上,比如 jquery4 空格和 2 空格也是一样,两种风格我都习惯
其实我和你的论据一样,但我得出的结论却和你不同。你在文章中也提到了修改如果分号没写可能会导致修改一部分代码的时候导致另一部分代码出错。然后有了前置分号的做法。我想说的是,你的做法在解决问题的同时引入了另一个规范,而且这个规范不是一个代码规范而是一个代码风格规范。这样为解决一个问题而引入另一个问题的做法是不太可取的。分号这个问题的本质是:“省略分号会导致代码出现二异性“。你的例子已经很好的说明了这个问题。这个二异性不是机器解释的问题,是人的问题,而你靠一些看似普遍的风格规范来规避这个问题,我感觉是不太靠谱的。以你的例子来说:var a = b(function(){})()这个代码你是如何知道编写者不希望是var a = b(function(){})()的呢?你又以什么理由帮他补分号的呢?所以,编写者出现二异性就必须要由编写者来解决,不应该由另外的人或者程序来猜测。总结起来就是:分号作为js的语句结束符号,不是完全没有用的,他是能够明确的标明语句结束位置,避免二异性的,所以,为了不让解释器或程序的维护者猜测代码的执行状况,请在js代码中需要添加分号的地方填写分号。
行尾不写分号已有半年,我学习到的和推荐的是:知道什么时候该加分号比任何时候都加分号要好。1)掌握一次,就能永久地避免分号陷阱——已经不能比 @贺师俊 的解释更详细了。 2)开发者肯定会要去适应不同项目的代码风格。尽量不加分号。我常常发现一万个分号中连一个必要的都没有,去掉了分号不仅看起来不容易累,打起来也不容易累。当然很多人不愿意去理解和接受,据我目测,都被养成了分号强迫症患者。
如果题主的目的是为了code review的话可以这样。你首先强制程序员加入所有分号,其次拿一个javascript的parser(到处都是)给parse一下,最后就可以搞个小算法轻松看出javascript是不是帮你插入过什么分号了。一旦发现这种情况就打回去。
允许不写分号是个Mis-feature。我曾经看到有段很底层的代码被IDE格式化成return
排错花了好久才反应过来。我猜这种陷阱还会导致一次"go to fail"安全漏洞(Node.js的服务器端漏洞)
hax 已经做了很详尽的回答,关于语法,国外开发者 issac(npm 作者写过一篇简单的介绍 ,里面也给出了一篇更详尽的语法分析的文章 )可供参考。我还想补充一下自己使用过程中感到的方便。我是支持和推荐使用无分号的风格的。这确实是风格和习惯问题。我的习惯除了不加分号,还有两空格缩进前置逗号对象字面量或数组字面量两个分号/中括号占两行(第一个分号跟在括号、逗号或等号后面,不换行),第一行缩进四空格,之后前置逗号,缩进两格用一个 var 语句来举例就是这样的方便之处在于,如果你要新添加一个声明变量,只要在最后添加即可,如果使用分号结尾、后置逗号的风格,你需要先把最后的分号改成逗号,新加的一行最后也不要忘掉分号。如果你要删除一行,用我上面说的这种的风格只需要直接删除(除非是第一行),而后置逗号加分号的风格还要把最后的逗号再改成分号。例外就是删除第一行时,需要把第一个逗号改成 var。不过声明变量时一般把确定的变量放在前面,第一行尽量少改动。说到这里忘了一点,一般把带默认值的声明写在前面,不带默认值的声明写在最后,一般最后一行写多个。之前我试过第二行以后的逗号对齐 v 来写,但后来发现后面的逗号还是空两格更容易识别。这是我推荐的写法,不过我想说,整洁易读保持一致性的风格就是好风格。
补充一点:引自DC在Youtube上的一次演讲;
如果下一行的第一个token是 ( ,
这五个字符之一的话, Javascript 将不会自动在上一行句尾加上分号。
PS:另外在一些语句中,分号是必不可少的。如for循环语句中的分号,否则会报语法错误。还有在多层嵌套中有时在其中一个以
结束的语句中忘了加分号,有时就会出错了
已有帐号?
无法登录?
社交帐号登录分号、逗号、感叹号、逗号、句号应在阅读题如何运用??请详细解释_百度知道
分号、逗号、感叹号、逗号、句号应在阅读题如何运用??请详细解释
我有更好的答案
html" target="_blank">http.baidu<a href="/view//view/62f920dea58dadf://wenku://wenku
来自:求助得到的回答
其他类似问题
为您推荐:
分号的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁javascript语法本身允许句末可以不加引号,现在想把以前的js文件没加分号的统统加上,高手帮帮我吧!急!_百度知道
javascript语法本身允许句末可以不加引号,现在想把以前的js文件没加分号的统统加上,高手帮帮我吧!急!
能否用C#写一些实现代码
我有更好的答案
不好实现,你要判断哪里是句末,这个很麻烦去找找工具吧
我这个需要自己写出来,因为要把这个功能合并到一个批量处理文件的工具中
不好意思,不知道
- -、感觉判断句末是一件不可能完成的任务,或者非常复杂的任务。。。。你在研究研究吧
好像有工具,比如jshint
其他类似问题
为您推荐:
引号的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁

我要回帖

更多关于 excel函数感叹号 的文章

 

随机推荐