前端JavaScript规范

目录

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() {
 8var 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

有时间学完补完

原文地址:https://www.cnblogs.com/liuqiuchen/p/4522013.html