数据类型
数据类型简介
在学习JavaScript的过程中,很容易感受到,每一个显示的值,都有它自己所属的数据类型,在JavaScript中,数据类型分为6种:
- 数值(number)
- 字符串(string)
- 布尔值(boolean)
- undefined
- null
- 对象(object)
一般来说,6大数据类型分为两大类:
- 原始类型(primitive type)[数值,字符串,布尔值]
- 合成类型(complex type)[对象]
undefined和null,一般作为特殊值存在。
对象作为复杂的合成类型,又可以分为三个子类型:
- 狭义的对象(object)
- 数组(array)
- 函数(function)
undefined | null |布尔值
定义(undefined | null )
null是表示一个“空”的对象,在转化为数字时,被赋值为0undefined是表示一个“此处无定义”的原始值,转化数值为NaN
Number(undefined) //NaN
Number(null) // 0
用法和含义(undefined | null )
null表示“空“值,表示当前时刻参数的值为空。调用函数时,某个参数未设置任何值,这时就可以传入null,表示该参数为空。某个函数接受引擎抛出的错误作为参数,如果运行过程中未出错,那么这个参数就会传入null,表示未发生错误。
undefined表示“未定义”,声明的变量未赋值,则变量等于undefined,调用函数时,应该提供的参数没有提供,该参数等于 undefined,尝试获取对象不存在的属性,则会得到 undefined,或者是无返回值的函数,默认返回 undefined。
var i;
i // undefined
function f(x) {
return x;
}
f() // undefined
var o = new Object();
o.p // undefined
function f() {}
f() // undefined
布尔值
布尔值代表“真”和“假”两个状态。
truefalse- 前置逻辑运算符:
! - 相等运算符:
===|==|!==|!= ===严格相等,会比较两个值的类型和值 不做类型转换,类型不同的结果一定不等==抽象相等,比较时,会先进行类型转换,然后再比较值- 比较运算符:
>>=<<=
六个被转化为false的特殊值
undefinednullfalse0NaN- 空字符串
" "
数值
整数与浮点
在JavaScript的内部,所有数字都是以64位浮点数形式储存,即使整数也是如此。换句话说,JS的底层根本没有整数,所有数字都是小数(64位浮点数),容易造成混淆的是,某些运算只有整数才能完成,此时 JavaScript 会自动把64位浮点数,转成32位整数,然后再进行运算。 由于浮点数不是精确的值,所以涉及小数的比较和运算要特别小心。
1 === 1.0 // true
0.1 + 0.2 === 0.3 // false
0.3 / 0.1 // 2.9999999999999996
(0.3 - 0.2) === (0.2 - 0.1) // false
数值精度
根据国际标准 IEEE 754,JavaScript 浮点数的64个二进制位,从最左边开始,是这样组成的。
- 第1位:符号位,
0表示正数,1表示负数 决定数值的正负 - 第2位到第12位(共11位):指数部分 决定数值的大小
- 第13位到第64位(共52位):小数部分(即有效数字) 决定数值的精度
关于JS的数值精度,阮一峰老师给出了一个公式
指数部分存在11位,所以能表示的大小范围也就是[0,2047],IEEE 754 规定,如果指数部分的值存在于0到2047之间(不含两个端点),那么有效数字的第一位默认总是1,不保存在64位浮点数之中。也就是说,有效数字这时总是1.xx...xx的形式,其中xx..xx的部分保存在64位浮点数之中,最长可能为52位。因此,JavaScript提供的有效数字最长为53个二进制位。
- 精度最多只能到53个二进制位,
到
,都可以精确表示。
- JavaScript能够表示的数值范围为
到
(开区间),超出这个范围的数无法表示。
- 超出数值表示范围的数则以
Infinity表示,表示正向溢出,或者以0表示,表示负向溢出
表示实际存在的最大最小值
Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324
一个有趣的例子:谈一谈精度的丢失
0.1+0.2=0.30000000000000004 为什么?在计算的过程中,发生了什么?
- 首先
0.1从十进制转换为二进制
0.1
->0.0001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001,1001...无限循环
->(公式) (-1)^(0) * 1.(1001)*12,1001,1001 * 2^(-4)
解释一下:
- 正数符号位为0,所以
- 1.(1001)后面都是1001的无限循环,但是Js本身只能精确到52位,53位开始丢失精度
- 因为是从0.0001....到1.1001... 乘以
所以指数部分要取-4。
从公式分析第49-56位,1001,1001,第53位的1不能取到,所以进位,1001变成1010
转化为二进制之后,0.1比之前变大了。所以0.1+0.2也就比0.3大了
数值的表示
自动转化科学计数法的两种情况
- 小数点前的数字多于21位
- 小数点后的零多于5个
特殊数值
- 正零和负零(在作为分母的时候
+0返回+Infinity,-0返回-Infinity) - NaN
- JS的特殊值,含义是”非数字“(Not a Number)
- 数据类型依然属于 Number
- 不等于任何值,包括它本身
- Infinity
- 表示“无穷”
- 符合正常的四则运算
相关的方法
parseInt()方法用于将字符串转为整数。
- 如果字符串头部有空格,空格会被自动去除。
- 如果parseInt的参数不是字符串,则会先转为字符串再转换。
- 字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分。
- 如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN
- 对于那些会自动转为科学计数法的数字,parseInt会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果。
parseInt(0.0000008) // 8
// 等同于
parseInt('8e-7') // 8
parseFloat()方法用于将一个字符串转为浮点数。
- 如果字符串符合科学计数法,则会进行相应的转换。
- 如果字符串包含不能转为浮点数的字符,则不再进行往后转换,返回已经转好的部分。
- parseFloat方法会自动过滤字符串前导的空格。
- 如果参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回NaN。
- parseFloat会将空字符串转为NaN
字符串
定义
- 字符串就是零个或多个排在一起的字符,放在单引号或双引号之中。
- 单引号字符串的内部,可以使用双引号。双引号字符串的内部,可以使用单引号。
- 如果要在单引号字符串的内部,使用单引号,就必须在内部的单引号前面加上反斜杠,用来转义。双引号字符串内部使用双引号,也是如此。
'Did she say \'Hello\'?' // "Did she say 'Hello'?"
"Did she say \"Hello\"?" // "Did she say "Hello"?"
- 对于
Js的字符串,不要单双引号混用,坚持一种风格 - 长字符串必须分成多行,可以在每一行的尾部使用反斜杠
//反斜杠的后面必须是换行符,而不能有其他字符(比如空格)
var longString = 'Long \
long \
long \
string';
转义
反斜杠(\)在字符串内有特殊含义,用来表示一些特殊字符。
- 特殊的反斜杠
\HHHHHH对应该字符的 Unicode 码点\xHHHH对应该字符的 Unicode 码点\uXXXXXXXX对应该字符的 Unicode 码点
字符串与数组
字符串可以被视为字符数组,因此可以使用数组的方括号运算符,用来返回某个位置的字(位置编号从0开始)。
var s = 'hello';
s[0] // "h"
s[1] // "e"
s[4] // "o"
s[5] // undefined 如果读取了超出长度的位数,则返回未定义
// 直接对字符串使用方括号运算符
'hello'[1] // "e"
字符串与数组的相似性仅此而已。实际上,无法通过赋值改变字符串数组。[字符串不可改变]
length属性
length属性返回字符串的长度,该属性也是无法改变的。对length属性做赋值更改,不会生效,也不会报错。
字符集
JavaScript 使用 Unicode 字符集。JavaScript 引擎内部,所有字符都用 Unicode 表示。
//Js会自动识别unicode的字符,包括程序中,在渲染显示时,都会直接转换为字面形式
var s = '\u00A9';
s // "©"
var f\u006F\u006F = 'abc';
foo // "abc"
每个字符在 JavaScript 内部都是以16位(即2个字节)的 UTF-16 格式储存。
'𝌆'.length // 2
特殊的字符(四字节字符)浏览器可以正常识别,但是JS无法识别正确的长度
Base64 转码
对于包含特殊字符或者不可打印字符的符号,可以转化为Base64 编码。或者以文本格式传递二进制数据时,也可以使用Base64 编码。
Js提供了两个原生的方法://只适用与Ascll码
- btoa()
- atob()
检定值的类型
在Js中,如何检定一个值的类型呢?Js提供了三种方法
- typeof
- instanceof
- Object.prototype.toString
唯一需要注意的是 typeof 函数对于null的返回,是Object。