JavaScript中有七种数据类型,本文主要描述了我在阅读JavaScript教程时我不会的细节知识点。
Number
存储方式
所有的number都是以64位浮点数形式存储的,所以当计算的时候结果并不准确。
1 | 0.1 + 0.2 // 0.30000000000000004 |
当进行位运算时,会转换为32位的整型
1 | ~1.1 // -2 |
精度
根据国际标准 IEEE 754,JavaScript 浮点数的64个二进制位,从最左边开始,是这样组成的。
- 第1位:符号位,
0
表示正数,1
表示负数 - 第2位到第12位(共11位):指数部分
- 第13位到第64位(共52位):小数部分(即有效数字)
计算公式:
1 | (-1)^符号位 * 小数部分 * 2^指数部分 |
其中小数部分表示1.xxxx…x,所以只需存储xxxx…x部分即可。
1 | // 当整数值大于2^53时计算会出现错误 |
因为64位浮点数最多可以表示53个二进制位,所以在JavaScript中绝对值小于2^53^的整数(-9007199254740992~9007199254740992)可以被精确表示,也可以简记为15位的十进制整数可以精确表示。
1 | // 当浮点数大于可表示的最大值时,会上溢出,转换为Infinity |
因为指数部分的值为11位,可以表示的范围为[-1023, 1023],所以JavaScript中浮点数可以表示的值范围为[2^-1023^, 2^1024^)。
JavaScript 提供Number
对象的MAX_VALUE
和MIN_VALUE
属性,返回可以表示的具体的最大值和最小值。
1 | Number.MAX_VALUE // 1.7976931348623157e+308 |
数值表示方法
科学计数法表示
1 | 123e3 // => 123 * (10 ** 3) => 123000 |
当整数部分多余21位时,会使用科学计数法表示
1 | 1234567890123456789012 // 1.2345678901234568e+21 |
小数点后的零多于5个,同样会使用科学计数法表示
1 | 0.0000003 // => 3 * (10 ** -7) => 3e-7 |
不同进制表示
1 | 0xff // 16进制 => 255 |
其余问题详见阮一峰JavaScript教程
1 | NaN === NaN // false |
String
JavaScript 对 UTF-16 的支持是不完整的,由于历史原因,只支持两字节的字符,不支持四字节的字符。这是因为 JavaScript 第一版发布的时候,Unicode 的码点只编到U+FFFF
,因此两字节足够表示了。后来,Unicode 纳入的字符越来越多,出现了四字节的编码。但是,JavaScript 的标准此时已经定型了,统一将字符长度限制在两字节,导致无法识别四字节的字符。上一节的那个四字节字符𝌆
,浏览器会正确识别这是一个字符,但是 JavaScript 无法识别,会认为这是两个字符。
JavaScript 原生提供两个 Base64 相关的方法。
btoa()
:任意值转为 Base64 编码atob()
:Base64 编码转为原来的值
1 | var string = 'Hello World!'; |
注意,这两个方法不适合非 ASCII 码的字符,会报错。
1 | btoa('你好') // 报错 |
Boolean
1 | // 只有这7种情况为false,其余情况全都为true |
null
表示无
1 | // 遵循c语言的传统,null转换为number为0 |
undefined
表示未定义
1 | // undefined转换为number为NaN |
Object
for...in
循环有两个使用注意点。
- 它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性。
- 它不仅遍历对象自身的属性,还遍历继承的属性。
Function
函数的name
属性返回函数的名字。
1 | function f1() {} |
如果是通过变量赋值定义的函数,那么name
属性返回变量名。
1 | var f2 = function () {}; |
但是,上面这种情况,只有在变量的值是一个匿名函数时才是如此。如果变量的值是一个具名函数,那么name
属性返回function
关键字之后的那个函数名。
1 | var f3 = function myName() {}; |
上面代码中,f3.name
返回函数表达式的名字。注意,真正的函数名还是f3
,而myName
这个名字只在函数体内部可用。
name
属性的一个用处,就是获取参数函数的名字。
1 | var myFunc = function () {}; |
上面代码中,函数test
内部通过name
属性,就可以知道传入的参数是什么函数
array
JavaScript 使用一个32位整数,保存数组的元素个数。这意味着,数组成员最多只有 4294967295 个(232 - 1)个,也就是说length
属性的最大值就是 4294967295。
如果数组的键名是添加超出范围的数值,该键名会自动转为字符串。
1 | var arr = []; |
Symbol(es6)
symbol是es6的新数据类型,简而言之就是一个独一无二的可以作为key的类型。暂时不做过多的了解,详细的教程看ECMAScript入门或者MDN
ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入Symbol的原因。
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
Symbol 值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
本文链接:JavaScrit中的数据类型
版权声明:本文章采用CC BY-NC-SA 3.0 CN许可协议进行许可。转载请注明出处!