Javascript团队规范(总)

2016-05-31  本文已影响35人  天外来人

Arrays

1 给数组添加项时,使用push 而不用 arr[arr.length] = ''"

var arr = [];

//bad
arr[arr.length] = '123321';

//good
arr.push('123321');

2 复制数组时候:使用slice

var len = items.length;
var itemsCopy = [];
var i;

//bad
for(i = 0; i < len; i++){
  itemsCopy[i] = item[i];
}

//good
itemsCopy = items.slice();

3 将一个类数组转成数组时候:使用slice

var args = Array.prototype.slice.call(arr);

Functions

1 不要在非函数代码块(if while 等)中声明函数, 把那个函数赋给一个变量。浏览器允许你这么做,但它们的解析表现不一致。

// bad
if (currentUser) { 
  function test() { 
    console.log('Nope.'); 
  }
}
// good
var test;
if (currentUser) { 
  test = function test() {
    console.log('Yup.'); 
  };
}

2 永远不要把参数命名为 arguments. 这将取代函数作用域内的arguments对象。

Properties

1 使用.来访问对象的属性

var luke = {
  jedi: true,
  age: 28
};

//bad
var isJedi = luke['jedi'];

//good
var isJedi = luke.jedi;

2 当通过变量访问属性时使用中括号[]。

var luke = {
  jedi: true, 
  age: 28
};
function getProp(prop) { 
  return luke[prop];
}
var isJedi = getProp('jedi');

变量

1 总是使用var 来声明变量。避免产生全局变量,避免污染全局命名空间。
2 每个var 只能声明一个变量。原因:如果var 声明多给变量,容易导致较长的行长度,并且在修改时容易造成逗号和分号的混淆.
3 在作用域的顶部声明变量,这样做,可以避免因变量提升而带来的问题。

//bad
function () {
  test();
  console.log("doing stuff...");
  //..other stuff..
  if(name === 'test') {
    return false;
  }
  return name;
}
//good
function () {
  var name = getName();
  test();
  console.log('dong stuff..');
  //..other stuff..
  if(name === 'test'){
    return false;
  }
  return name;
}

4 最后声明未赋值的变量。当你需要引用前面的变量赋值时这将变得很有作用。

//bad
var i;
var items = getItems();
var dragonball;
var goSportsTeam = true;
var len;

//good
var items = getItems();
var dragonball;
var goSportsTeam  = true;
var len;

变量提升

1 变量声明会提升至作用域顶部,但赋值不会。
2 匿名函数表达式会提升它们的变量名,但不会提升函数的赋值
3 命名函数表达式会提升变量名,但不会提升函数名或函数体
4 函数声明提升它们的名字和函数体

function example() { 
  console.log(named); // => undefined 
  named(); // => TypeError named is not a function 
  superPower(); // => ReferenceError superPower is not defined   
  
 var named = function superPower() { 
    console.log('Flying'); 
  };}

function example() { 
   console.log(named); // => undefined 
   named(); // => TypeError named is not a function 
   var named = function named() { 
    console.log('named'); 
  }
}

条件

1 优先使用 === 和 !== 而不是 == 和 !=
2 尽可能使用简洁的表达式。

//字符串为空
// good
if (!name){
}
// bad
if (name === ''){
}

//字符串非空
// good
if (name) {
}
// bad
if(name !== ''){
}

//数组非空
// good
if (collection.length) {
}
// bad
if(collection.length > 0){
}

//布尔不成立
// good
if(!notTrue){
}
// bad
if(notTrue === false){
}

// null 或 undefined
// good
if(noValue == null){
}
// bad
if(noValue === null || typeof noValue === 'undefined'){
}

3 按执行频率排列分支的顺序。原因:提高执行效率和检查代码的出错效率。

命名

1 变量,函数名、函数的参数,类的属性、方法,命名空间使用Camel(骆驼)命名法。

var loadingModules = {}; //变量
function stringFormat(theBells) {}; //函数名,参数
function Person(name, age){  //类的属性,方法
  this.name = name;
  this.age = age;
}
Person.prototype.getName = function() {};
equipments.heavyWeapons = {}; //命名空间

2 类名,枚举变量名使用Pascal(帕斯卡)命名法。

function TextNode() {} //类名
var TargetState = {}; //枚举变量

3 常量,枚举变量的属性 使用 全部字母大写,单词间以下划线分隔 的命名方式。

var HTML_ENTITY = {}; //常量
var TargetState = { //枚举变量属性
  READING: 1,
  READED: 2,
  READY: 3
};

4 以下划线"_"开头命名私有变量

//bad
this._firstName_ = "123";
this.firstName = '123';

//good
this._firstName = '123';

5 当要保存this时候,使用_this来保存

//bad
function () {
  var self = this;
  return function () {
    console.log(self);
  }
}
//good
function () {
  var _this = this;
  return function () {
    console.log(_this);
  }
}

6 类名使用 名词,函数名使用 动宾短语, Promise对象(遗留问题) 用动宾短语的进行时。

function Engine(options) {} //类名
function getStyle(){ //函数名
} 
var loadingData = ajax.get('url'); //Promise对象
loadingData.then(callback);

7 boolean 类型的变量使用 is 或 has 开头。

var isReady = false;
var hasMoreCommands = false;

8 给函数命名。这在做堆栈轨迹时很有帮助

//bad
var log = function (msg) {
  console.log(msg);
};
//good
var log = function log(msg) {
  console.log(msg);
}

9 如果你的文件导出一个类,你的文件名应该与类名完全相同

class checkBox {
  //..
}
module.exports = checkBox;
//in some other file
//bad
var CheckBox = require('./checkBox');
//bad
var CheckBox = require('./check_box');
//good
var CheckBox = require('./CheckBox');

空格

此部分只需要了解,因为sublineText3的格式化代码插件已经帮助开发人员做到了
1 二元运算符两侧必须有一个空格,一元运算符与操作对象之间不允许有空格。

a = b + c;
var a = !true;

2 用作代码块起始的左花括号"{"前必须有一个空格。

//bad
function show (){
}
//good
function show () {
}

3 if / else / for / while / function...关键字后,必须有一个空格。

if (condition) {
}

4 对象中,属性中":"之后必须有空格,":"之前不允许有空格。

  var obj = {
    a: 1,
    b: 2
  };

5 "," 和";"前不允许有空格。

//bad
callFunc(a , b);

//good
callFunc(a, b); 

6 在函数调用、函数声明、括号表达式、属性访问、if/for 等语句中,()和 [] 内紧贴括号部分不允许有空格。

//  bad
callFunc( param1, param2, param3 );
if( num > list.length ){
}
while( len-- ){
}

//  good
callFunc(param1, param2, param3);
if(num > list.length)}{
}
while(len--) {
}

换行问题

1 单行声明的数组与对象,如果包含元素,{}和[]内紧贴括号部分不允许包含空格。另外当内部元素的形式较为复杂时候,还应该换行书写。

//bad
var arr1 = [ 1, 2, 3 ];
var obj3 = { name: 'obj', age: 20};

//good
var arr1 = [1, 2, 3];
var obj1 = {
  name: 'obj',
  age: 20,
  sex: 1
};

2 运算符处换行时,运算符必须在新行的行首。(并未强调换行时,运算符必须在行首)

if (user.isAuthenticated() 
    && user.isInRole('admin') 
    && user.hasAuthority('add-admin') 
    || user.hasAuthority('delete-admin')
) {
    // Code
}
var result = number1 + number2 + number3 
                   + number4 + number5;

3 在语句的行长度超过 120 时, 根据逻辑条件合理缩进。(额外)

// 按一定长度截断字符串,并使用 + 运算符进行连接。
// 分隔字符串尽量按语义进行,如不要在一个完整的名词中间断开。
// 特别的,对于HTML片段的拼接,通过缩进,保持和HTML相同的结构。
var html = '' // 此处用一个空字符串,以便整个HTML片段都在新行严格对齐 
    + '<article>' 
    + '<h1>Title here</h1>' 
    + '<p>This is a paragraph</p>' 
    + '<footer>Complete</footer>' 
    + '</article>';
// 也可使用数组来进行拼接,相对 + 更容易调整缩进。
var html = [ 
    '<article>', 
      '<h1>Title here</h1>', 
      '<p>This is a paragraph</p>',    
    '</article>'];
html = html.join('');

// 当参数过多时,将每个参数独立写在一行上,并将结束的右括号 ) 独立一行。
// 所有参数必须增加一个缩进。
foo(
  aVeryVeryLongArgument, 
  anotherVeryLongArgument, 
  callback
);

// 链式调用较长时采用缩进进行调整。
$('#items') 
    .find('.selected')
    .highlight() 
    .end();

// 也可以按逻辑对参数进行组合。
// 最经典的是baidu.format函数,调用时将参数分为“模板”和“数据”两块
baidu.format( 
  dateFormatTemplate, 
  year, month, date, hour, minute, second
);

4 当在程序中生成一个字符串时候,使用Array 而不是用 "+"拼接

var items;
var messages;
var length;
var 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;

// bad
function inbox(messages) { 
  items = '<ul>'; 
  for (i = 0; i < length; i++) { 
    items += '<li>' + messages[i].message + '</li>'; 
  } 
  return items + '</ul>';
}
// good
function inbox(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>';
}

类型转换

在语句开始时执行类型转换
1 转字符串

//bad
var str = str2 + '';
//good
var str = '' + str2;

//bad
var str = '' + str2 + '123';
//good
var str = '123' + str2;

2 转Number,转换数字时总是带上类型转换基数

var num = '4';

//bad
var val = parseInt(num);

//good
var val = Number(num);
var val = parseInt(inputValue, 10);

3 转Booleans

var age = 0;

//bad
var hasAge = new Boolean(age);

//good
var hasAge = Boolean(age);
var hasAge = !!age

构造函数

给对象原型分配方法,而不是使用一个新对象覆盖原型。覆盖原型将导致继承出现问题:重设原型将覆盖原有原型!

function Jedi() { 
  console.log('new jedi');
}

// bad
Jedi.prototype = { 
  fight: function fight() { 
    console.log('fighting');
  }, 
  block: function block() { 
    console.log('blocking'); 
  }
};

// good
Jedi.prototype.fight = function fight() {   
  console.log('fighting');
};
Jedi.prototype.block = function block() { 
  console.log('blocking');
};

2 为了能实现链式调用,可以在每个方法中返回return this

// bad
Jedi.prototype.jump = function jump() { 
  this.jumping = true; 
  return true;
};

Jedi.prototype.setHeight = function setHeight(height) { 
  this.height = height;
};

var luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined

// good
Jedi.prototype.jump = function jump() { 
  this.jumping = true; 
  return this;
};
Jedi.prototype.setHeight = function setHeight(height) { 
  this.height = height; 
  return this;
};
var luke = new Jedi();
luke.jump() 
      .setHeight(20);

事件

在注册事件(on)以及触发注册事件(trigger)中,参数要以json的格式传递。这是为了以后修改过程中,不需要更新trigger函数。

//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
});

JQuery

1 jQuery对象以$开发命名

// bad
var sidebar = $('.sidebar');
// good
var $sidebar = $('.sidebar');

2 当多次使用jQuery对象的时候,缓存jQuery对象

// bad
function setSidebar() { 
  $('.sidebar').hide(); 
  // ...stuff... 
  $('.sidebar').css({ 'background-color': 'pink' });}
  
 // good
 function setSidebar() { 
   var $sidebar = $('.sidebar'); 
   $sidebar.hide(); 
   // ...stuff... 
   $sidebar.css({ 
    'background-color': 'pink' 
   });
}

3 查找jQuery对象的时候,如果存在层级(父子)关系的时候,使用$('.sidebar ul') 或 $('.sidebar > ul')

//bad
$('ul', '.sidebar').hide();
$('.sidebar').find('ul').hide();

//good
$('.sidebar ul').hide();
$('.sidebar > ul').hide();
$sidebar.find('ul').hide();

4 对有作用域的jQuery对象查询使用find

参考文献
https://github.com/airbnb/javascript/tree/master/es5#naming-conventions
https://github.com/sivan/javascript-style-guide/blob/master/es5/README.md#variables

上一篇下一篇

猜你喜欢

热点阅读