JS 里的数据类型
JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型,共有六种。
- 数值(number):整数和小数(比如
1
和3.14
) - 字符串(string):文本(比如
Hello World
)。 - 布尔值(boolean):表示真伪的两个特殊值,即
true
(真)和false
(假) -
undefined
:表示“未定义”或不存在,即由于目前没有定义,所以此处暂时没有任何值 -
null
:表示空值,即此处的值为空。 - 对象(object):各种值组成的集合。
通常,数值、字符串、布尔值这三种类型,合称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分了。对象则称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于undefined和null,一般将它们看成两个特殊值。
对象可以分成三类:
- 狭义的对象(object)
- 数组(array)
- 函数(function)
关于typeof运算符
typeof
运算符可以返回一个值的数据类型。
数值、字符串、布尔值分别返回number
、string
、boolean
。
typeof 123 // "number"
typeof '123' // "string"
typeof false // "boolean"
函数返回function
。(函数属于对象的一种,理论应该返回object
,但是js里是返回function
,算是bug)
undefined
返回undefined
。
利用这一点,typeof
可以用来检查一个没有声明的变量,而不报错。
a
// ReferenceError: v is not defined
typeof a
// "undefined"
上面代码中,变量a
没有用var
命令声明,直接使用就会报错。但是,放在typeof
后面,就不报错了,而是返回undefined
。
对象返回object
。
typeof window // "object"
typeof {} // "object"
typeof [] // "object"
null
返回object
。(实际上null
的类型就是null
,返回object
也算是bug)
typeof null // "object"
null
返回的类型是object
,这是由于历史原因造成的。1995年的 JavaScript 语言第一版,只设计了五种数据类型(对象、整数、浮点数、字符串和布尔值),没考虑null
,只把它当作object
的一种特殊值。后来null
独立出来,作为一种单独的数据类型,为了兼容以前的代码,typeof null
返回object
就没法改变了。
一、数值(number)
- 关于数值的进制
使用字面量(literal)直接表示一个数值时,JavaScript 对整数提供四种进制的表示方法:十进制、十六进制、八进制、二进制。
- 十进制:没有前导0的数值。
- 八进制:有前缀
0o
或0O
的数值,或者有前导0、且只用到0-7的八个阿拉伯数字的数值。 - 十六进制:有前缀
0x
或0X
的数值。 - 二进制:有前缀
0b
或0B
的数值。
默认情况下,JavaScript 内部会自动将八进制、十六进制、二进制转为十进制。
如果八进制、十六进制、二进制的数值里面,出现不属于该进制的数字,就会报错。
- 关于NaN
NaN是 JavaScript 的特殊值,表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合。
2 - 'w' //报错
上面代码运行时,会自动将字符串x
转为数值,但是由于x
不是数值,所以最后得到结果为NaN
,表示它是“非数字”(NaN
)。
NaN
不是独立的数据类型,而是一个特殊数值,它的数据类型依然属于Number
。
NaN
不等于任何值,包括它本身。
NaN === NaN // false
二、字符串(string)
- 定义
字符串就是零个或多个排在一起的字符,放在单引号或双引号之中。
'bbb'
"aaa"
单引号字符串的内部,可以使用双引号。双引号字符串的内部,可以使用单引号。
"'key' = value"
'hello "world" yeah'
如果要在单引号字符串的内部,使用单引号,就必须在内部的单引号前面加上反斜杠,用来转义。双引号字符串内部使用双引号,也是如此。
'go go \'go\'' //"go go 'go'"
注意,转义符\
与后面的任何字符数字都只算一个length,转义符也可以转转义本身。\\
空字符串''
和空格字符串' '
是不一样的,前者length为0,后者为1。
如果长字符串必须分成多行,可以在每一行的尾部使用反斜杠。(不建议这种方法)
var a ='a\
c\
e';
输出的时候还是单行,效果与写在同一行完全一样。注意,反斜杠的后面必须是换行符,而不能有其他字符(比如空格),否则会报错。
连接运算符(+
)可以连接多个单行字符串,将长字符串拆成多行书写,输出的时候也是单行。(分成多行建议这种方法)
var b ='a'
+'c'
+'f';
三、布尔值(Boolean)
布尔值代表“真”和“假”两个状态。“真”用关键字true表示,“假”用关键字false表示。布尔值只有这两个值。
相与运算符&&
a&&b
必须要a和b同时为true
或者false
,结果才会是true
false
;
或运算符||
只要a或者b有一个是true
时,结果就是true
,只有当ab同时为false
时,结果才是false
。
四、null 和 undefined
null与undefined都可以表示“没有”,含义非常相似。将一个变量赋值为undefined或null,都表示什么都没有。
区别:
- 变量没有被赋值 ——>undefined 声明了但是没有定义的变量
- var obj = null ——>null 空对象
五、对象(object)
- 生成方法
对象(object)是 JavaScript 语言的核心概念,也是最重要的数据类型。对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合。
var obj = {
foo: 'Hello',
bar: 'World'
};
上面代码中,大括号就定义了一个对象,它被赋值给变量obj
,所以变量obj
就指向一个对象。该对象内部包含两个键值对(又称为两个“成员”),第一个键值对是foo: 'Hello'
,其中foo
是“键名”(成员的名称),字符串Hello
是“键值”(成员的值)。键名与键值之间用冒号分隔。第二个键值对是bar: 'World'
,bar
是键名,World
是键值。两个键值对之间用逗号分隔。
-
键名
对象的所有键名都是字符串,所以加不加引号都可以。如果键名是数值,会被自动转为字符串。
如果键名不符合标识名的条件(比如第一个字符为数字,或者含有空格或运算符),且也不是数字,则必须加上引号,否则会报错。
对象的每一个键名又称为“属性”(property),它的“键值”可以是任何数据类型。如果一个属性的值为函数,通常把这个属性称为“方法”,它可以像函数那样调用。 -
属性的读取
读取对象的属性,有两种方法,一种是使用点运算符,还有一种是使用方括号运算符。
var obj = {
p: 'Hello'
};
obj.p // "Hello"
obj['p'] // "Hello"
上面代码分别采用点运算符和方括号运算符,读取属性p
。
注意,如果使用方括号运算符,键名必须放在引号里面,否则会被当作变量处理。
var f = 'b';
var obj = {
f: 1,
b: 2
};
obj.f // 1
obj[f] // 2
上面代码中,引用对象obj
的f
属性时,如果使用点运算符,f
就是字符串;如果使用方括号运算符,但是不使用引号,那么f
就是一个变量,指向字符串b
。
方括号运算符内部还可以使用表达式。数字键可以不加引号,因为会自动转成字符串。
obj['hello' + ' world']
obj[3 + 3]
注意,数值键名不能使用点运算符(因为会被当成小数点),只能使用方括号运算符。
var obj = {
123: 'hello world'
};
obj.123 // 报错
obj[123] // "hello world"
上面代码的第一个表达式,对数值键名123
使用点运算符,结果报错。第二个表达式使用方括号运算符,结果就是正确的。
- 属性的查看
查看一个对象本身的所有属性,可以使用Object.keys
方法。
var obj = {
key1: 1,
key2: 2
};
Object.keys(obj);
// ['key1', 'key2']
- 属性的删除:delete 命令
delete
命令用于删除对象的属性,删除成功后返回true
。
var obj = { p: 1 };
Object.keys(obj) // ["p"]
delete obj.p // true
obj.p // undefined
Object.keys(obj) // []
上面代码中,delete
命令删除对象obj
的p
属性。删除后,再读取p
属性就会返回undefined
,而且Object.keys
方法的返回值也不再包括该属性。
注意,删除一个不存在的属性,delete
不报错,而且返回true
。因此,不能根据delete命令的结果,认定某个属性是存在的。
只有一种情况,delete
命令会返回false
,那就是该属性存在,且不得删除。
- 属性是否存在:in 运算符
in
运算符用于检查对象是否包含某个属性(注意,检查的是键名,不是键值),如果包含就返回true
,否则返回false
。
var obj = { a: 1 };
'a' in obj // true
- 属性的遍历:for...in 循环
for...in
循环用来遍历一个对象的全部属性。
var obj = {a: 1, b: 2};
for (var key in obj) {
console.log(key);
console.log(obj[key]);
}
// a
// 1
// b
// 2
注意,遍历出的顺序并不一定是按照对象内部的顺序排列的。它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性。