You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// badvarerrorMessage='This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';// badvarerrorMessage='This is a super long error that was thrown because \of Batman. When you stop to think about how Batman had anything to do \with this, you would get nowhere \fast.';// goodvarerrorMessage='This is a super long error that was thrown because '+'of Batman. When you stop to think about how Batman had anything to do '+'with this, you would get nowhere fast.';
varitems;varmessages;varlength;vari;messages=[{state: 'success',message: 'This one worked.'},{state: 'success',message: 'This one worked as well.'},{state: 'error',message: 'This one did not work.'}];length=messages.length;// badfunctioninbox(messages){items='<ul>';for(i=0;i<length;i++){items+='<li>'+messages[i].message+'</li>';}returnitems+'</ul>';}// goodfunctioninbox(messages){items=[];for(i=0;i<length;i++){// use direct assignment in this case because we're micro-optimizing.items[i]='<li>'+messages[i].message+'</li>';}return'<ul>'+items.join('')+'</ul>';}
// 匿名函数表达式varanonymous=function(){returntrue;};// 命名函数表达式varnamed=functionnamed(){returntrue;};// 立即调用的函数表达式(IIFE)(function(){console.log('Welcome to the Internet. Please follow me.');}());
functionexample(){console.log(anonymous);// => undefinedanonymous();// => TypeError anonymous is not a functionvaranonymous=function(){console.log('anonymous function expression');};}
命名函数表达式会提升变量名,但不会提升函数名或函数体。
functionexample(){console.log(named);// => undefinednamed();// => TypeError named is not a functionsuperPower();// => ReferenceError superPower is not definedvarnamed=functionsuperPower(){console.log('Flying');};}// 当函数名跟变量名一样时,表现也是如此。functionexample(){console.log(named);// => undefinednamed();// => TypeError named is not a functionvarnamed=functionnamed(){console.log('named');}}
// bad// make() returns a new element// based on the passed in tag name//// @param {String} tag// @return {Element} elementfunctionmake(tag){// ...stuff...returnelement;}// good/** * make() returns a new element * based on the passed in tag name * * @param {String} tag * @return {Element} element */functionmake(tag){// ...stuff...returnelement;}
使用 // 作为单行注释。在评论对象上面另起一行使用单行注释。在注释前插入空行。
// badvaractive=true;// is current tab// good// is current tabvaractive=true;// badfunctiongetType(){console.log('fetching type...');// set the default type to 'no type'vartype=this.type||'no type';returntype;}// goodfunctiongetType(){console.log('fetching type...');// set the default type to 'no type'vartype=this.type||'no type';returntype;}
给注释增加 FIXME 或 TODO 的前缀可以帮助其他开发者快速了解这是一个需要复查的问题,或是给需要实现的功能提供一个解决方式。这将有别于常见的注释,因为它们是可操作的。使用 FIXME -- need to figure this out 或者 TODO -- need to implement。
使用 // FIXME: 标注问题。
functionCalculator(){// FIXME: shouldn't use a global heretotal=0;returnthis;}
使用 // TODO: 标注问题的解决方式。
functionCalculator(){// TODO: total should be configurable by an options paramthis.total=0;returnthis;}
Edition 5 clarifies the fact that a trailing comma at the end of an ArrayInitialiser does not add to the length of the array. This is not a semantic change from Edition 3 but some implementations may have previously misinterpreted this.
```javascript
// bad
var hero = {
firstName: 'Kevin',
lastName: 'Flynn',
};
var heroes = [
'Batman',
'Superman',
];
// good
var hero = {
firstName: 'Kevin',
lastName: 'Flynn'
};
var heroes = [
'Batman',
'Superman'
];
```
// good/** * parseInt was the reason my code was slow. * Bitshifting the String to coerce it to a * Number made it a lot faster. */varval=inputValue>>0;
// file contentsclassCheckBox{// ...}module.exports=CheckBox;// in some other file// badvarCheckBox=require('./checkBox');// badvarCheckBox=require('./check_box');// goodvarCheckBox=require('./CheckBox');
当给事件附加数据时(无论是 DOM 事件还是私有事件),传入一个哈希而不是原始值。这样可以让后面的贡献者增加更多数据到事件数据而无需找出并更新事件的每一个处理器。例如,不好的写法:
// bad$(this).trigger('listingUpdated',listing.id);
...
$(this).on('listingUpdated',function(e,listingId){// do something with listingId});
更好的写法:
// good$(this).trigger('listingUpdated',{listingId : listing.id});
...
$(this).on('listingUpdated',function(e,data){// do something with data.listingId});
Zving前端开发规范(JS部分)
最后修改2017-03-10
目录
引言
软件的长期价值直接源于其编码质量,清晰易理解的代码是编码质量的重要一环,代码应该写成可供他人容易阅读的。
编写目的
本文档旨在为zving前端开发提供基本规范,保持页面规范,避免版本管理(git/svn)中开发人员因代码风格不同而产生的非功能性的冲突,提高前端开发人员协作开发的水平。同时减少页面错误、提高系统健壮性。
使用环境及对象
本规范适用基于浏览器的B/S版软件项目开发工作。适用于目前正在进行开发的系统(ZCMS,ZOA,ZShop)的前/后台页面。本规范不约束第三方库(如jQuery、React)。
适用对象包括:
JS开发编辑器
我们约定使用 JavaScript Standard Style(Standard JS风格规范),所以请使用以下编辑器和安装 Standard 插件
Visual Studio Code
下载地址 https://code.visualstudio.com/
安装
JavaScript Standard Style
插件:vscode-standardjs
参考 https://marketplace.visualstudio.com/items?itemName=chenxsan.vscode-standardjs
Sublime Text
下载地址 http://www.sublimetext.com
安装
JavaScript Standard Style
插件:依次安装SublimeLinter
,SublimeLinter-contrib-standard
,StandardFormat
。参考
http://www.sublimelinter.com/en/latest/installation.html
https://packagecontrol.io/packages/SublimeLinter-contrib-standard
https://packagecontrol.io/packages/StandardFormat
Atom
下载地址 https://atom.io/
安装
JavaScript Standard Style
插件:依次安装linter-js-standard
,standard-formatter
,standardjs-snippets
。参考
https://atom.io/packages/linter-js-standard
https://atom.io/packages/standard-formatter
https://atom.io/packages/standardjs-snippets
VIM
下载地址 http://www.vim.org/
安装
JavaScript Standard Style
插件:安装Syntastic
插件里面包含有Standard
,或者安装spf13-vim
插件包,里面包含有Syntastic
插件,并且默认开启了Standard
。参考
https://github.com/vim-syntastic/syntastic
http://vim.spf13.com/
WebStorm
下载地址 http://www.jetbrains.com/webstorm/
可以直接在 IDE 中使用
standard
。无需再安装JavaScript Standard Style
插件。编码
JS文件的“换行符类型”为“windows换行符-CR/LF”;编码为
UTF-8
(在需要与支持GBK
的控件交互的情况下,使用GBK
编码)Javascript编码规范
我们约定使用Airbnb公司的JavaScript编码规范,参考网址 https://github.com/airbnb/javascript
JS风格一览表
编码规范目录
类型
原始值: 存取直接作用于它自身。
string
number
boolean
null
undefined
复杂类型: 存取时作用于它自身值的引用。
object
array
function
↑ 回到编码规范目录
对象
使用直接量创建对象。
不要使用保留字作为键名,它们在 IE8 下不工作。更多信息。
使用同义词替换需要使用的保留字。
↑ 回到编码规范目录
数组
使用直接量创建数组。
向数组增加元素时使用 Array#push 来替代直接赋值。
当你需要拷贝数组时,使用 Array#slice。jsPerf
使用 Array#slice 将类数组对象转换成数组。
↑ 回到编码规范目录
字符串
使用单引号
''
包裹字符串。超过 100 个字符的字符串应该使用连接符写成多行。
注:若过度使用,通过连接符连接的长字符串可能会影响性能。jsPerf & 讨论.
程序化生成的字符串使用 Array#join 连接而不是使用连接符。尤其是 IE 下:jsPerf.
↑ 回到编码规范目录
函数
函数表达式:
永远不要在一个非函数代码块(if、while 等)中声明一个函数,把那个函数赋给一个变量。浏览器允许你这么做,但它们的解析表现不一致。
注: ECMA-262 把
块
定义为一组语句。函数声明不是语句。阅读对 ECMA-262 这个问题的说明。永远不要把参数命名为
arguments
。这将取代函数作用域内的arguments
对象。↑ 回到编码规范目录
属性
使用
.
来访问对象的属性。当通过变量访问属性时使用中括号
[]
。↑ 回到编码规范目录
变量
总是使用
var
来声明变量。不这么做将导致产生全局变量。我们要避免污染全局命名空间。使用
var
声明每一个变量。这样做的好处是增加新变量将变的更加容易,而且你永远不用再担心调换错
;
跟,
。最后再声明未赋值的变量。当你需要引用前面的变量赋值时这将变的很有用。
在作用域顶部声明变量。这将帮你避免变量声明提升相关的问题。
↑ 回到编码规范目录
提升
变量声明会提升至作用域顶部,但赋值不会。
匿名函数表达式会提升它们的变量名,但不会提升函数的赋值。
命名函数表达式会提升变量名,但不会提升函数名或函数体。
函数声明提升它们的名字和函数体。
了解更多信息在 JavaScript Scoping & Hoisting by Ben Cherry.
↑ 回到编码规范目录
比较运算符 & 等号
优先使用
===
和!==
而不是==
和!=
.条件表达式例如
if
语句通过抽象方法ToBoolean
强制计算它们的表达式并且总是遵守下面的规则:''
被计算为 false,否则为 true使用快捷方式。
了解更多信息在 Truth Equality and JavaScript by Angus Croll.
↑ 回到编码规范目录
块
使用大括号包裹所有的多行代码块。
如果通过
if
和else
使用多行代码块,把else
放在if
代码块关闭括号的同一行。↑ 回到编码规范目录
注释
鼓励按JsDoc的注释规范来写注释,以便可以通过JsDoc等工具自动生成API文档。
JS组件的开头要写上此文档所实现的功能及实现思路(使用多行注释),保证非原作者也可以接手开发工作。
重要代码后的注释主要是说明代码段的用处,疑难代码后的注释对逻辑进行解释。
使用
/** ... */
作为多行注释。包含描述、指定所有参数和返回值的类型和值。使用
//
作为单行注释。在评论对象上面另起一行使用单行注释。在注释前插入空行。给注释增加
FIXME
或TODO
的前缀可以帮助其他开发者快速了解这是一个需要复查的问题,或是给需要实现的功能提供一个解决方式。这将有别于常见的注释,因为它们是可操作的。使用FIXME -- need to figure this out
或者TODO -- need to implement
。使用
// FIXME:
标注问题。使用
// TODO:
标注问题的解决方式。↑ 回到编码规范目录
空白
使用 2 个空格作为缩进。不要制表位和空格混合使用。
在大括号前放一个空格。
在控制语句(
if
、while
等)的小括号前放一个空格。在函数调用及声明中,不在函数的参数列表前加空格。使用空格把运算符隔开。
在文件末尾插入一个空行。
在使用长方法链时进行缩进。使用前面的点
.
强调这是方法调用而不是新语句。在块末和新语句前插入空行。
↑ 回到编码规范目录
逗号
行首逗号: 不需要。
额外的行末逗号:不需要。这样做会在 IE6/7 和 IE9 怪异模式下引起问题。同样,多余的逗号在某些 ES3 的实现里会增加数组的长度。在 ES5 中已经澄清了 (source):
↑ 回到编码规范目录
分号
使用分号。
了解更多.
↑ 回到编码规范目录
类型转换
在语句开始时执行类型转换。
字符串:
使用
parseInt
转换数字时总是带上类型转换的基数。如果因为某些原因
parseInt
成为你所做的事的瓶颈而需要使用位操作解决性能问题时,留个注释说清楚原因和你的目的。注: 小心使用位操作运算符。数字会被当成 64 位值,但是位操作运算符总是返回 32 位的整数(source)。位操作处理大于 32 位的整数值时还会导致意料之外的行为。讨论。最大的 32 位整数是 2,147,483,647:
布尔:
↑ 回到编码规范目录
命名规则
不要使用下划线前/后缀。允许使用下划线前缀来暗示私有变量,建议使用闭包来限制对私有变量的访问。
循环语句中计数变量建议使用 "i", "j", "k" (依次类推),其他情况下避免单字母命名。常用单词可进行缩写,如
element
或缩写为elem
/ele
/el
,作用域越大的变量越要避免使用缩写;使用有意义的英文单词作变量名,命名应具备描述性,清楚的表达其自身的属性,避免字义含糊不清。
使用驼峰式命名对象、函数和实例。
使用帕斯卡式命名构造函数或类。
不要保存
this
的引用。使用 Function#bind。给函数命名。这在做堆栈轨迹时很有帮助。
注: IE8 及以下版本对命名函数表达式的处理有些怪异。了解更多信息到 http://kangax.github.io/nfe/。
如果你的文件导出一个类,你的文件名应该与类名完全相同。
↑ 回到编码规范目录
存取器
属性的存取函数不是必须的。
如果你需要存取函数时使用
getVal()
和setVal('hello')
。如果属性是布尔值,使用
isVal()
或hasVal()
。创建 get() 和 set() 函数是可以的,但要保持一致。
↑ 回到编码规范目录
构造函数
给对象原型分配方法,而不是使用一个新对象覆盖原型。覆盖原型将导致继承出现问题:重设原型将覆盖原有原型!
方法可以返回
this
来实现方法链式使用。写一个自定义的
toString()
方法是可以的,但是确保它可以正常工作且不会产生副作用。↑ 回到编码规范目录
事件
当给事件附加数据时(无论是 DOM 事件还是私有事件),传入一个哈希而不是原始值。这样可以让后面的贡献者增加更多数据到事件数据而无需找出并更新事件的每一个处理器。例如,不好的写法:
更好的写法:
↑ 回到编码规范目录
模块
模块应该以
!
开始。这样确保了当一个不好的模块忘记包含最后的分号时,在合并代码到生产环境后不会产生错误。详细说明文件应该以驼峰式命名,并放在同名的文件夹里,且与导出的名字一致。
增加一个名为
noConflict()
的方法来设置导出的模块为前一个版本并返回它。永远在模块顶部声明
'use strict';
。↑ 回到编码规范目录
jQuery
使用
$
作为存储 jQuery 对象的变量名前缀。缓存 jQuery 查询。
对 DOM 查询使用层叠
$('.sidebar ul')
或 父元素 > 子元素$('.sidebar > ul')
。 jsPerf对有作用域的 jQuery 对象查询使用
find
。↑ 回到编码规范目录
其他注意事项
ECMAScript 5 兼容性
参考 Kangax 的 ES5 兼容表。
ES5的严格模式下,以下情况下会显式的报错;所以要避免以下写法。
对未定义的变量赋值
操作被设置为不可写,不可配置或不可扩充的属性
删除变量,函数,参数
在对象直接量里重复定义属性
eval
做关键字,在eval的字符串里定义变量覆写
arguments
使用
arguments.caller
和arguments.callee
(匿名函数必须具名才能引用自己)(function(){
…}).call( null );
// Exception使用
with
特别注意
禁止扩展原生对象的原型,特别是
Object.prototype
。尽量不要在if的条件部分使用赋值表达式,如果确实想要在if条件部分赋值,那么把它括在另一对括号中,如:
if ((a = b)) {
...}
parseInt
的第一个参数的第一个字符是0
时,该字符串将被基于八进制而不是十进制求值。所以使用parseInt
方法时,建议总是提供第二个参数来指明基于十进制求值。因为javascript遵循二进制浮点数算术标准,所以不能正确地处理十进制的小数,因此在js中
0.1+0.2
不等于0.3
。但js中的整数运算是精确的,所以在需要精确浮点运算的时候,建议可以先乘以10的阶乘,使用整数部分运算,运算完后再除以10的阶乘。其他建议
使用
{}
代替new Object()
,使用[]
代替new Array()
;某些情况下使用
||
或&&
代替if
,如evt = evt || window.event
;避免在
if
和while
语句的条件部分赋值。如if(evt=window.event){}
鼓励
使用命名空间来管理所有代码中的对象和变量
使用闭包来隐藏临时变量、私有变量、私有方法。、
建议在类型确定时使用
===
和!==
运算符代替==
和!=
运算符。注意在ie下window!==window.parent
基础类及工具类开发流程
主要参考Extjs、Kendo UI、dojo,因为这几个js框架都有比较多的组件:考虑了复杂的应用情况,同时也有较多的项目应用,我们需要的应用其中上都可以在这两个js框架中找到切实可行的解决方案。
调研同类组件,整理成文档,分析列举出各种同类组件的优劣。主要参考Extjs、Kendo UI、dojo,因为这几个js框架都有比较多的组件:考虑了复杂的应用情况,同时也有较多的项目应用,我们需要的应用其中上都可以在这两个js框架中找到切实可行的解决方案。
控件的表现,要参考Material UI,这几个JS框架比较新,并且注重在不同终端下的易用性。
确定组件要实现的功能,确定好组件的 public api.:
代码上,精简小巧,越小越好。功能上,遵循8/2原则,用 20% 的代码,开发出 80% 的常用功能即可,扩展上,适度灵活,提供扩展接口,让用户可以通过扩展,完成不常用的 20% 功能
组件可以从已存在的DOM元素进行初始化,也可以纯配置初始化生成DOM。
要有响应式特性,考虑在手机上的使用。
The text was updated successfully, but these errors were encountered: