关于类型,有哪些不知道的细节?
问题
- 为什么有的编程规范要求用void 0 代替 undefined?
- 字符串有最大长度吗?
- 0.1 + 0.2 不是等于0.3吗? 为什么JavaScript里不是这样的?
- ES6 新加入的Symbol 是个什么东西?
- 为什么给对象添加的方法能用在基本类型上?
undefined 和 null(为什么有的编程规范要求用void 0 代替 undefined?)
- Undefined 类型是未定义,它的类型只有一个值,就是undefined,未定义
- Null 类型也只有一个值,就是null,定义了但是为空
- undefined 是变量,null 是关键字
- undefined 是变量,这是JavaScript语言公认的设计失误之一,因为变量会被篡改,所以,为了避免无意中被篡改,使用void 0 来获取undefined值
String (字符串有最大长度吗?)
- String 有最大长度是2^53-1
- String 的意义并非“字符串”,而是字符串的UTF16编码
Number(0.1 + 0.2 不是等于0.3吗? 为什么JavaScript里不是这样的?)
- JavaScript 中Number 类型有18437736874454810627(即2^64-2^53+3)个值
- 额外的语言场景,可以除以0不会出错
- NaN
- Infinity 正无穷
- -Infinity 负无穷大
- 区分 +0和-0的方式,正是监测1/x是Infinity还是-Infinity
- 正确比较小数点方法
Math.abs(0.1+ 0.2 - 0.3) <= Number.EPSILON
// Math.abs() 绝对值
// Number.EPSILON ES6新增 表示可以接受的最小误差范围。
Symbol(ES6 新加入的Symbol 是个什么东西?)(ps: 参考《ECMAScript 6 入门》)
- Symbol 不是对象,不能使用new命令,不能添加属性, 基本上,它是一种类似于字符串的数据类型。
- Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示。
- 如果 Symbol 的参数是一个对象,就会调用该对象的toString方法,将其转为字符串,然后才生成一个 Symbol 值。
- Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。
- Symbol 值不能与其他类型的值进行运算,会报错。但是,Symbol 值可以显式转为字符串。
- Symbol 值也可以转为布尔值,但是不能转为数值。
- Symbol 值作为对象属性名时,不能用点运算符。
- 在对象的内部,使用 Symbol 值定义属性时,Symbol 值必须放在方括号之中。
- Symbol 作为属性名,该属性不会出现在for…in、for…of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。但是,它也不是私有属性,有一个Object.getOwnPropertySymbols方法,可以获取指定对象的所有 Symbol 属性名。
Object(为什么给对象添加的方法能用在基本类型上?)
- (点).运算符提供了装箱操作,它会根据基础类型构造一个临时对象,使得我们能在基础类型上调用对应对象的方法
类型转换
- 臭名昭著的是JavaScript中“==” 实现跨类型比较吗, 属于设计失误
String To Number
- Number()
- parseInt()
- parseFloat()
- 隐式转换(运算符ps: - * /)
装箱转换
- 装箱转换:基本类型转换为对应的引用类型的操作称为装箱转换
拆箱转换
- 对象类型转换为基本数据类型称为拆箱
- 将引用类型对象转换为对应的值类型对象,它是通过引用类型的valueOf()或者toString()方法来实现的。如果是自定义的对象,你也可以自定义它的valueOf()/tostring()方法,实现对这个对象的拆箱。
var objNum = new Number(123);
var objStr =new String("123");
console.log( typeof objNum ); //object
console.log( typeof objStr ); //object
console.log( typeof objNum.valueOf() ); //number
console.log( typeof objStr.valueOf() ); //string
console.log( typeof objNum.toString() ); // string
console.log( typeof objStr.toString() ); // string
- 拆箱转换会尝试调用valueOf 和toSting来获得拆箱后的基本类型,如何valueOf 和toString都不存在,或者没有返回基本类型,则会产生类型错误TypeError
var o = {
valueOf: () => {
console.log('valueOf');
return {}
},
toString: () => {
console.log('toString');
return {}
}
}
o * 2
// valueOf
// toString
// TypeError 产生错误类型的原因是,虽然o对象中有valueOf 和 toString, 但是没有返回基本类型
- ES6 之后,允许对象通过显示指定@@toPrimitive Symbol 来覆盖原有的行为
var o = {
valueOf: () => {
console.log('valueOf');
return {}
},
toString: () => {
console.log('toString');
return {}
}
}
o[Symbol.toPrimitive] = () => {
console.log('toPrimitive');
return "hello"
}
console.log(o + '');
// toPrimitive
// hello