JavaScript数据类型

类型

在最新的ECMAScript标准定义了7种数据类型中,一共有7种数据类型,6种原始数据类型/基本数据类型(Number, String, Boolean, Null, Undefined, Symbol),1种引用类型/复杂类型Object,而Object类型又可以细分为Array, Function, Date, Error等等。

类型检测

typeof一元运算符

typeof可以检测出number, string, boolean, undefined, object, function,symbol这些类型,但是对于其他类型是判断不出来的。

instanceof二元运算符

instanceof运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype属性。语法:object instanceof constructor
下面我们先来回忆一下之前学过的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function C(){}
function D(){}
var o = new C();
o instanceof C;//true
o instanceof D;//false
C.prototype instanceof Object;//true
C.prototype = {};
var o2 = new C();
o2 instanceof C;//true
o instanceof C;//false 重写了C的prototype之后,指向的新对象不在o的原型链上
D.prototype = new C();//继承
var o3 = new D();
o3 instanceof D;//true
o3 instanceof C;//true

instanceof运算符的判断步骤:

1
2
3
4
5
6
7
8
9
10
11
12
13
function instance_of(L, R) {
var O = R.prototype;
L = L.__proto__;
while (true) {
if(L === null) {
return false;
}
if(O === L) {
return true;
}
L = L.__proto__;
}
}

__proto__又是啥呢?根据ECMA定义”to the value of its constructor’s prototype”指向创建这个对象的函数的显示原型。对于Object来说就是Object.proto === Function.prototype。对于new运算符创建出来的对象来说就是构造函数的prototype。有了上面的过程我们就更加容易明白intanceof运算符了。

1
2
3
4
5
Object instanceof Object;//true
Function instanceof Function;//true
Number instanceof Number;//false
String instanceof String;//false
Function instanceof Object;//true

根据上面的过程可以想想为什么?
但是instanceof运算符只能判断两个对象是否属于原型链的关系,并不能获取对象的具体类型。比如说:

1
2
3
var a=new Array();
a instanceof Array; // true
a instanceof Object; // true Array.prototype.__proto__ = Object.prototype

Object.prototype.toString.call()方法

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
var num = 1;
var str = "1";
var boo = true;
var und = undefined;
var nul = null;
var arr = [1,2,3];
var obj = {name: "li", age: 25};
var dat = new Date();
var err = new Error();
var exp = new RegExp("s$");
var func = function(){console.log('1')};
var mat = Math;
var jso = JSON;
var sym = Symbol();
console.log(Object.prototype.toString.call(num), Object.prototype.toString.call(str),
Object.prototype.toString.call(boo), Object.prototype.toString.call(und),
Object.prototype.toString.call(nul), Object.prototype.toString.call(arr),
Object.prototype.toString.call(obj), Object.prototype.toString.call(dat),
Object.prototype.toString.call(err),Object.prototype.toString.call(exp),
Object.prototype.toString.call(mat),Object.prototype.toString.call(jso),
Object.prototype.toString.call(func),Object.prototype.toString.call(sym));
(function a() {
console.log(Object.prototype.toString.call(arguments));
})()
[object Number] [object String] [object Boolean] [object Undefined] [object Null] [object Array] [object Object] [object Date] [object Error] [object RegExp] [object Math] [object JSON] [object Function] [object Symbol]
[object Arguments]

我们可以看到至少可以判断出15种类型。
jquery种type方法的实现源码:https://github.com/jquery/jquery/blob/ac9e3016645078e1e42120822cfb2076151c8cbe/src/core.js#L269
另外,在ES5中,又为数组提供了一种检测方法,Array.isArray(obj),如果对象是 Array,则为true; 否则为false。

null与undefined的区别

简单的来说,null表示”没有对象”,即此处不应该有值,undefined表示”缺少值”,就是此处应该有一个值,但是还没有定义。需要注意的是用一元操作符typeof判断null时,返回值为object。

1
2
3
4
5
null == undefined;//true
typeof null;//object
typeof undefined;//undefined
Number(null) //0
Number(undefined) //NaN

null的应用场景

1:用来初始化一个可能赋值的对象,或者清空一个对象的赋值(方便JS引擎对这个变量进行垃圾回收)
2:用来和一个已经初始化的变量做比较,这个变量可以是也可以不是一个对象
3:函数参数期望是对象时,作为参数传入,函数返回期望是对象时,做为返回值传出
4:作为对象原型链的终点。Object.getPrototypeOf(Object.prototype)//null

undefined的应用场景

1:变量声明但未被初始化
2:函数没有返回值
3:访问不存在的对象属性时
4:函数参数没有被传递值
5:赋值为undefined的变量
6:void(expression) 形式的表达式。

这里解释一下第6条:void在JavaScript中是一个操作符,对传入的操作不执行并且返回undefined。void后面可以跟()来用,例如void(0)。在HTML里阻止带href的默认点击操作时,都喜欢把href写成javascript:void(0),实际上也是依靠void操作不执行的意思。

参考文章:https://segmentfault.com/a/1190000000512023
https://www.zhihu.com/question/34183746
https://www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/index.html