【三】JavaScript类型:关于类型,有哪些你不知道的细节?
抛出问题
- 为什么有的编程规范要求用 void 0 代替 undefined?
- 字符串有最大长度吗?
- 0.1+0.2不是等于0.3吗?为什么js里面不是这样?
- es6中的symbol是什么?
- 为什么给对象添加的方法能用在基本类型上?
一、类型
js语言的每一个值都属于某一种数据类型。js规定了7种语言类型。广泛的用于变量、函数参数、表达式、函数返回值等场合。分别是
- undefined
- null
- boolean
- string
- number
- symbol
- object
1、undefined、null
undefined表示未定义,它的类型只有一个值,就是undefined。但是js的代码undefined是一个变量,并非一个关键字,会造成可能无意中的篡改,所以使用void 0来获取undefined的值
null表示空值,是js的关键字,所以在任何代码中,都可以用null来获取null的值
2、boolean
boolean有两个值,true和false,表示逻辑上的真和假,同样就具有关键字的true和false来表示
3、string
string表示文本数据。最大长度是2^53-1,一般来说是够用的。但是string的意义并非“字符串”,而是UTF16编码,我们平时的charAt、charCodeAt、length等方法都是针对UTF16编码。所以,字符串最大的长度其实是受字符串的编码长度影响的。
4、number
number表示我们通常意义上的“数字”,大致对应数学中的有理数,当然在计算机中是有精度限制的
js中的number类型有18437736874454810627(即 264-253+3)个值,它基本符合IEEE 754-2008规定的双精度浮点数规则,但是也有几个例外
- NaN,占用了9007199254740990,这是符合规则的数字
- Infinity,无穷大
- -Infinity,无穷小
根据双精度浮点数的定义,number类型中有效的整数范围是-0x1fffffffffffff至0x1fffffffffffff,所以number无法精确表示此范围外的整数
非整数的number类型无法使用==或者===来比较,比如
console.log(0.1 + 0.2 == 0.3)
// false
但是我们可以这样干
console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);
// true
这是使用了js提供的最小精度值,检查等式左右两边差的绝对值是否小于最小精度。
5、symbol
symbol是es6中新引入的类型,是一切非字符串对象key的集合,在es6的规范中,整个对象系统被用symbol重塑
symbol可以具有字符串类型的描述,但是即使描述相同,symbol也不相同
我们创建一个全局的symbol函数
var mySymbol = Symbol("my symbol");
使用symbol.iterator来自定义for...of在对象上的行为:
var o = new Object
o[Symbol.iterator] = function() {
var v = 0
return {
next: function() {
return { value: v++, done: v > 10 }
}
}
};
for(var v of o)
console.log(v); // 0 1 2 3 ... 9
6、object
object是js中最复杂的类型。也是js的核心机制之一,object是对象的意思。
在js中,对象的定义是“属性的集合”,属性分为数据属性和访问器属性,二者都是key-value的结构,key可以是字符串或者symbol类型
说到对象,我们一定要说一下“类”
在js中,“类”仅仅是运行时对象的一个私有属性,而js中是无法自定义类型的
js中有几个基本类型,都在对象中有自己的“亲戚”
- number
- string
- boolean
- symbol
所以要知道,3和 new Number(3)是完全[图片上传中...(image.png-75b66f-1549423004254-0)]
不同的值,一个是number的类型,一个是对象类型
二、类型转换
因为js是弱类型语言,所以类型转换发生十分频繁,看图
image.png
装箱变换
装箱变换即把基本类型转换成对应的对象
拆箱变换
拆箱变换即在js中,规定了ToPrimitive函数,它是对象类型到基本类型的转换
var o = {
valueOf : () => {console.log("valueOf"); return {}},
toString : () => {console.log("toString"); return {}}
}
o * 2
// valueOf
// toString
// TypeError
三、写在最后
除了7种用语言类型,还有一些语言的实现者更关心的规范类型
- list和record:用于描述函数传参的过程
- set:主要用于解释字符集等
- completion record:用于描述异常、跳出等语句执行过程
- reference:用于描述对象属性访问、delete等
- property descriptor:用于描述对象的属性
- lexical environment和environment record:用于描述变量和作用域
- data block:用于描述二进制数据
关于typeof
typeof是用返回操作数的类型,但是我们可以看下图
image.png
可以看出typeof对于object和function是有问题的,这确实是缺陷,但是js之父也说已经错过了修改它的最佳时机了。。