JavaScript中总共有6种数据类型。可分为两大类:简单数据类型和复杂数据类型。
说明一下:上面这句话现在来说应该是不对的,因为ES6中新增了数据类型。不过我们暂时不涉及ES6。
简单数据类型即基本数据类型,共有5种:Undefined、Null、Boolean、Number、String,其值分别对应undefined、null、布尔值true和false、数值、字符串值。
复杂数据类型只有一种,就是Object——对象。JS中的对象就是一组无序键值对外面套一个大括号{}所构成。Object非常常用、非常强大、非常有意思,而且对于JS这门语言结构来说,Object意义不一般。这些,之后的文章再来讨论吧。
ECMAScript不支持任何创建自定义类型的机制,而所有值最终都将是上述6种数据类型之一。
上面这句话引用自《JavaScript高级程序设计(第3版)》(之后简称J3),其实不用多解释,这句话说的很明白了。这就是说,你“定义”的所有变量,它的类型都是唯一确定的,必定是上述6种之一。
这里的“定义”两个字,我加了引号,是想表示这个词广义上的意思。在一般的编程语言中,当你想“定义”一个变量时,不外乎3种情况:声明,定义,初始化。声明就如字面意思一样,仅仅是宣称一个命名;定义就是给这个命名分配内存空间;初始化则是给这个内存空间赋值。显然,他们3个是循序渐进的。在JS中,我们所说的初始化其实做的事是分配内存并赋值,也就是定义并初始化。所以在JS中,我们一般只说声明和初始化。看如下代码:
var value1; //声明变量
value1 = 'Hello'; //(定义并)初始化
var value2 = 'Hello'; //声明并初始化
再摘录博客园的一句话,对于声明、定义与初始化大家应该就能完全理解了:
因为javascript为动态语言,其变量并没有固定的类型,其存储空间大小会随初始化与赋值而变化,所以其变量的“定义”就不像传统的静态语言一样了,其定义显得无关紧要。
http://www.cnblogs.com/silentjesse/p/4024536.html
接下来,让我们来具体看一看JavaScript的6种数据类型。
不过首先,必须先了解一个操作符—typeof
。顾名思义,这个操作符的作用就是返回某个变量的数据类型。对某个值使用typeof
操作符始终会返回以下6个字符串之一:'undefined'
、'boolean'
、'number'
、'string'
、'object'
、'function'
。你肯定发现了一个问题,就是这6个字符串为什么不和6种数据类型完全对应?没有'null'吗?'function'
又是哪儿来的?请看下面的测试代码:
console.log(typeof null) //'object'
var f = function(){};
console.log(typeof f); //'function'
注意到,对Null
类型的唯一值null
使用typeof
操作符返回的不是什么'null',而是'object'
,这是为什么呢?这是因为null
这个值比较特殊,它是基本数据类型Null
的唯一值,但同时,它又被认为是一个空的对象(Object
)引用。
有些时候,typeof 操作符会返回一些令人迷惑但技术上却正确的值。比如,调用typeof null会返回"object",因为特殊值null 被认为是一个空的对象引用。——《J3》
对于typeof
可以返回'function'
,这么理解吧:
从技术角度讲,函数在ECMAScript 中是对象,不是一种数据类型。然而,函数也确实有一些特殊的属性,因此通过typeof 操作符来区分函数和其他对象是有必要的。——《J3》
在JS中,Function
和Object
的关系很微妙也很复杂,需要对原型构造、原型链等一些知识有所理解之后才能进一步理解这两者的关系。不过这并不影响我们现在的理解,站在数据类型的角度,我们可以明确地认为Function
就是一类特殊的Object
。至于对一个Function
使用typeof
操作符的返回结果是'function'
而不是'object'
,原因就像书上说的,只是因为我们有必要知道它是一个函数而不是一般的对象。
介绍完typeof
操作符这个实用的工具,下面就真的具体来看看JS的6种数据类型吧。
Undefined 类型
- 只有一个唯一值,即
undefined
。 - 所有只进行了声明而未初始化的变量,其值都是
undefined
。比如:
var a;
console.log(a); //undefined(注意,这可不是字符串)
需要明白的是,undefined
是一个明确的、合法的值,而不是一个错误。真正会导致错误的是如下的代码:
console.log(b); //Uncaught ReferenceError: b is not defined
这行代码会报一个空引用异常的错误,因为变量b没有声明。这很好理解。
- 还有一点需要了解,对于上边两段示例代码中的变量 a 和 b,执行
typeof
操作都会返回'undefined'
:
var a;
console.log(typeof a); //'undefined'
console.log(typeof b); //'undefined'
看起来,你可能会觉得对 b 执行typeof
应该报错才对,但因为typeof
必然会返回6个字符串之一,所以并不会报错。而且,无论是 a 还是 b,都无法执行真正的操作,那么就让 b 和 a 一样返回'undefined'
好了。看一下书上的解释:
结果表明,对未初始化和未声明的变量执行typeof 操作符都返回了undefined 值;这个结果有其逻辑上的合理性。因为虽然这两种变量从技术角度看有本质区别,但实际上无论对哪种变量也不可能执行真正的操作。——《J3》
由此可知,当你使用typeof
操作符检测变量的数据类型时,如果返回的是'undefined'
,那么这个变量可能是未初始化,也可能是未声明。因此,从规范性上来说,为了避免这种模糊,我们在定义变量时最好直接进行初始化。这样的话,如果还返回'undefined'
,那么我们立即就能知道是因为这个变量压根就没声明了。
Null 类型
- 只有一个唯一值,即
null
。 -
null
表示一个空对象(Object
)引用,因此typeof null
会返回'object'
。 - 实际上,
undefined
派生自null
,因此undefined == null
返回true
,但是undefined === null
会返回false
,因为这两个值的数据类型不一样。这里补充一下:==
是相等操作符,===
是全等操作符,前者会对操作数自动进行转型,而后者不会,后者只有在两个操作数未经转换就相等的情况下才返回true
。 - 还有一点,如果某个变量用来在以后保存对象,那么最好将其初始化为
null
,以方便区分和判断。
Boolean 类型
- 布尔类型,有2个值:
true
和false
。 - 其他所有数据类型都有与
true
和false
对应的值,通过转型函数Boolean()
可以得到某个值所对应的布尔值。如:
var s = 'Hello';
console.log(Boolean(s)); //true
转换规则如下表:
在流程控制语句中,比如在
if
语句的小括号内,会自动对操作数调用转型函数Boolean()
再求最终的布尔值。如下:
var s = 'Hello';
if(s){
//do something //后台自动对s调用转型函数`Boolean()`,因为s不是空串,会返回true
}
Number 类型
数值类型。了解几个知识点即可。
- 保存浮点数所需的内存空间是整数值的2倍;
- 永远不要测试特定的浮点数值,如:
var a = 0.1;
var b = 0.2;
console.log(a + b); //0.30000000000000004 有误差,并不会是0.3
-
NaN
是一个特殊的Number
值,它的存在是为了避免程序直接报错,比如0/0
的结果就是NaN
;NaN
的任何操作都会返回NaN
;NaN
与任何值都不相等,包括它本身:NaN === NaN
会返回false
; - 另外,还有
parseInt()
和parseFloat()
等常用转型函数的用法自行Google即可。
String 类型
字符串类型。在这里了解几个点即可,之后在引用类型等处会做详细介绍。
单引号
''
和双引号""
都可以使用且没有任何差别。ECMAScript 中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量。——《J3》
将某个值转换为字符串,可以使用以下3种方法:
toString()
方法、转型函数String()
、加空串+ ''
。
Object 类型
对象类型。Object
是所有对象的基础,其所具有的属性和方法其他对象也必然拥有。这里只列几个Object
的属性和方法:
-
constructor
:保存着用于创建当前对象的构造函数; -
hasOwnProperty('属性名')
:用于检查给定的属性在当前对象实例中是否存在(不查找原型链); -
isPrototypeOf(某一Object类型)
:用于检查对象实例是否是传入对象的原型; -
propertyIsEnumerable('属性名')
:用于检查传入的属性是否可以枚举; -
toString()
:返回该对象的字符串表示; -
toLocalString()
:同上,与所在地区有关 -
valueOf()
:返回对象最有意义的那个值,返回的可能是字符串、数值或者布尔值。