译]JavaScript规范-葵花宝典
2015-04-10 16:21 by yonghu86, 319 阅读, 6 评论, 收藏, 编辑
【译】JavaScript规范
译自:https://github.com/airbnb/javascript
类型
-
原始值: 相当于传值
|
1
2
3
4
5
6
7
8
9
10
11
|
stringnumberbooleannullundefinedvar foo = 1, bar = foo;bar = 9;console.log(foo, bar); // => 1, 9 |
复杂类型: 相当于传引用
-
123456789
objectarrayfunctionvarfoo = [1, 2],bar = foo;bar[0] = 9;console.log(foo[0], bar[0]);// => 9, 9
对象
-
使用字面值创建对象
12345// badvaritem =newObject();// goodvaritem = {}; -
不要使用保留字 reserved words 作为键
12345678910111213// badvarsuperman = {class:'superhero',default: { clark:'kent'},private:true};// goodvarsuperman = {klass:'superhero',defaults: { clark:'kent'},hidden:true};
数组
-
使用字面值创建数组
12345// badvaritems =newArray();// goodvaritems = []; -
如果你不知道数组的长度,使用push
12345678varsomeStack = [];// badsomeStack[someStack.length] ='abracadabra';// goodsomeStack.push('abracadabra'); -
当你需要拷贝数组时使用slice. jsPerf
1234567891011varlen = items.length,itemsCopy = [],i;// badfor(i = 0; i < len; i++) {itemsCopy[i] = items[i];}// gooditemsCopy = items.slice(); -
使用slice将类数组的对象转成数组.
1234functiontrigger() {varargs = Array.prototype.slice.call(arguments);...}
字符串
-
对字符串使用单引号
''1234567891011// badvarname ="Bob Parr";// goodvarname ='Bob Parr';// badvarfullName ="Bob "+this.lastName;// goodvarfullName ='Bob '+this.lastName; -
超过80个字符的字符串应该使用字符串连接换行
-
注: 如果过度使用,长字符串连接可能会对性能有影响. jsPerf & Discussion
12345678910111213141516171819// 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.'; -
编程时使用join而不是字符串连接来构建字符串,特别是IE: jsPerf.
1234567891011121314151617181920212223242526272829303132333435363738varitems,messages,length, i;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++) {items[i] = messages[i].message;}return'<ul><li>'+ items.join('</li><li>') +'</li></ul>';}
<函数
-
函数表达式:
1234567891011121314// 匿名函数表达式varanonymous =function() {returntrue;};// 有名函数表达式varnamed =functionnamed() {returntrue;};// 立即调用函数表达式(function() {console.log('Welcome to the Internet. Please follow me.');})(); -
绝对不要在一个非函数块里声明一个函数,把那个函数赋给一个变量。浏览器允许你这么做,但是它们解析不同。
-
注: ECMA-262定义把
块定义为一组语句,函数声明不是一个语句。阅读ECMA-262对这个问题的说明.12345678910111213// badif(currentUser) {functiontest() {console.log('Nope.');}}// goodif(currentUser) {vartest =functiontest() {console.log('Yup.');};} -
绝对不要把参数命名为
arguments, 这将会逾越函数作用域内传过来的arguments对象.123456789// badfunctionnope(name, options, arguments) {// ...stuff...}// goodfunctionyup(name, options, args) {// ...stuff...}
属性
-
当使用变量访问属性时使用中括号.
12345678910varluke = {jedi:true,age: 28};functiongetProp(prop) {returnluke[prop];}varisJedi = getProp('jedi');
变量
-
总是使用
var来声明变量,如果不这么做将导致产生全局变量,我们要避免污染全局命名空间。12345// badsuperPower =newSuperPower();// goodvarsuperPower =newSuperPower(); -
使用一个
var以及新行声明多个变量,缩进4个空格。123456789// badvaritems = getItems();vargoSportsTeam =true;vardragonball ='z';// goodvaritems = getItems(),goSportsTeam =true,dragonball ='z'; -
最后再声明未赋值的变量,当你想引用之前已赋值变量的时候很有用。
1234567891011121314151617// badvari, len, dragonball,items = getItems(),goSportsTeam =true;// badvari, items = getItems(),dragonball,goSportsTeam =true,len;// goodvaritems = getItems(),goSportsTeam =true,dragonball,length,i; -
在作用域顶部声明变量,避免变量声明和赋值引起的相关问题。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253// badfunction() {test();console.log('doing stuff..');//..other stuff..varname = getName();if(name ==='test') {returnfalse;}returnname;}// goodfunction() {varname = getName();test();console.log('doing stuff..');//..other stuff..if(name ==='test') {returnfalse;}returnname;}// badfunction() {varname = getName();if(!arguments.length) {returnfalse;}returntrue;}// goodfunction() {if(!arguments.length) {returnfalse;}varname = getName();returntrue;}
条件表达式和等号
- 适当使用
===和!==以及==和!=. -
条件表达式的强制类型转换遵循以下规则:
- 对象 被计算为 true
- Undefined 被计算为 false
- Null 被计算为 false
- 布尔值 被计算为 布尔的值
- 数字 如果是 +0, -0, or NaN 被计算为 false , 否则为 true
- 字符串 如果是空字符串
''则被计算为 false, 否则为 true
1234if([0]) {// true// An array is an object, objects evaluate to true} -
使用快捷方式.
12345678910111213141516171819// badif(name !=='') {// ...stuff...}// goodif(name) {// ...stuff...}// badif(collection.length > 0) {// ...stuff...}// goodif(collection.length) {// ...stuff...} -
阅读 Truth Equality and JavaScript 了解更多
块
-
给所有多行的块使用大括号
12345678910111213141516171819// badif(test)returnfalse;// goodif(test)returnfalse;// goodif(test) {returnfalse;}// badfunction() {returnfalse; }// goodfunction() {returnfalse;}
注释
-
使用
/** ... */进行多行注释,包括描述,指定类型以及参数值和返回值123456789101112131415161718192021222324252627// 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;} -
使用
//进行单行注释,在评论对象的上面进行单行注释,注释前放一个空行.12345678910111213141516171819202122232425// 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帮助其他人迅速理解1234567891011121314functionCalculator() {// FIXME: shouldn't use a global heretotal = 0;returnthis;}functionCalculator() {// TODO: total should be configurable by an options paramthis.total = 0;returnthis;}
空白
-
将tab设为4个空格
1234567891011121314// badfunction() {∙∙varname;}// badfunction() {∙varname;}// goodfunction() {∙∙∙∙varname;} -
大括号前放一个空格
123456789101112131415161718192021// badfunctiontest(){console.log('test');}// goodfunctiontest() {console.log('test');}// baddog.set('attr',{age:'1 year',breed:'Bernese Mountain Dog'});// gooddog.set('attr', {age:'1 year',breed:'Bernese Mountain Dog'}); -
在做长方法链时使用缩进.
1234567891011121314151617181920212223242526// bad$('#items').find('.selected').highlight().end().find('.open').updateCount();// good$('#items').find('.selected').highlight().end().find('.open').updateCount();// badvarleds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led',true).attr('width', (radius + margin) * 2).append('svg:g').attr('transform','translate('+ (radius + margin) +','+ (radius + margin) +')').call(tron.led);// goodvarleds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led',true).attr('width', (radius + margin) * 2).append('svg:g').attr('transform','translate('+ (radius + margin) +','+ (radius + margin) +')').call(tron.led);
逗号
-
不要将逗号放前面
12345678910111213141516171819202122232425// badvaronce, upon, aTime;// goodvaronce,upon,aTime;// badvarhero = {firstName:'Bob', lastName:'Parr', heroName:'Mr. Incredible', superPower:'strength'};// goodvarhero = {firstName:'Bob',lastName:'Parr',heroName:'Mr. Incredible',superPower:'strength'}; -
不要加多余的逗号,这可能会在IE下引起错误,同时如果多一个逗号某些ES3的实现会计算多数组的长度。
123456789101112131415161718192021// badvarhero = {firstName:'Kevin',lastName:'Flynn',};varheroes = ['Batman','Superman',];// goodvarhero = {firstName:'Kevin',lastName:'Flynn'};varheroes = ['Batman','Superman'];
分号
-
语句结束一定要加分号
1234567891011121314151617// bad(function() {varname ='Skywalker'returnname})()// good(function() {varname ='Skywalker';returnname;})();// good;(function() {varname ='Skywalker';returnname;})();
类型转换
- 在语句的开始执行类型转换.
-
字符串:
12345678910111213// => this.reviewScore = 9;// badvartotalScore =this.reviewScore +'';// goodvartotalScore =''+this.reviewScore;// badvartotalScore =''+this.reviewScore +' total score';// goodvartotalScore =this.reviewScore +' total score'; -
对数字使用
parseInt并且总是带上类型转换的基数.123456789101112131415161718192021222324252627varinputValue ='4';// badvarval =newNumber(inputValue);// badvarval = +inputValue;// badvarval = inputValue >> 0;// badvarval = parseInt(inputValue);// goodvarval = Number(inputValue);// goodvarval = parseInt(inputValue, 10);// 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; -
布尔值:
12345678910varage = 0;// badvarhasAge =newBoolean(age);// goodvarhasAge = Boolean(age);// goodvarhasAge = !!age;
命名约定
-
避免单个字符名,让你的变量名有描述意义。
123456789// badfunctionq() {// ...stuff...}// goodfunctionquery() {// ..stuff..} -
当命名对象、函数和实例时使用驼峰命名规则
123456789101112131415// badvarOBJEcttsssss = {};varthis_is_my_object = {};varthis-is-my-object = {};functionc() {};varu =newuser({name:'Bob Parr'});// goodvarthisIsMyObject = {};functionthisIsMyFunction() {};varuser =newUser({name:'Bob Parr'}); -
当命名构造函数或类时使用驼峰式大写
1234567891011121314151617// badfunctionuser(options) {this.name = options.name;}varbad =newuser({name:'nope'});// goodfunctionUser(options) {this.name = options.name;}vargood =newUser({name:'yup'}); -
命名私有属性时前面加个下划线
_123456// badthis.__firstName__ ='Panda';this.firstName_ ='Panda';// goodthis._firstName ='Panda'; -
当保存对
this的引用时使用_this.1234567891011121314151617181920212223// badfunction() {varself =this;returnfunction() {console.log(self);};}// badfunction() {varthat =this;returnfunction() {console.log(that);};}// goodfunction() {var_this =this;returnfunction() {console.log(_this);};}
存取器
- 属性的存取器函数不是必需的
-
如果你确实有存取器函数的话使用getVal() 和 setVal('hello')
1234567891011// baddragon.age();// gooddragon.getAge();// baddragon.age(25);// gooddragon.setAge(25); -
如果属性是布尔值,使用isVal() 或 hasVal()
123456789// badif(!dragon.age()) {returnfalse;}// goodif(!dragon.hasAge()) {returnfalse;} -
可以创建get()和set()函数,但是要保持一致
12345678910111213functionJedi(options) {options || (options = {});varlightsaber = options.lightsaber ||'blue';this.set('lightsaber', lightsaber);}Jedi.prototype.set =function(key, val) {this[key] = val;};Jedi.prototype.get =function(key) {returnthis[key];};
构造器
-
给对象原型分配方法,而不是用一个新的对象覆盖原型,覆盖原型会使继承出现问题。
1234567891011121314151617181920212223functionJedi() {console.log('new jedi');}// badJedi.prototype = {fight:functionfight() {console.log('fighting');},block:functionblock() {console.log('blocking');}};// goodJedi.prototype.fight =functionfight() {console.log('fighting');};Jedi.prototype.block =functionblock() {console.log('blocking');}; -
方法可以返回
this帮助方法可链。1234567891011121314151617181920212223242526272829// badJedi.prototype.jump =function() {this.jumping =true;returntrue;};Jedi.prototype.setHeight =function(height) {this.height = height;};varluke =newJedi();luke.jump();// => trueluke.setHeight(20)// => undefined// goodJedi.prototype.jump =function() {this.jumping =true;returnthis;};Jedi.prototype.setHeight =function(height) {this.height = height;returnthis;};varluke =newJedi();luke.jump().setHeight(20); -
可以写一个自定义的toString()方法,但是确保它工作正常并且不会有副作用。
123456789101112functionJedi(options) {options || (options = {});this.name = options.name ||'no name';}Jedi.prototype.getName =functiongetName() {returnthis.name;};Jedi.prototype.toString =functiontoString() {return'Jedi - '+this.getName();};
事件
-
当给事件附加数据时,传入一个哈希而不是原始值,这可以让后面的贡献者加入更多数据到事件数据里而不用找出并更新那个事件的事件处理器
12345678// bad$(this).trigger('listingUpdated', listing.id);...$(this).on('listingUpdated',function(e, listingId) {// do something with listingId});更好:
12345678// good$(this).trigger('listingUpdated', { listingId : listing.id });...$(this).on('listingUpdated',function(e, data) {// do something with data.listingId});
模块
- 模块应该以
!开始,这保证了如果一个有问题的模块忘记包含最后的分号在合并后不会出现错误 - 这个文件应该以驼峰命名,并在同名文件夹下,同时导出的时候名字一致
- 加入一个名为noConflict()的方法来设置导出的模块为之前的版本并返回它
-
总是在模块顶部声明
'use strict';123456789101112131415161718// fancyInput/fancyInput.js!function(global) {'use strict';varpreviousFancyInput = global.FancyInput;functionFancyInput(options) {this.options = options || {};}FancyInput.noConflict =functionnoConflict() {global.FancyInput = previousFancyInput;returnFancyInput;};global.FancyInput = FancyInput;}(this);
jQuery
-
缓存jQuery查询
12345678910111213141516171819202122// badfunctionsetSidebar() {$('.sidebar').hide();// ...stuff...$('.sidebar').css({'background-color':'pink'});}// goodfunctionsetSidebar() {var$sidebar = $('.sidebar');$sidebar.hide();// ...stuff...$sidebar.css({'background-color':'pink'});} -
对DOM查询使用级联的
$('.sidebar ul')或$('.sidebar ul'),jsPerf -
对有作用域的jQuery对象查询使用
find1234567891011121314151617// bad$('.sidebar','ul').hide();// bad$('.sidebar').find('ul').hide();// good$('.sidebar ul').hide();// good$('.sidebar > ul').hide();// good (slower)$sidebar.find('ul');// good (faster)$($sidebar[0]).find('ul');
ECMAScript 5兼容性
-
参考Kangax的 ES5 compatibility table
性能
- On Layout & Web Performance
- String vs Array Concat
- Try/Catch Cost In a Loop
- Bang Function
- jQuery Find vs Context, Selector
- innerHTML vs textContent for script text
- Long String Concatenation
-
Loading...
资源
Read This
其它规范
- Google JavaScript Style Guide
- jQuery Core Style Guidelines
- Principles of Writing Consistent, Idiomatic JavaScript
其它风格
- Naming this in nested functions - Christian Johansen
- Conditional Callbacks
阅读更多
- Understanding JavaScript Closures - Angus Croll
书籍
- JavaScript: The Good Parts - Douglas Crockford
- JavaScript Patterns - Stoyan Stefanov
- Pro JavaScript Design Patterns - Ross Harmes and Dustin Diaz
- High Performance Web Sites: Essential Knowledge for Front-End Engineers - Steve Souders
- Maintainable JavaScript - Nicholas C. Zakas
- JavaScript Web Applications - Alex MacCaw
- Pro JavaScript Techniques - John Resig
- Smashing Node.js: JavaScript Everywhere - Guillermo Rauch
作者: EricHu
出处:http://www.cnblogs.com/huyong/
posted on
浙公网安备 33010602011771号