目录
1.类型
2.对象
3.数组
4.字符串
5.函数
6.属性
7.变量
8.条件表达式和等号
9.块
10.注释
11.空白
12.逗号
13.分号
14.类型转换
15.命名约定
16.存取器
17.构造器
18.事件
19.模块
20.jQuery
21.ES5兼容性
22.HTML、CSS、JavaScript分离
23.使用jsHint
24.前端工具
类型
原始值:相当于传值(JavaScript对象都提供了字面量),使用字面量创建对象。
string
number
boolean
null
undefined
1 var foo = 1, 2 bar = foo; 3 bar = 9; 4 5 console.log(foo,bar); //1 9
复杂类型:相当于传引用
object
array
function
1 var foo = [1,2], 2 bar = foo; 3 4 bar[0] = 9; 5 6 console.log(foo[0],bar[0]); //9 9
对象
使用字面值创建对象
1 //bad 2 var item = new Object(); 3 4 //good 5 var item = {};
不要使用保留字reserved words作为键
1 //bad 2 var superman = { 3 class:'superhero', 4 default:{clark:'kent'}, 5 private:true 6 }; 7 8 //good 9 var superman = { 10 klass:'superhero', 11 defaults:{clark:'kent'}, 12 hidden:true 13 };
数组
使用字面值创建数组
1 //bad 2 var items = new Array(); 3 4 //good 5 var items = [];
如果你不知道数组的长度,使用push
1 var someStack = []; 2 3 //bad 4 someStack[someStack.length] = 'xxx'; 5 6 //good 7 someStack.push('xxx');
当你需要拷贝数组时使用slice
1 var items = [1,2,3], 2 len = items.length, 3 itemsCopy = [], 4 i; 5 6 //bad 7 for(i = 0;i < len;i++){ 8 itemsCopy[i] = items[i]; 9 } 10 11 //good 12 itemsCopy = items.slice(); 13 14 console.log(itemsCopy); //[1, 2, 3]
使用slice将类数组的对象转成数组
1 function trigger(){ 2 var args = [].slice.apply(arguments); 3 //... 4 }
字符串
对字符串使用单引号' '
1 //bad 2 var name = "Bob Parr"; 3 4 //good 5 var name = 'Bob Parr'; 6 7 //bad 8 var fullName = "Bob" + this.lastName; 9 10 //good 11 var fullName = 'Bob' + this.lastName;
超过80(也有规定140的,项目具体可制定)个字符的字符串应该使用字符串连接换行。
注: 如果过度使用,长字符串连接可能会对性能有影响。
1 // bad 2 var errorMessage = '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.'; 3 4 // bad 5 var errorMessage = 'This is a super long error that 6 was thrown because of Batman. 7 When you stop to think about 8 how Batman had anything to do 9 with this, you would get nowhere 10 fast.'; 11 12 // good 13 var errorMessage = 'This is a super long error that ' + 14 'was thrown because of Batman.' + 15 'When you stop to think about ' + 16 'how Batman had anything to do ' + 17 'with this, you would get nowhere ' + 18 'fast.';
编程时用join而不是字符串连接来构建字符串
1 var items, 2 messages, 3 length, i; 4 5 messages = [{ 6 state: 'success', 7 message: 'This one worked.' 8 },{ 9 state: 'success', 10 message: 'This one worked as well.' 11 },{ 12 state: 'error', 13 message: 'This one did not work.' 14 }]; 15 16 length = messages.length; 17 18 // bad 19 function inbox(messages) { 20 items = '<ul>'; 21 22 for (i = 0; i < length; i++) { 23 items += '<li>' + messages[i].message + '</li>'; 24 } 25 26 return items + '</ul>'; 27 } 28 29 // good 30 function inbox(messages) { 31 items = []; 32 33 for (i = 0; i < length; i++) { 34 items[i] = messages[i].message; 35 } 36 37 return '<ul><li>' + items.join('</li><li>') + '</li></ul>'; 38 } 39 40 console.log(inbox(messages));
函数
函数表达式
1 //匿名函数表达式 2 var anonymous = function (){ 3 return true; 4 }; 5 6 //有名函数表达式 7 var named = function named(){ 8 return true; 9 }; 10 11 //立即调用函数表达式 12 (function (){ 13 console.log('Welcome to the Internet.Please follow me.'); 14 })();
绝对不要把参数命名为 arguments
, 这将会逾越函数作用域内传过来的 arguments
对象。
1 //bad 2 function nope(name,options,arguments){ 3 //...stuff... 4 } 5 6 //good 7 function yup(name,options,args){ 8 //...stuff... 9 }
属性
当使用变量和特殊非法变量名时,访问属性时可以使用中括号(.
优先)。
1 var luke = { 2 jedi:true, 3 age:28 4 }; 5 6 function getProp(prop){ 7 return luke[prop]; 8 } 9 10 var isJedi = getProp('jedi'); 11 console.log(isJedi);
变量
总是使用 var
来声明变量,如果不这么做将导致产生全局变量,我们要避免污染全局命名空间。
1 //bad 2 superPower = new SuperPower(); 3 4 //good 5 var superPower = new SuperPower();
使用一个 var
以及新行声明多个变量,缩进4个空格。
1 //bad 2 var items = getItems(); 3 var goSportsTeam = true; 4 var dragonball = 'z'; 5 6 //good 7 var items = getItems(), 8 goSportsTeam = true, 9 dragonball = 'z';
最后再声明未赋值的变量,当你想引用之前已赋值变量的时候很有用。
1 //bad 2 var i,len,dragonball, 3 items = getItems(), 4 goSportsTeam = true; 5 6 //bad 7 var i, items = getItems(), 8 dragonball, 9 goSportsTeam = true, 10 len; 11 12 //good 13 var items = getItems(), 14 goSportsTeam = true, 15 dragonball, 16 length, 17 i;
在作用域顶部声明变量,避免变量声明和赋值引起的相关问题。
1 // bad 2 function fn() { 3 test(); 4 console.log('doing stuff..'); 5 6 //..other stuff.. 7 8 var name = getName(); 9 10 if (name === 'test') { 11 return false; 12 } 13 14 return name; 15 } 16 17 // good 18 function fn() { 19 var name = getName(); 20 21 test(); 22 console.log('doing stuff..'); 23 24 //..other stuff.. 25 26 if (name === 'test') { 27 return false; 28 } 29 30 return name; 31 } 32 33 // bad 34 function fn() { 35 var name = getName(); 36 37 if (!arguments.length) { 38 return false; 39 } 40 41 return true; 42 } 43 44 // good 45 function fn() { 46 if (!arguments.length) { 47 return false; 48 } 49 50 var name = getName(); 51 52 return true; 53 }
条件表达式和等号
合理使用 === 和 !== 以及 == 和 !=
合理使用表达式逻辑操作运算
条件表达式的强制类型转换遵循以下规则:
对象 被计算为true
Undefined 被计算为false
Null 被计算为false
布尔值 被计算为布尔的值
数字 如果是+0,-0,or NaN被计算为false,否则为true
字符串 如果是空字符串 '' 则被计算为false,否则为true
1 if([0]){ 2 console.log('success'); 3 //true 4 //An array is an object,objects evaluate to true 5 }
使用快捷方式
1 //bad 2 if(name !== ''){ 3 //...stuff... 4 } 5 6 //good 7 if(name){ 8 //...stuff.. 9 } 10 11 //bad 12 if(collection.length > 0){ 13 //...stuff... 14 } 15 16 //good 17 if(collection.length){ 18 //...stuff... 19 }
块
给所有多行的块使用大括号
1 //bad 2 if(test) 3 return false; 4 5 //good 6 if(test) return false; 7 8 //good 9 if(test){ 10 return false; 11 } 12 13 //bad 14 function fn(){ return false;} 15 16 //good 17 function fn(){ 18 return false; 19 }
注释
使用 /** ... */ 进行多行注释,包括描述,指定类型以及参数值和返回值。
1 //bad 2 //make() return a new element 3 //based on the passed in tag name 4 // 5 //@param <String> tag 6 7 //good 8 /** 9 * make() returns a new element 10 * based on the passed in the tag name 11 * 12 * @param <String> tag 13 * @return <Element> element 14 */ 15 function make(tag){ 16 //...stuff... 17 return element; 18 }
使用 // 进行单行注释,在评论对象的上面进行单行注释,注释前放一个空行。
1 //bad 2 var active = true; // is current tab 3 4 //good 5 // is current tab 6 var active = true; 7 8 //bad 9 function getType() { 10 console.log('fetching type...'); 11 // set the default type to 'no type' 12 var type = this._type || 'no type'; 13 14 return type; 15 } 16 17 // good 18 function getType() { 19 console.log('fetching type...'); 20 21 // set the default type to 'no type' 22 var type = this._type || 'no type'; 23 24 return type; 25 }
如果你有一个问题需要重新来看一下或如果你建议一个需要被实现的解决方法的话需要在你的注释前面加上 FIXME 或 TODO 帮助其他人迅速理解
1 function Calculator(){ 2 3 // FIXME: shouldn't use a global here 4 total = 0; 5 6 return this; 7 8 } 9 10 function Calculator(){ 11 12 // TODO: shouldn't use a global here 13 total = 0; 14 15 return this; 16 17 }
空白
缩进、格式化能帮助团队更快得定位修复代码BUG。
将tab设为4个空格。
1 // bad 2 function() { 3 ∙∙var name; 4 } 5 6 // bad 7 function() { 8 ∙var name; 9 } 10 11 // good 12 function() { 13 ∙∙∙∙var name; 14 }
大括号前放一个空格
1 //bad 2 function test(){ 3 console.log('test'); 4 } 5 6 //good 7 function test() { 8 console.log('test'); 9 } 10 11 //bad 12 dog.set('attr',{ 13 age:'1 year', 14 breed:'Bernese Mountain Dog' 15 }); 16 17 //good 18 dog.set('attr', { 19 age:'1 year', 20 breed:'Bernese Mountain Dog' 21 });
在做长链方法时使用缩进
1 // bad 2 $('#items').find('.selected').highlight().end().find('.open').updateCount(); 3 4 // good 5 $('#items') 6 .find('.selected') 7 .highlight() 8 .end() 9 .find('.open') 10 .updateCount(); 11 12 // bad 13 var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').class('led', true) 14 .attr('width', (radius + margin) * 2).append('svg:g') 15 .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') 16 .call(tron.led); 17 18 // good 19 var leds = stage.selectAll('.led') 20 .data(data) 21 .enter().append('svg:svg') 22 .class('led', true) 23 .attr('width', (radius + margin) * 2) 24 .append('svg:g') 25 .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')') 26 .call(tron.led);
逗号
不要将逗号放前面
1 //bad 2 var once 3 ,upon 4 ,aTime; 5 6 //good 7 var once, 8 upon, 9 aTime; 10 11 //bad 12 var hero = { 13 firstName: 'Bob' 14 , lastName: 'Parr' 15 , heroName: 'Mr. Incredible' 16 , superPower: 'strength' 17 }; 18 19 //good 20 var hero = { 21 firstName:'Bob', 22 lastName:'Parr', 23 heroName:'Mr. Incredible', 24 superPower:'strength' 25 };
不要加多余的逗号,这可能会在IE下引起错误,同时如果多一个逗号某些ES3的实现会计算多数组的长度
1 // bad 2 var hero = { 3 firstName: 'Kevin', 4 lastName: 'Flynn', 5 }; 6 7 var heroes = [ 8 'Batman', 9 'Superman', 10 ]; 11 12 // good 13 var hero = { 14 firstName: 'Kevin', 15 lastName: 'Flynn' 16 }; 17 18 var heroes = [ 19 'Batman', 20 'Superman' 21 ];
分号
语句结束一定要加分号
1 // bad 2 (function() { 3 var name = 'Skywalker' 4 return name 5 })() 6 7 // good 8 (function() { 9 var name = 'Skywalker'; 10 return name; 11 })(); 12 13 // good 14 ;(function() { 15 var name = 'Skywalker'; 16 return name; 17 })();
类型转换
在语句的开始执行类型转换
字符串:
1 // => this.reviewScore = 9; 2 3 //bad 4 var totalScore = this.reviewScore + ''; 5 6 //good 7 var totalScore = '' + this.reviewScore; 8 9 //bad 10 var totalScore = '' + this.reviewScore + ' total score'; 11 12 //good 13 var totalScore = this.reviewScore + ' total score';
对数字使用 parseInt 并且总是带上类型转换的基数,如 parseInt(value,10)
1 var inputValue = '4'; 2 3 //bad 4 var val = new Number(inputValue); 5 6 //bad 7 var val = +inputValue; 8 9 //bad 10 var val = inputValue >> 0; 11 12 //bad 13 var val = parseInt(inputValue); 14 15 //good 16 var val = Number(inputValue); 17 18 //good 19 var val = parseInt(inputValue,10);
布尔值
1 var age = 0; 2 3 //bad 4 var hasAge = new Boolean(age); 5 6 //good 7 var hasAge = Boolean(age); 8 9 //good 10 var hasAge = !!age;
命名约定
避免单个字符名,让你的变量名有描述意义
1 //bad 2 function q(){ 3 //...stuff... 4 } 5 6 //good 7 function query(){ 8 //...stuff... 9 }
当命名对象、函数和实例时使用驼峰命名规则
1 //good 2 var thisIsMyObject = {}; 3 4 function thisIsMyFunction(){ 5 var user = new User({ 6 name:'Bob Parr' 7 }); 8 }
当命名构造函数或类时使用驼峰式大写
1 //good 2 function User(options){ 3 this.name = options.name; 4 } 5 6 var good = new User({ 7 name:'yup' 8 });
命名私有属性时前加个下划线 _ :
1 //good 2 this._firstName = 'Panda';
当保存对 this
的引用时使用 self(python 风格)
1 //good 2 function fn(){ 3 var self = this; 4 5 return function (){ 6 console.log(self); 7 }(); 8 }
存取器
属性的存取器函数不是必须的
如果你确实有存取器函数的话使用 getVal() 和 setVal()
如果属性是布尔值,使用 isVal() 或 hasVal()
1 //bad 2 if(!dragon.age()){ 3 return false; 4 } 5 6 //good 7 if(!dragon.hasAge()){ 8 return false; 9 }
可以创建 get() 和 set() 函数,但是要保持一致
1 function Jedi(options){ 2 options || (options = {}); 3 var lightsaber = options.lightsaber || 'blue'; 4 this.set('lightsaber',lightsaber); 5 } 6 7 Jedi.prototype.set = function (key,val) { 8 this[key] = val; 9 }; 10 11 Jedi.prototype.get = function (key) { 12 return this[key]; 13 };
后面比较长。。详见:http://www.w3cschool.cc/w3cnote/javascript-guide.html?from=timeline&isappinstalled=0#constructors
有时间学完补完