JavaScript语言教程
Javascript语法指南大全
目录
类型
-
初始类型: 当你访问初始类型,可以直接使用其值。
- string字符串类型
- number类型
- boolean类型
- null类型
- undefined类型
var foo = 1,
bar = foo;
bar = 9;
console.log(foo, bar); // => 1, 9
- 复杂: 当你访问复杂类型,你使用的是其值的引用。
- object对象
- array数组
- function函数
var foo = [1, 2],
bar = foo;
bar[0] = 9;
console.log(foo[0], bar[0]); // => 9, 9
对象
-
使用literal字面语法创建对象.
// bad
var item = new Object();
// good
var item = {};
-
不用使用 保护词语reserved words 作为代码,在IE8中不会工作.
// 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 = []; - 如果你不知道数组的长度,使用Array#push.
var someStack = [];
// bad
someStack[someStack.length] = 'abracadabra';
// good
someStack.push('abracadabra'); - 拷贝数组时使用Array#slice
var len = items.length,
itemsCopy = [],
i; // bad for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } // good
itemsCopy = items.slice(); - 转换类似数组的对象转换为一个数组, 使用Array#slice.
function trigger() {
var args = Array.prototype.slice.call(arguments); ...
}
字符串Strings
-
字符串用单引号"
// bad
var name = "Bob Parr"; //双引号
// good
var name = 'Bob Parr'; //单引号
// bad
var fullName = "Bob " + this.lastName;
// good
var fullName = 'Bob ' + this.lastName; - 超过80字符的字符串应该多行编写,使用字符串连接。
- 如果过度使用,长字符串连接可能会影响性能
// bad
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.';
// bad 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.';
// good 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.'; - 当通过编程建立一个字符串,使用数组Array#join加入而不是字符串连接。
var items,
messages,
length,
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>';
}
函数Function
-
函数表达式:
// 匿名函数 var anonymous = function() { return true; }; // 有名函数 var named = function named() { return true; }; //立即调用的函数 (function() {
console.log('Welcome to the Internet. Please follow me.');
})(); - 不要在非函数块中定义一个函数,应该分配函数到一个变量。虽然浏览器可能允许你这么做,但是不同浏览器有不同的解释执行方式,这是导致运行不稳定原因。
- 注意: ECMA-262 定义一个代码块作为statement集合. 但是一个函数声明不是一个statement. Read ECMA-262's note on this issue.
// bad if (currentUser) { function test() { console.log('Nope.'); } } // good var test; if (currentUser) { test = function test() { console.log('Yup.'); }; }
- 不要给一个参数取名为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(); var goSportsTeam = true; var dragonball = 'z'; // good var items = getItems(), goSportsTeam = true, dragonball = 'z';
- 最后声明未赋值的变量,如果你需要依赖之前已经分配的变量分配变量时这会有帮助。
// bad var i, len, dragonball, items = getItems(), goSportsTeam = true; // bad var i, items = getItems(), dragonball, goSportsTeam = true, len; // good var items = getItems(), goSportsTeam = true, dragonball, length, 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
-
变量声明能够升级到作用域顶部,而他们的分配值则不可以.
// 下面不会正常工作(假设没有notDefined这个全局变量)
function example() {
console.log(notDefined); // => 抛出错误ReferenceError
}
// 当你引用一个变量后再创建变量的声明会正常工作
//因为变量提升的原因。但是分配值`true`不会提升
function example() {
console.log(declaredButNotAssigned); // => 未定义
var declaredButNotAssigned = true;
}
// 解释器会提升变量到当前作用域顶部,这个案例可以重写为:
function example() {
var declaredButNotAssigned;
console.log(declaredButNotAssigned); // => undefined
declaredButNotAssigned = true;
}
- 匿名函数表达式会提升他们的变量名,但函数赋值不行
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');
};
}
// the same is true when the function name
// is the same as the variable name.
function example() {
console.log(named); // => undefined
named(); // => TypeError named is not a function
var named = function named() {
console.log('named');
}
}
- 函数声明会提升它们的名称和函数体
function example() {
superPower(); // => Flying
function superPower() {
console.log('Flying');
}
}
- 多细节见 JavaScript Scoping & Hoisting by Ben Cherry
条件表达式与等式
- 使用 === 和 !==,不用 == 和 !=.
- 条件表达式使用ToBoolean方法被强迫转换,遵循下面规则:
- Objects 是 true
- Undefined 等同 false
- Null 是 false
- Booleans 是 boolean的值
- Numbers 是在 +0, -0, or NaN为false , 其他为 true
- Strings 如果有空字符串''是 false ,否则是true
if ([0]) {
// true
// 一个数组array是一个对象,对象将等同于true
}
- 使用快捷方式shortcuts.
// bad
if (name !== '') {
// ...stuff...
}
// good
if (name) {
// ...stuff...
}
// bad
if (collection.length > 0) {
// ...stuff...
}
// good
if (collection.length) {
// ...stuff...
}
- 更多细节见 Truth Equality and JavaScript by Angus Croll
块Blocks
-
多行代码块使用花括号.
// bad
if (test)
return false;
// good
if (test) return false;
// good
if (test) {
return false;
}
// bad
function() { return false; }
// good
function() {
return false;
}
注释
-
使用 /** ... */ 多行注解 包括描述,为所有指定类型和值参数和返回值。
// bad
// make() returns a new element
// based on the passed in tag name
//
// @param <String> tag
// @return <Element> element
function make(tag) {
// ...stuff...
return element;
}
// good
/**
* make() returns a new element
* based on the passed in tag name
*
* @param <String> tag
* @return <Element> element
*/
function make(tag) {
// ...stuff...
return element;
}
- 使用// 单行注释,
// bad
var active = true; // is current tab
// good
// is current tab
var active = true;
// bad
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
var type = this._type || 'no type';
return type;
}
// good
function getType() {
console.log('fetching type...');
// set the default type to 'no type'
var type = this._type || 'no type';
return type;
}
- 用 // FIXME: 标注问题
function Calculator() {
// FIXME: shouldn't use a global here
total = 0;
return this;
}
- 使用// TODO: 标注问题的解决
function Calculator() {
// TODO: total should be configurable by an options param
this.total = 0;
return this;
}