数据类型的转换

强制转换主要指使用Number()、String()和Boolean()三个函数,手动将各种类型的值,分别转换成数字、字符串或者布尔值。

使用Number函数,可以将任意类型的值转化成数值。下面分成两种情况讨论,一种是参数是原始类型的值,另一种是参数是对象。

// 数值:转换后还是原来的值
Number(324) // 324

// 字符串:如果可以被解析为数值,则转换为相应的数值
Number('324') // 324

// 字符串:如果不可以被解析为数值,返回 NaN
Number('324abc') // NaN

// 空字符串转为0
Number('') // 0

// 布尔值:true 转成 1,false 转成 0
Number(true) // 1
Number(false) // 0

// undefined:转成 NaN
Number(undefined) // NaN

// null:转成0
Number(null) // 0

Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5

String函数可以将任意类型的值转化成字符串,转换规则如下。

(1)原始类型值

数值:转为相应的字符串。
字符串:转换后还是原来的值。
布尔值:true转为字符串”true”,false转为字符串”false”。
undefined:转为字符串”undefined”。
null:转为字符串”null”。

(2)对象

String方法的参数如果是对象,返回一个类型字符串;如果是数组,返回该数组的字符串形式。

Boolean()
Boolean()函数可以将任意类型的值转为布尔值。

它的转换规则相对简单:除了以下五个值的转换结果为false,其他的值全部为true。

undefined
null
0(包含-0和+0)
NaN
‘’(空字符串)

错误处理机制

JvaScript 解析或运行时,一旦发生错误,引擎就会抛出一个错误对象。JavaScript 原生提供Error构造函数,所有抛出的错误都是这个构造函数的实例。

Error实例对象是最一般的错误类型,在它的基础上,JavaScript 还定义了其他6种错误对象。也就是说,存在Error的6个派生对象。

SyntaxError 对象

SyntaxError对象是解析代码时发生的语法错误。

ReferenceError 对象

ReferenceError对象是引用一个不存在的变量时发生的错误。

RangeError 对象

RangeError对象是一个值超出有效范围时发生的错误。主要有几种情况,一是数组长度为负数,二是Number对象的方法参数超出范围,以及函数堆栈超过最大值。

TypeError 对象

TypeError对象是变量或参数不是预期类型时发生的错误。比如,对字符串、布尔值、数值等原始类型的值使用new命令,就会抛出这种错误,因为new命令的参数应该是一个构造函数。

URIError

URIError对象是 URI 相关函数的参数不正确时抛出的错误,主要涉及encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()这六个函数。

EvalError 对象

eval函数没有被正确执行时,会抛出EvalError错误。该错误类型已经不再使用了,只是为了保证与以前代码兼容,才继续保留。

以上这6种派生错误,连同原始的Error对象,都是构造函数。开发者可以使用它们,手动生成错误对象的实例。这些构造函数都接受一个参数,代表错误提示信息(message)。

var err1 = new Error('出错了!');
var err2 = new RangeError('出错了,变量超出有效范围!');
var err3 = new TypeError('出错了,变量类型无效!');

err1.message // "出错了!"
err2.message // "出错了,变量超出有效范围!"
err3.message // "出错了,变量类型无效!"

自定义错误

除了 JavaScript 原生提供的七种错误对象,还可以定义自己的错误对象。


function UserError(message) {
this.message = message || '默认信息';
this.name = 'UserError';
}

UserError.prototype = new Error();
UserError.prototype.constructor = UserError;

上面代码自定义一个错误对象UserError,让它继承Error对象。然后,就可以生成这种自定义类型的错误了。

throw 语句

throw语句的作用是手动中断程序执行,抛出一个错误。

if (x <= 0) {
throw new Error('x 必须为正数');
}
// Uncaught ReferenceError: x is not defined

上面代码中,如果变量x小于等于0,就手动抛出一个错误,告诉用户x的值不正确,整个程序就会在这里中断执行。可以看到,throw抛出的错误就是它的参数,这里是一个Error实例。

throw也可以抛出自定义错误。

// 抛出一个字符串
throw 'Error!';
// Uncaught Error!

// 抛出一个数值
throw 42;
// Uncaught 42

// 抛出一个布尔值
throw true;
// Uncaught true

// 抛出一个对象
throw {
toString: function () {
return 'Error!';
}
};
// Uncaught {toString: ƒ}

try…catch 结构

一旦发生错误,程序就中止执行了。JavaScript 提供了try…catch结构,允许对错误进行处理,选择是否往下执行。

try {
throw new Error('出错了!');
} catch (e) {
console.log(e.name + ": " + e.message);
console.log(e.stack);
}
// Error: 出错了!
// at <anonymous>:3:9
// ...

上面代码中,try代码块抛出错误(上例用的是throw语句),JavaScript 引擎就立即把代码的执行,转到catch代码块,或者说错误被catch代码块捕获了。catch接受一个参数,表示try代码块抛出的值。

如果你不确定某些代码是否会报错,就可以把它们放在try…catch代码块之中,便于进一步对错误进行处理。

catch代码块捕获错误之后,程序不会中断,会按照正常流程继续执行下去。

finally 代码块

try…catch结构允许在最后添加一个finally代码块,表示不管是否出现错误,都必需在最后运行的语句。

编程风格

缩进

空格,两格

区块

因此,建议总是使用大括号表示区块。起首的大括号跟在关键字的后面。

圆括号

  • 表示函数调用时,函数名与左括号之间没有空格。
  • 表示函数定义时,函数名与左括号之间没有空格。
  • 其他情况时,前面位置的语法元素与左括号之间,都有一个空格。

行尾的分号

建议不要省略这个分号。

全局变量

建议避免使用全局变量。如果不得不使用,可以考虑用大写字母表示变量名,这样更容易看出这是全局变量,比如UPPER_CASE

变量声明

为了避免可能出现的问题,最好把变量声明都放在代码块的头部。

with 语句

不要使用with语句

相等和严格相等

建议不要使用相等运算符(==),只使用严格相等运算符(===)

语句的合并

建议不要将不同目的的语句,合并成一行

自增和自减运算符

建议自增(++)和自减(–)运算符尽量使用+=和-=代替

switch…case 结构

建议switch…case结构可以用对象结构代替

function doAction(action) {
switch (action) {
case 'hack':
return 'hack';
case 'slash':
return 'slash';
case 'run':
return 'run';
default:
throw new Error('Invalid action.');
}
}

// 换成

function doAction(action) {
var actions = {
'hack': function () {
return 'hack';
},
'slash': function () {
return 'slash';
},
'run': function () {
return 'run';
}
};

if (typeof actions[action] !== 'function') {
throw new Error('Invalid action.');
}

return actions[action]();
}