一、javascript数据类型
JavaScript中的值分为2大类7种数据类型:
基本类型和引用类型。
一)基本类型(也叫原始类型)
-
按值访问,可以操作保存在变量中实际的值。包括6种:
-
1、数字类型:Number
-
包含了所有的数值类型,不像高级语言那么细分成int,double,deciable,他的取值范围是:1.7976931348623157E+308到-1.7976931348623157E+308之间,Number类型有一个特殊的值NaN,它表示非数值的数值,NaN不等于NaN;
-
2、布尔类型:Boolean(true和false)
boolean类型的值有两个true和false,Boolean类型和Number类型相结合时,true转化为1,false转化为0;
-
3、字符串类型:String 用来表示一个字符串
-
4、Undefined类型
-
Undefined类型只有一个值Undefined,表示一个变量定义了但未赋值
-
5、Null类型
-
Null类型只有一个专用值 null,即它的字面量。值 undefined 实际上是从值 null 派生来的,因此 ECMAScript 把它们定义为相等的。
alert(null == undefined); //输出 "true"
-
尽管这两个值相等,但它们的含义不同。undefined 是声明了变量但未对其初始化时赋予该变量的值,null 则用于表示尚未存在的对象引用。如果函数或方法要返回的是对象,那么找不到该对象时,返回的通常是 null。
-
6、Symbol(es6新定义的)
-
ES5的对象属性名都是字符串,这容易造成属性名的冲突。ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。
二)引用类型
引用类型有很多名字,
引用类型的值(对象)是引用对象的一个实例,引用类型是一种数据结构,用于将数据与功能组织在一起。ECMAScript有一些内置引用类型可以用来创建特定的对象。
引用类型有时也被称为对象定义,因为它们描述的是一类对象所拥有的属性和方法。
其中包括了三种基本包装类型:Number、String和Boolean,它们是特殊的引用类型,既与其他的引用类型相似,同时又具有与各自的原始类型相应的特殊行为。
1、Object类型
Object对象,是所有JavaScript对象的超类(基类),Object.prototype(Object的原型)定义了Js对象的基本方法和属性。
2、Array类型
- 数组是数据的有序列表。
- JS中的数组每一项都能保存任何类型的数据。
- JS数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增的数据。
3、Date类型
JS中的Date类型使用UTC(Coordinated Universal Time,国际协调时间)自1970年1月1日0时开始经过的毫秒数来保存时间。
基本包装类型
为了操作基本类型值,ECDMAScript提供了3个特殊的引用类型——基本包装类型Boolean、Number和String。每当读取一个基本类型值时,后台会创建一个对应的基本包装类型的对象。
基本包装类型是特殊的引用类型,引用类型与基本包装类型的区别如下:
(1) 对象的生存期
使用new操作符创建的引用类型的实例,在执行流离开当前作用域之前一直存在于内存中,而自动创建的基本包装类型的对象,只存在于代码执行瞬间,然后立即被销毁,也就是说,不能在运行时为基本包装类型添加属性和方法。
(2) instanceof操作符测试结果
使用instanceof操作符测试基本包装类型实例会返回true,测试基本类型值会返回false。
4、String类型
String类型是字符串的对象包装类型,可以使用String构造函数来创建。
String类型继承的valueOf()、toString()、toLocaleString()方法返回对象所表示的字符串值。
5、Number类型
Number类型是数值的对象包装类型,可以使用Number构造函数来创建。Number类型也重写了继承的valueOf()、toString()、toLocaleString()方法,重写后的valueOf()方法返回对应的基本类型值,另外两个方法返回对应的字符串。
6、Boolean类型
Boolean类型是数值的对象包装类型,可以使用Boolean构造函数来创建。Boolean类型的实例重写了valueOf()方法,返回对应的基本类型值true和false;重写了toString()方法,返回字符串"true"和"false"。
7、Function类型
每一个函数都是Function类型的实例,而且都和其他引用类型的实例一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。
8、RegExp类型
ECMAscript通过RegExp类型来支持正则表达式。正则表达式,又称规则表达式,正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
单体内置对象类型
由ECMAScript提供的、不依赖于宿主环境的对象,这些对象在ECMAScript程序执行之前就已经存在了。
在所有代码执行前,作用域中就已经存在两个内置对象:Global和Math。
9、Global对象
不属于任何其他对象的属性和方法,最终都是它的属性和方法;所有在全局作用域中定义的属性和函数,都是Global对象的属性;诸如isNaN()、isFinite()、parseInt()以及parseFloat(),都是Global对象的方法。
在大多数ECMAScript实现中都不能直接访问Global对象;不过,web浏览器实现了承担该角色的window对象。全局变量和函数都是Global对象的属性。
10、Math对象
Math 对象用于执行数学任务。
三)基本类型和引用类型在内存中的区别
基本类型是保存在栈内存(stack)中,引用类型保存在堆内存(heap)中,JavaScript不能直接访问堆内存,通过在栈内存中保存堆内存中对象的引用地址(指针point)来引用堆内存中的对象。
这个逻辑有点像在一个箱子里保存一把钥匙,通过钥匙去开一个房间的门,我们要到房间里取东西就必须通过钥匙。
- 复制一个基本类型变量时,类似将一个箱子a里的东西(值)一模一样的复制一份放到一个新的箱子b里,a与b本质上是两个放了相同东西的箱子,即a=b的值相等,但一个箱子的变化不会影响到另一个箱子。
- 复制一个引用类型时,类似将房间的钥匙要配一把,虽然是两把钥匙,但是开的是一个房间,当房间的情况发生变化时,两把钥匙打开房门看到的是一样的,这种复制引用类型也叫==浅拷贝。
二、判断数据类型
1、最常见的判断方法:typeof方法
类型 | 结果 |
---|---|
String | “string” |
Number | “number” |
Boolean | “boolean” |
Undefined | “undefined” |
Null | “object” |
Object | “object” |
Array | “object” |
function函数对象 | “function” |
Symbol(ES6新增) | “symbol” |
对于原始数据类型,我们可以使用typeof()函数来判断他的数据类型。
注意:typeof 运算符对于 null 值和引用类型一样会返回 “object”。这实际上是 JavaScript 最初实现中的一个错误,现在,null 被认为是对象的占位符,从而解释了这一矛盾,但从技术上来说,它仍然是原始类型。
另外typeof 可以判断function的类型
2、判断已知对象类型的方法: instanceof
instanceof对于引用类型的支持很好,但他是无法对原始类型进行判断,所以一般都是在typeof判断为object时才使用instanceof。
var o1 = {
'name':'Lily'
};
var o2 = [1,2,3];
console.log(o1 instanceof Object);// true
console.log(o2 instanceof Array);// true
3、根据对象的constructor判断
JavaScript中,每个对象都有一个constructor属性,它引用了初始化该对象的构造函数,可以判断未知对象的类型。
var o1 = {
'name':'Lily'
};
var o2 = [1,2,3];
console.dir(o1.constructor); //ƒ Object()
console.log(o1.constructor.name);// Object
console.log(o2.constructor.name);// Array
4、Object.prototype.toString
Object 原型对象上有一个方法toString(),用于返回对象的信息,但由于js的内置引用类型Number、String,Boolean,Array,RegExp、Date、Function都重写了toString()方法,所以需要Object对象的原型方法来实现判断对象的数据类型
Object.prototype.toString.call(obj)
返回调用者的类型字符串,格式是输出的格式就是[object 对象数据类型]。
Object.prototype.toString.call(''); //[object String]
Object.prototype.toString.call(1); //[object Number]
Object.prototype.toString.call(true); //[object Boolean]
Object.prototype.toString.call([]); //[object Array]
Object.prototype.toString.call({}); //[object Object]
Object.prototype.toString.call(undefined); //[object Undefined]
Object.prototype.toString.call(null); //[object Null]
Object.prototype.toString.call(new Function()); //[object Function]
Object.prototype.toString.call(new Date()); //[object Date]
Object.prototype.toString.call(new RegExp()); //[object RegExp]
Object.prototype.toString.call(new Error()); //[object Error]
Object.prototype.toString.call(document); //[object HTMLDocument]
Object.prototype.toString.call(window); //[object Window]
PS:关于ES6关于数据类型的扩展请见《ES6 声明与表达式》