最近开始学习Meteor框架的使用,按照官网的Guide一步步来吧
首先是JavaScript Coding Style,转载自Airbnb style guide,部分作了删减
- 引用
1、对所有引用使用const;不要使用var
这样可以保证你无法对引用重新赋值,也不会导致出现bug或难以理解
// bad
var a = 1;
var b = 2;
// good
const a = 1;
const b = 2;
2、如果一定需要可变动的引用,使用let代替var
因为let是块级作用域,而var是函数作用域
// bad
var count = 1;
if (true) {
count += 1;
}
// good, use let.
let count = 1;
if (true) {
count += 1;
}
3、注意let和const都是块级作用域
// let和const都只存在于定义它们的区块内
{
let a = 1;
const b = 2;
}
console.log(a); // ReferenceError
console.log(b); // ReferenceError
- 对象
1、使用字面值创建新对象
// bad
const item = new Object();
// good
const item = {};
2、创建有动态属性名的对象时,使用可被计算的属性名称
这样你可以在一个地方定义所有的对象属性
function getKey(k) {
return `a key name ${k}`;
}
// bad
const obj = {
id: 5,
name: 'San Francisco',
};
obj[getKey('enable')] = true;
// good
const obj = {
id: 5,
name: 'San Francisco',
[getKey('enable')] = true,
};
3、使用对象方法的简写
// bad
const atom = {
value: 1,
addValue function (value) {
return atom.value + value;
},
};
// good
const atom = {
value: 1,
addValue(value) {
return atom.value + value;
},
};
4、使用对象属性值的简写
更短更有描述性
const lukeSkywalker = 'Luke Skywalker';
// bad
const obj = {
lukeSkywalker: lukeSkywalker,
};
// good
const obj = {
lukeSkywalker,
}
5、在对象属性声明前把简写的属性分组
这样可以清楚的看到哪些属性使用了简写
const anakinSkywalker = 'Anakin Skywalker';
const lukeSkywalker = 'Luke Skywalker';
// bad
const obj = {
episodeOne: 1,
twoJedisWalkIntoACantina: 2,
lukeSkywalker,
episodeThree: 3,
mayTheFourth: 4,
anakinSkywalker,
};
// good
const obj = {
lukeSkywalker,
anakinSkywalker,
episodeOne: 1,
twoJedisWalkIntoACantina: 2,
episodeThree: 3,
mayTheFourth: 4,
};
- 数组
1、使用字面值创建数组
// bad
const items = new Array();
// good
const items = [];
2、向数组添加元素时使用Array#push替代直接赋值
const someStack = [];
// bad
someStack[somestack.length] = 'acacaca';
// good
someStack.push['acacaca'];
3、使用拓展运算符复制数组
// bad
const len = items.length;
const itemCopy = [];
let i;
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i];
}
// good
const itemsCopy = [...items];
- 解构
1、使用解构存取和使用多属性对象
因为解构能减少临时引用属性
// bad
function getFullName(user) {
firstName = user.firstName;
lastName = user.lastName;
return `${firstName} ${lastName}`;
}
// good
function getFullName(obj) {
const { firstName, lastName } = obj;
return `${firstName} ${lastName}`;
}
// best
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
2、对数组使用解构赋值
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
// good
const [first, second] = arr;
3、需要回传多个值时,使用对象解构,而不是数组解构
因为增加属性或改变排序不会改变调用时的位置
// bad
function ProcessInput(input) {
// then a miracle occurs
return [left, right, top, bottom];
}
// 调用时需要考虑回调数据的顺序
const [left, _, top] = ProcessInput(input);
// good
function ProcessInput(input) {
return { left, right, top, bottom};
}
// 调用时只选择需要的数据
const { left, right } = ProcessInput(input);
- 字符串
1、字符串使用单引号
// bad
const name = "Capt. Janeway";
// good
const name = 'Capt. Janeway';
2、字符串超过80个字节应使用字符串连接号换行
3、程序化生成字符串时,使用模板字符串代替字符串连接
因为模板字符串更为简洁,更具可读性
// bad
function Hi(name) {
return 'How are you, ' + name + '?';
}
// good
function Hi(name) { return `How are you ${name}?`;}
- 函数
1、使用函数声明代替函数表达式
因为函数声明是可命名的,所以他们在调用栈中更容易被识别。此外,函数声明会把整个函数提升(hoisted),而函数表达式只会把函数的引用变量名提升。这条规则使得箭头函数可以取代函数表达式
// bad
const foo = function() {
};
// good
function foo() {
}
2、函数表达式
// 立即调用的函数表达式 (IIFE)
(() => {
console.log('Hello world');
})();
3、永远不要在一个非函数代码块(if、while等)中声明一个函数,把那个函数赋给一个变量。浏览器允许你这么做,但它们的解析表现不一致
// bad
if (currentUser) {
function test() {
console.log('Nope.');
}
}
// good
let test;
if (currentUser) {
test = () => {
console.log('Yup.');
};
}
4、永远不要把参数命名为arguments,这将取代原来函数作用域内的arguments对象
5、不要使用arguments,可以选择rest语法...替代
因为使用...能明确你要传入的参数。另外rest参数是一个真正的数组,而arguments是一个类数组
// bad
function concatenateAll() {
const args = Array.prototype.slice.call(arguments);
return args.join('');
}
// good
function concatenateAll(...args) {
return args.join('');
}
6、直接给函数的参数指定默认值,不要使用一个变化的函数参数
// really bad
funciont handleThings(opts) {
// 不!我们不应该改变函数参数
// 更加糟糕:如果参数opts是false的话,它就会被设定为一个对象
// 但这样的写法会造成一些bug
// (译注:例如当opts被赋值为空字符串,opts仍然会被下一行代码设定为一个空对象)
opts = opts || {};
// ...
}
// still bad
function handleThings(opts) {
if (opts === void 0) {
opts = {};
}
// ...
}
// good
function handleThings(opts = {}) {
// ...
}
- 箭头函数
1、当你必须使用函数表达式(或传递一个匿名函数)时,使用箭头函数符号
因为箭头函数创造了一个新的this执行环境,通常情况下都能满足你的需求,而且这样的写法更简洁
// bad
[1, 2, 3].map(function (x) {
const y = x + 1;
return x * y;
});
// good
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
});
2、如果一个函数适合用一行写出并且只有一个参数,那就把花括号、圆括号和return都省略掉,如果不是,那就不要这么做
为什么?语法糖。在链式调用中可读性很高
为什么不?当你打算回传一个对象的时候
// good
[1, 2, 3].map(x => x * x);
// good
[1, 2, 3].reduce((total, n) => {
return total + n;
}, 0);
- 模块
1、不要使用通配符import
这样能确保你只有一个默认export
// bad
import * as AirbnbStyleGuide from './AirbnbStyleGuide';
// good
import AirbnbStyleGuide from './AirbnbStyleGuide';
- 属性
1、使用.来访问对象的属性
const luke = {
jedi: true,
age: 28,
};
// bad
const isJedi = luke['jedi'];
// good
const isJedi = luke.jedi;
2、当使用变量访问属性时使用中括号[]
const luke = {
jedi: true,
age: 28,
};
function getProp(prop) {
return luke[prop];
}
const isJedi = getProp('jedi');
- 比较运算符和等号
1、优先使用===和!==而不是==和!=
2、条件表达式例如if语句通过抽象方法ToBoolean强制计算它们的表达式并且总是遵循下面的规则
- 对象被计算为true
- Undefined被计算为false
- Null被计算为false
- 布尔值被计算为布尔的值
- 数字如果是+0、-0或NaN被计算为false,否则为true
- 字符串如果是空字符串''被计算为false,否则为true
3、使用简写
// bad
if (name !== '') {
// ...stuff...
}
// good
if (name) {
// ...stuff...
}
// bad
if (collections.length > 0) {
// ...stuff...
}
// good
if (collections.length) {
// ... stuff...
}
- 代码块
1、使用大括号包裹所有的多行代码块
// bad if (test) return false; // good if (test) return false; // good if (test) { return false; } // bad function() { return false; } // good function() { return false; }
2、如果通过if和else使用多行代码块,把else放在if代码块关闭的同一行
// bad if (test) { thing1(); thing2(); } else { thing3(); } // good if (test) { thing1(); thing2(); } else { thing3(); }
- 事件
当给事件附加数据时(无论是 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 });
- jQuery
1、使用$作为存储jQuery对象的变量名前缀
// bad const sidebar = $('.sidebar'); // good const $sidebar = $('.sidebar');
2、缓存jQuery查询
// bad function setSidebar() { $('.sidebar').hide(); // ...stuff... $('.sidebar').css({ 'background-color': 'pink' }); } // good function setSidebar() { const $sidebar = $('.sidebar'); $sidebar.hide(); // ...stuff... $sidebar.css({ 'background-color': 'pink' }); }
3、对 DOM 查询使用层叠 $('.sidebar ul')
或 父元素 > 子元素 $('.sidebar > ul')
4、对有作用域的jQuery对象查询使用find
// bad $('ul', '.sidebar').hide(); // bad $('.sidebar').find('ul').hide(); // good $('.sidebar ul').hide(); // good $('.sidebar > ul').hide(); // good $sidebar.find('ul').hide();