一些有用的 javascript 知识和代码规范
类型 Types
基础类型:When you access a primitive type you work directly on its value
- string
- number
- boolean
- null
- undefined
var foo = 1; var bar = foo; bar = 9; console.log(foo, bar); // => 1, 9
复合类型:When you access a complex type you work on a reference to its value
- object
- array
- function
var foo = [1, 2]; var bar = foo; bar[0] = 9; console.log(foo[0], bar[0]); // => 9, 9
对象 Objects
- 创建对象
// bad var item = new Object(); // good var item = {};
- 不要使用保留字作为 key
// bad var superman = { default: { clark: 'kent' }, private: true }; // good var superman = { defaults: { clark: 'kent' }, hidden: true };
- 使用可读近义词代替保留字
// bad var superman = { class: 'alien' }; // bad var superman = { klass: 'alien' }; // good var superman = { type: 'alien' };
数组 Arrays
创建数组
// bad var items = new Array(); // good var items = [];
不知道数组长度时,使用 push 函数添加元素
var someStack = []; // bad someStack[someStack.length] = 'abracadabra'; // good someStack.push('abracadabra');
复制数组时使用 slice 函数
var len = items.length; var itemsCopy = []; var i; // bad for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good itemsCopy = items.slice();
将一个数组类对象转化为数组,使用 slice 函数
function list() { return Array.prototype.slice.call(arguments, 0); } var list1 = list(1, 2, 3); // => [1, 2, 3]
字符串 Strings
使用单引号
// bad var name = "Bob Parr"; // good var name = 'Bob Parr';
字符串长度超过 80,应写成多行并使用 “ + ” 连接
动态构建一个字符串时,使用 join 函数而不是 “ + ”
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++) { items[i] = messages[i].message; } return '<ul><li>' + items.join('</li><li>') + '</li></ul>'; }
函数 Functions
函数表达式
// anonymous function expression var anonymous = function() { return true; }; // named function expression var named = function named() { return true; }; // immediately-invoked function expression (IIFE) (function() { console.log('Welcome to the Internet. Please follow me.'); })();
Never declare a function in a non-function block (if, while, etc). Assign the function to a variable instead.
// bad if (currentUser) { function test() { console.log('Nope.'); } } // good var test; if (currentUser) { test = function test() { console.log('Yup.'); }; }
不要把任何参数命名为 arguments,这会替代每个函数原有的 arguments 对象
// bad function nope(name, options, arguments) { // ...stuff... } // good function yup(name, options, args) { // ...stuff... }
属性 Properties
使用 “ . ” 符号来获取属性
var luke = { jedi: true, age: 28 }; // bad var isJedi = luke['jedi']; // good var isJedi = luke.jedi;
当使用变量获取属性时,使用 “ [ ] “
var luke = { jedi: true, age: 28 }; function getProp(prop) { return luke[prop]; } var isJedi = getProp('jedi');
变量 Variables
总是使用 var 来定义变量,否则会产生占用内存的全局变量
// bad superPower = new SuperPower(); // good var superPower = new SuperPower();
每个变量使用一个 var 来定义
// bad var items = getItems(), goSportsTeam = true, dragonball = 'z'; // good var items = getItems(); var goSportsTeam = true; var dragonball = 'z';
未初始化的变量放在最后
// bad var i; var items = getItems(); var dragonball; var goSportsTeam = true; var len; // good var items = getItems(); var goSportsTeam = true; var dragonball; var length; var i;
在变量范围内的顶部对其赋值,注意第二个例子
// bad function() { test(); console.log('doing stuff..'); //..other stuff.. var name = getName(); if (name === 'test') { return false; } return name; } // good function() { var name = getName(); test(); console.log('doing stuff..'); //..other stuff.. if (name === 'test') { return false; } return name; } // bad function() { var name = getName(); if (!arguments.length) { return false; } return true; } // good function() { if (!arguments.length) { return false; } var name = getName(); return true; }
提前 Hoisting
变量声明在作用域内被提前,而赋值却留在原地
function example() { console.log(notDefined); // => throws a ReferenceError } function example() { // Outputs: undefined console.log(declaredLater); declaredLater = "Now it's defined!"; //声明被提前到作用域开始处,赋值操作还在原地 // Outputs: "Now it's defined!" console.log(declaredLater); }
匿名函数变量被提前,函数定义却未被提前
function example() { console.log(anonymous); // => undefined anonymous(); // => TypeError anonymous is not a function var anonymous = function() { console.log('anonymous function expression'); }; }
命名函数提前了变量名,但函数名和函数主体未被提前
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() { superPower(); // => Flying function superPower() { console.log('Flying'); } }
条件表达式和相等判断 Conditional Expressions & Equality
使用 “ === ” 和 “ !== ” 替代 “ == ” 和 “ != ”
表达式的值
- Objects:true
- Undefined:false
- Null:false
- Booleans:此 Boolean 的值
- Numbers:0,-0,NaN 为 false,其他为 true
- Strings:’ ‘ 为 false,其他为 true
使用简单表达式
// bad if (name !== '') { // ...stuff... } // good if (name) { // ...stuff... } // bad if (collection.length > 0) { // ...stuff... } // good if (collection.length) { // ...stuff... }
类型转换 Type Casting & Coercion
值转字符串
// => this.reviewScore = 9; // bad var totalScore = this.reviewScore + ''; // good var totalScore = '' + this.reviewScore; // bad var totalScore = '' + this.reviewScore + ' total score'; // good var totalScore = this.reviewScore + ' total score';
字符串转数字,使用 parseInt 函数,并且总是带上基数代表进制
var inputValue = '4'; // bad var val = new Number(inputValue); // bad var val = +inputValue; // bad var val = inputValue >> 0; // bad var val = parseInt(inputValue); // good var val = Number(inputValue); // good var val = parseInt(inputValue, 10);
布尔值
var age = 0; // bad var hasAge = new Boolean(age); // good var hasAge = Boolean(age); // good var hasAge = !!age;
事件 Events
- 捕捉事件后,传递一个哈希而非单纯的数据
// 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 });