数据类型的转换
简介
JavaScript 是一种动态类型语言,变量没有类型限制,可以随时赋予任意值。
变量的类型没法在编译阶段就知道,必须等到运行时才能知道。
虽然变量的数据类型是不确定的,但是各种运算符对数据类型是有要求的。如果运算
符发现,运算子的类型与预期不符,就会自动转换类型。比如,减法运算符预期左右
两侧的运算子应该是数值,如果不是,就会自动将它们转为数值。
'4' - '3' // 1
强制转换
强制转换主要指使用Number()、String()和Boolean()三个函数,手动将
各种类型的值,分别转换成数字、字符串或者布尔值。
1.Number()
(1)原始类型值
/ 数值:转换后还是原来的值
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
(2)对象
简单的规则是,Number方法的参数是对象时,将返回NaN,
除非是包含单个数值的数组。
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5
2.String()
String函数可以将任意类型的值转化成字符串。
String方法的参数如果是对象,返回一个类型字符串;如果是数组,
返回该数组的字符串形式。
String({a: 1}) // "[object Object]"
String([1, 2, 3]) // "1,2,3"
String方法背后的转换规则,与Number方法基本相同,只是互换了
valueOf方法和toString方法的执行顺序。
3.Boolean()
Boolean()函数可以将任意类型的值转为布尔值。
它的转换规则相对简单:除了以下五个值的转换结果为false,其他的值全部为true。
undefined
null
0(包含-0和+0)
NaN
''(空字符串)
错误处理机制
Error 实例对象
JavaScript 解析或运行时,一旦发生错误,引擎就会抛出一个错误对象。
JavaScript 原生提供Error构造函数,所有抛出的错误都是这个构造函数的实例。
var err = new Error('出错了');
err.message // "出错了"
上面代码中,我们调用Error构造函数,生成一个实例对象err。Error构造函数接受
一个参数,表示错误提示,可以从实例的message属性读到这个参数。抛出Error实例
对象以后,整个程序就中断在发生错误的地方,不再往下执行。
JavaScript 语言标准只提到,Error实例对象必须有message属性,表示出错时的
提示信息,没有提到其他属性。大多数 JavaScript 引擎,对Error实例还提供
name和stack属性,分别表示错误的名称和错误的堆栈,但它们是非标准的,不是每种
实现都有。
message:错误提示信息
name:错误名称(非标准属性)
stack:错误的堆栈(非标准属性)
原生错误类型
Error实例对象是最一般的错误类型,在它的基础上,JavaScript 还定义了
其他6种错误对象。也就是说,存在Error的6个派生对象。
1.SyntaxError 对象
SyntaxError对象是解析代码时发生的语法错误。
// 变量名错误
var 1a;
// Uncaught SyntaxError: Invalid or unexpected token
2.ReferenceError 对象
ReferenceError对象是引用一个不存在的变量时发生的错误。
// 使用一个不存在的变量
unknownVariable
// Uncaught ReferenceError: unknownVariable is not defined
3.RangeError 对象
RangeError对象是一个值超出有效范围时发生的错误。主要有几种情况,一是
数组长度为负数,二是Number对象的方法参数超出范围,以及函数堆栈超过最大值。
// 数组长度不得为负数
new Array(-1)
// Uncaught RangeError: Invalid array length
4.TypeError 对象
TypeError对象是变量或参数不是预期类型时发生的错误。比如,对字符串、布尔值、
数值等原始类型的值使用new命令,就会抛出这种错误,因为new命令的参数应该是一
个构造函数。
new 123
// Uncaught TypeError: number is not a func
var obj = {};
obj.unknownMethod()
// Uncaught TypeError: obj.unknownMethod is not a function
5.URIError 对象
URIError对象是 URI 相关函数的参数不正确时抛出的错误,主要涉及encodeURI()
decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()
和unescape()这六个函数。
decodeURI('%2')
// URIError: URI malformed
6.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对象。然后,就可以生成
这种自定义类型的错误了。
new UserError('这是自定义的错误!');
throw 语句
throw语句的作用是手动中断程序执行,抛出一个错误。
if (x <= 0) {
throw new Error('x 必须为正数');
}
throw可以抛出任何类型的值。也就是说,它的参数可以是任何值。
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代码块之中,便于
进一步对错误进行处理。
try {
f();
} catch(e) {
// 处理错误
}
上面代码中,如果函数f执行报错,就会进行catch代码块,接着对错误进行处理。
finally 代码块
try...catch结构允许在最后添加一个finally代码块,表示不管是否出现错误,
都必需在最后运行的语句。
function cleansUp() {
try {
throw new Error('出错了……');
console.log('此行不会执行');
} finally {
console.log('完成清理工作');
}
}
cleansUp()
// 完成清理工作
// Uncaught Error: 出错了……
// at cleansUp (<anonymous>:3:11)
// at <anonymous>:10:1
上面代码中,由于没有catch语句块,一旦发生错误,代码就会中断执行。
中断执行之前,会先执行finally代码块,然后再向用户提示报错信息。
return语句的执行是排在finally代码之前,只是等finally代码执行完毕后
才返回。
var count = 0;
function countUp() {
try {
return count;
} finally {
count++;
}
}
countUp()
// 0
count
// 1