JS ES5数据类型及转换规则

数据类型

ES5中的数据类型包括number、string、boolean、null、undefined和object六种,object还可以细分为数组array和函数function。

1
2
3
4
5
6
7
8
9
10
11
const number = 1;
const string = 'hi';
const boolean = true;
const object = {
first:"white",
second:"yin"
};
const array = [1,2,3];
function f(){
console.log('hello');
}

数据类型反射

已知一个变量,要获取其数据类型,可以使用三种方法:typeof、instanceof和Object.prototype.toString()方法。

typeof

1
2
3
4
5
6
7
8
typeof number;//"number"
typeof string;//"string"
typeof boolean;//"boolean"
typeof object;//"object"
typeof array;//"object"
typeof f;//"function"
typeof undefined;//"undefined"
typeof null;//"object"

所有返回值都是字符串,能够判断number、string、boolean、object、function和undefined六种类型,对array和null操作返回为object。

instanceof

instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。即实例是否继承于一个类

1
2
3
4
var arr = [];
arr instanceof Array;//true
arr instanceof Object;//true
arr instanceof Function;//false

这种方法判断数组时,不能判断其他页面声明的数组。不过我觉得这个问题很少见。

Object.prototype.toString()

使用call或apply指定toString方法的this值,获取数据的类型:

1
2
3
4
5
6
7
8
Object.prototype.toString.apply(1)//"[object Number]"
Object.prototype.toString.apply("1")//"[object String]"
Object.prototype.toString.apply(null)//"[object Null]"
Object.prototype.toString.apply(undefined)//"[object Undefined]"
Object.prototype.toString.apply(true)//"[object Boolean]"
Object.prototype.toString.apply({})//"[object Object]"
Object.prototype.toString.apply([])//"[object Array]"
Object.prototype.toString.apply(function(){})//"[object Function]"

通过这种方法判断数据类型是比较准确的。除非你修改了toString方法。剁手!

其他方法

有些特殊类型会有特定的判断方法,比如NaN。可以使用isNaN()方法对传入的参数进行判断。但是如果参数是非数值,会转换为数值类型,这时会出现问题:isNaN('NIHAO')===true。所以推荐的方法是利用NaN的自不等性:NaN !== NaN

数组类型也有特殊的判断方法:isArray()。传入参数如果是数组则返回true。不过这个方法可能在老版本的浏览器中不支持,所以要先判断是否支持。

1
2
3
4
5
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}

数值类型中无穷也是一种特殊情况:-Infinity和Infinity。判断是否有穷,即不为无穷数,可以使用isFinite()方法。无穷返回false。

隐式转换

数据类型可以分为两大类,一类是原始数据类型:number、string、null、undefined和boolean,另一类是引用类型:object。

Object.valueOf()

valueOf方法是返回指定对象的原始值。

对象 返回值
Array 数组的元素被转换为字符串,由逗号分割。相当于toString()或join(‘’)方法。
Boolean 返回相应的布尔值
Date 从1970年1月1日开始的毫秒数
Function 函数本身
Number 相应的数字
Object 对象本身
String 字符串本身

toString()

toString方法返回对象的字符串形式:

对象 返回值
Array 逗号分割的字符串
Boolean ‘true’或’false’
Date 返回指定日期的字符串表示
Function 返回函数体的字符串
Number 返回数字的字符串形式
Object 返回[object Object]
String 字符串本身

Number()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 数值:转换后还是原来的值
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

//对象或多个值的数组:转成NaN
Number({x:1})//NaN
Number([1,2,3])//NaN

//只有一个值的数组:对这个值进行转换
Number([1])//1

Number方法比parseInt方法要严格,字符串中若是存在字母或特殊字符,一律返回NaN。

对象调用Number方法的处理逻辑如下:

  1. 首先调用对象的valueOf方法,如果返回值是原始类型则对该返回值调用Number方法;
  2. 如果返回值是对象,则调用该对象的toString()方法,如果返回原始类型的值则对该值调用Number方法;
  3. 如果返回对象,报错。

根据上面的规则,我们让一些不相等的值相等:

1
2
3
4
5
6
var a = {
valueOf:function(){
return 10;
}
}
a==10;//true

String()方法

String方法将数据转为字符串:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//数值:转为相应字符串
String(123) // "123"

//字符串:原值
String('abc') // "abc"

//布尔值:相应的字符串
String(true) // "true"

//undefined:"undefined"
String(undefined) // "undefined"

//null:"null"
String(null) // "null"

//对象:
String({x:1}) //"[object Object]"

//数组
String([1,2,3]) //"1,2,3"

String()的处理逻辑与Number()相反:

  1. 调用对象toString()方法,如果返回原始类型值对其调用String();
  2. 如果返回对象,调用其valueOf()方法,如果返回原始类型,对返回值调用String();
  3. 如果返回对象,报错。

Boolean()

Boolean()方法可以将数据转为布尔值。我们需要记忆的是下面几个转换为false的falsy值:

1
2
3
4
5
Boolean(undefined) //false
Boolean(null) //false
Boolean(0) //false
Boolean("") //false
Boolean(NaN) //false

其他值转换成true。空对象或数组也都转换为true。

自动转换

如果运算符的运算子的数据类型与预期不符,就会出现自动类型转换的情况。比如+、==等等,比较简单,不举例了。