基本类型
ECMAScript语言中所有的值都有一个对应的语言类型,ECMAScript语言类型包括Undefined、Null、Boolean、String、Number和Object(ES6中新增了Symbol)。除了对象Object被称为复杂数据类型外,其他均被称为“基本类型”。
在ES中,值是有类型的,但是变量是没有类型的。所以说,ES不做“类型强制”,JS有时也因此被称为“弱类型语言”。例如,开始为一个变量a赋一个Number类型的值,以后也可以再为该变量赋一个String类型的值。
var a = 123; //此时a变量中的值为Number类型
a = '123'; //此时a变量中的值为String类型
内置类型
JavaScript有七种内置类型:
- 空值(null)
- 未定义(undefined)
- 布尔值(boolean)
- 数字(number)
- 字符串(string)
- 对象(object)
- 符号(symbol)
其中,前五种是ES5中的基础数据类型,称为“基本类型”。在ES6中,新增了符号(symbol)这种基本类型。上面七种数据类型中,除了对象(object)是“复杂类型”外,其他六种都是“基本类型”。
类型检测
通过typeof操作符可以查看值的类型。typeof返回的有:'undefined'、'boolean'、'string'、'number'、'object'、'function'、'symbol'。其中有个例外(bug),typeof null返回的值是‘object’。所以检测几种数据类型的方式为:
typeof undefined === 'undefined'; //true
typeof false === 'boolean'; //true
typeof '123' === 'string'; //true
typeof 123 === 'number'; //true
typeof Symbol() === 'symbol'; //true
var a = null;
!a && typeof a === 'object'; //true,检查值是否为null
var obj = new Object();
obj && typeof obj === 'object'; //true
不同的对象在底层都表示为二进制,在JavaScript中二进制前三位都为0的话会被判断为object类型,null的二进制表示是全0,自然前三位也是0,所以执行typeof时会返回“object” ——你不知道的JS
基本类型与复杂类型区别
JavaScript不同于C++等语言,它没有指针。JavaScript对值和引用的赋值/传递在语法上没有区别,完全根据值的类型来决定。简单值(即标量基本类型值,scalar primitive)总是通过值复制的方式来赋值/传递;复合值(compound value)——对象(包括数组和其他封装对象等)和函数,则总是通过引用复制的方式来赋值/传递。
var a = 1;
var b = a;
b++;
a; // 1
b; // 2
var obj1 = { count: 1 };
var obj2 = obj1;
obj2.count++;
obj1.count; // 2
obj2.count; // 2
在调用函数时,会创建一份参数的副本,简单值复制值,复合值复制引用。
function foo(x) { // x是a的副本,由于a是复合值,所以x复制a的引用
x.push(4);
x; // [1, 2, 3, 4]
x = [5, 6, 7]; // x指向另一个复合值
x; // [5, 6, 7]
}
var a = [1, 2, 3];
foo(a);
a; //[1, 2, 3, 4]
我们在向函数foo传递a的时候,实际是将引用a的一个副本复制给x,而a仍指向[1, 2, 3];在函数执行时,通过引用x来修改数组的值,因为此时a和x指向同一个值,所以x和a都指向了[1, 2, 3, 4];但是`x = [5, 6, 7]`将x引用指向了另外一个数组[5, 6, 7],而a的引用不被影响,所以,a仍然指向数组[1, 2, 3, 4]。也就是说,如果x是a引用副本,可以用x引用可以改变a引用共同指向的值,但是不能用x引用来修改a引用的指向。