JavaScript

JavaScript数据类型和类型转换

Posted on 2018-12-30,8 min read

JavaScript的数据类型是弱数据类型,不像Java那样是强数据类型。使用var来定义变量,ES6中使用let和const。这篇文章简单的记录一下JS中的数据类型相关的内容。

数据类型转换

1. 数据类型

最新的ECMAScript标准定义了7种数据类型。

  • 原始数据类型(基本数据类型)
    • Boolean,Null,Undefined,Number,String,Symbol(ES6)
  • 复杂数据类型
    • 对象(Object)

2. 显式类型转换

显示类型转换也就是手动进行类型转换。

2.1 Number函数

  1. 原始类型的转换
// 1. 数值,
// 转换后还是原来的值
console.log(Number(123));  // 123

// 2. 字符串
// 如果可以被解析为数值,则转换为相应的数值;否则得到NaN;空字符串为0
console.log(Number('123'));  // 123
console.log(Number('123abc'));  // NaN
console.log(Number('abc123'));  // NaN
console.log(Number(''));  // 0

// 3. 布尔值
// false转为0;true转为1
console.log(Number(false));  // 0
console.log(Number(true));  // 1

// 4. undefined
// 转成NaN
console.log(Number(undefined));  // NaN

// 5. null
// 转成0
console.log(Number(null));  // 0
  1. 对象类型的转换

先调用对象自身的valueOf()方法,如果该方法返回原始类型的值(数值,字符串和布尔值),则直接对该值使用Number()方法。

如果valueOf()方法返回复合类型的值,再调用对象自身的toString()方法,如果toString()方法返回的是原始数据类型的值,则对该值使用Number()方法。

如果toString()返回的是复合类型的值,则报错。

console.log(Number({})); // NaN
console.log(Number({a:1})); // NaN
console.log(Number({a:'1'})); // NaN

console.log(Number([])); // 0
console.log(Number([1])); // 1
console.log(Number(['a','b'])); // NaN

上面的第二个输出语句的具体执行步骤是

// 首先调用对象自身的valueOf()方法
{a: 1}.valueOf(); // {a: 1}
// 返回的是复合类型的值,则调用toString()方法
{a: 1}.toString(); // "[object Object]"
// 返回的是一个原始数据类型,就使用Number()方法
Number("[object Object]"); // NaN

// 注:toString()对于对象而言返回的是 [object 构造函数名称]这样格式的字符串;对于数组和函数而言,它俩重写了对象了toString()方法。所以数组得到的是用逗号连接的元素序列字符串;函数得到其源代码字符串。

2.2 String函数

  1. 原始类型的转换
// 1. 数值
// 转为相应的字符串
console.log(String(123)); // "123"

// 2. 字符串
// 转换后还是原来的值
console.log(String('123')); // "123"

// 3. 布尔值
// true转换为"true"; false转换为"false"
console.log(String(true)); // "true"
console.log(String(false)); // "false"

// 4. undefined
// 转换为"undefined"
console.log(String(undefined)); // "undefined"

// 5. null
// 转换为"null"
console.log(String(null)); // "null"
  1. 对象类型的转换

先调用对象自身的toString()方法,如果返回的是原始类型的值,则再调用String()方法。

如果返回的是复合类型的值,就再调用valueOf()方法,如果返回的值是原始类型的值,则对该值使用String()方法。

如果valueOf()返回的是复合类型的值,就会报错。

console.log(String({})); // "[object Object]"
console.log(String({a:1})); // "[object Object]"
console.log(String({a:'1'})); // "[object Object]"

console.log(String([])); // ""
console.log(String([1])); // "1"
console.log(String(['a','b'])); // "a, b"

2.3 Boolean函数

  1. 原始类型的转换

只有空字符串("")、nullundefined+0-0NaN 转为布尔型是 false,其他的都是 true

  1. 对象类型转换

转换的布尔值均为true

3. 隐式类型转换

由于 JavaScript 是个弱类型语言,所以不是所有运算都要求类型一致,JavaScript 为了一些运算可以执行,使用了隐式类型转换。

隐式转换就是自动的,看不见的强制类型转换。

在进行四则运算,判断语句,Native调用时都会使用到隐式类型的转换。

3.1 加号(+)

加号(+)比较特殊,一个作用是正常的加法运算,另一个作用是字符串的拼接。

  • 数值 + 非字符串的原始类型数据
console.log(11 + true); // 12
console.log(11 + NaN); // NaN
console.log(11 + undefined); // NaN
console.log(11 + null); // 11

当数值与非字符串的值相加时,会把不是数值的那个值转换为数值类型,再进行相加。

任何数与NaN相加都是NaN

  • 数值 + 非字符串的复合数据类型
console.log(11 + {}); // "11[object Object]"
console.log({} + 11); // "[object Object]11"
console.log([] + 11); // "11"
console.log([1, 2] + 11); // "1,211"

复合数据类型先转换为字符串,再与数值进行相加。

  • 字符串 + 其他数据类型
console.log('11' + 23); // "1123"
console.log('11' + '23'); // "1123"
console.log('11' + true); // "11true"
console.log('11' + {a: 2}); // "11[object Object]"
console.log('11' + null); // "11null"
console.log('11' + undefined); // "11undefined"

先将不是字符串类型的值转换为字符串类型,再进行字符串与字符串的相加。就相当于字符串的拼接。

3.2 加号(+)除外的符号

除了加号(+),其他符号都是默认转换为数值型:

'3' - 1  // -> 2
'3' == 3 //转换后比较 3 == 3,而不是 '3' == '3'

3.3 复合类型数据之间的相加

console.log([]+[]); // ""
console.log({}+{}); // "[object Object][object Object]"
console.log([]+{}); // "[object Object]"
console.log({}+[]); // "[object Object]"

先将复合数据类型转换为字符串,在进行相加。

但是如果是直接在浏览器中直接输入{}+[]会得到一个数值0。这是因为在console.log{}是做是一个对象,而直接在浏览器中写的{}会被认为是一个代码块,代码块是空的执行完了就完了,后面的+[]会将[]转换为数值类型,结果就是0。

{}+[]; // 0
[]+{}; // "[object Object]"

4. “”与”=”的区别

“==”:进行比较,如果双方值类型不同,会进行隐式类型转换。再进行判断。

“===”:严格相等。如果双方的值类型不同,会判断直接不相等。

5. typeof和instanceof

5.1 typeof

typeof操作符返回一个字符串,表示未经计算的操作数的类型。

console.log(typeof(123)); // "number"
console.log(typeof('123')); // "string"
console.log(typeof(true)); // "boolean"
console.log(typeof([1,2])); // "object"
类型 结果
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
Symbol (ECMAScript 6 新增) "symbol"
宿主对象(由JS环境提供) Implementation-dependent
函数对象([[Call]] 在ECMA-262条款中实现了) "function"
任何其他对象 "object"

typeof对数组和对象无法区分,返回的都是object

5.2 instanceof

instanceof 用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置。

语法是:object instanceof constructor

instanceof比较自定义对象

function Foo() {}
function Bar() {}
Bar.prototype = new Foo();

new Bar() instanceof Bar; // true
new Bar() instanceof Foo; // true

// 如果仅仅设置 Bar.prototype 为函数 Foo 本身,而不是 Foo 构造函数的一个实例
Bar.prototype = Foo;
new Bar() instanceof Foo; // false

instanceof比较内置对象

new String('foo') instanceof String; // true
new String('foo') instanceof Object; // true

'foo' instanceof String; // false
'foo' instanceof Object; // false

6. 用来判断数据类型的方法

在JS中有多种判断数据类型的方法

  • typeof
  • instanceof
  • Object.prototype.toString.call()

推荐使用第三种。

typeof判断数组和对象的返回值都是object,并且null的返回值也是object。使用起来并不是很方便。

instanceof返回值是布尔值。必须提前知道这个值的类型才能判断。

下一篇: Hello Gridea