目录
一 类型
JavaScript 语言的每一个值都属于某一种数据类型。JavaScript 语言规定了 7 种语言类
型。语言类型广泛用于变量、函数参数、表达式、函数返回值等场合。分别是:
- undefined;
- Null;
- Boolean;
- String;
- Number;
- Symbol;
- Object。
1.1 undefined
任何变量在赋值前是undefined 类型
、值为 undefined
因为设计失误: undefined 是一个变量,而并非是一个关键字
,为了避免无意中被篡改,我建议使用void 0 来获取 undefined 值。
在现代浏览器中,undefined的值将不能被重写
void 运算
把任意一个表达式变成undefined 值。
1.2 null
Null 类型也只有一个值,就是 null,它的语义表示空值,与 undefined 不同,null 是JavaScript 关键字
,所以在任何代码中,你都可以放心用 null 关键字来获取 null 值。
1.3 String
有最大长度是 2^53 - 1。这个所谓最大长度,并不完全是你理解中的字符数
。我们字符串的操作charAt、charCodeAt、length 等方法针对的都是 UTF16 编码
。所以,字符串的最大长度,实际上是受字符串的编码
长度影响
的。
1.4 Number
几个例外情况:
- NaN,占用了 9007199254740990,这原本是符合 IEEE 规则的数字;
- Infinity,无穷大;
- -Infinity,负无穷大。
JavaScript 中有 +0 和 -0
,在加法类运算中它们没有区别,但是除法的场合则需要特别留意区分,“忘记检测除以 -0,而得到负无穷大”的情况经常会导致错误,而区分 +0 和 -0 的方式,正是检测 1/x
是 Infinity 还是 -Infinity。
正确的比较方法
console.log( 0.1 + 0.2 == 0.3);//错误
console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);//正确
1.5 Symbol
Symbol 是 ES6
中引入的新类型,它是一切非字符串
的对象 key
的集合
,在 ES6 规范中,整个对象系统被用 Symbol 重塑。
Symbol 可以具有字符串类型的描述
,但是即使描述相同
,Symbol 也不相等
创建 Symbol
var mySymbol = Symbol("my symbol");
1.6 Object
对象的定义是“属性的集合”
。属性分为数据属性
和访问器属性
,二者都是 key-value 结构,key 可以是字符串或者 Symbol 类型
。
类
因为 C++ 和 Java 的成功,在这两门语言中,每个类都是一个类型,二者几乎等同,以至于很多人常常会把 JavaScript 的“类”与类型混淆。类型只有7种,类有无数种
JavaScript 中的“类”仅仅是运行时对象的一个私有属性
,而 JavaScript 中是无法自定义类型的。;总结:类是属性,不是完全和java中的概念一样。
JavaScript 中的几个基本类型,都在对象类型中有一个“亲戚”。它们是:
- Number
- String
- Boolean
- Symbol
所以,3 与 new Number(3) 是完全不同
的值,它们一个是 Number 类型, 一个是对象类型。
Number、String 和 Boolean,三个构造器是两用
的,当跟 new 搭配时,它们产生对象,当直接调用时,它们表示强制类型转换。
JavaScript 语言设计上试图模糊对象和基本类型之间的关系,我们日常代码可以把对象的方法在基本类型上使用
,比如:
console.log("abc".charAt(0)); //a
甚至我们在原型上添加方法,都可以应用于基本类型,比如以下代码,在 Symbol 原型上添加了 hello 方法,在任何 Symbol 类型变量都可以调用。
Symbol.prototype.hello = () => console.log("hello");
var a = Symbol("a");
console.log(typeof a); //symbol,a 并非对象
a.hello(); //hello,有效
为什么对象的方法在基本类型上可以使用
.
运算符提供了装箱操作
,它会根据基础类型构造一个临时对象,使得我们能在基础类型上调用对应对象的方法。
二 类型转换
因为 JS 是弱类型语言
,所以类型转换发生非常频繁,大部分我们熟悉的运算都会先进行类型转换。大部分类型转换符合人类的直觉,但是如果我们不去理解类型转换的严格定义,很容易造成一些代码中的判断失误。
==
的规则非常复杂,不建议使用.建议显式
地类型转换后,用===
比较
2.1 StringToNumber
字符串到数字的类型转换,存在一个语法结构,类型转换支持十进制、二进制、八进制和十六进制,比如:
- 30;
- 0b111;
- 0o13;
- 0xFF。
还支持括正负号科学计数法:比如:1e3
parseInt 和 parseFloat函数
这两个函数的转换规则和Number不一样,不传入第二个参数的情况下,parseInt 只支持 16 进制前缀“0x”,而且会忽略非数字字符,也不支持科学计数法。和java的强转不一样()是括后面的
var sc = Number("0x12")//值等于18
总结 多数情况下,Number 是比 parseInt 和 parseFloat 更好的选择。
2.2 NumberToString
在较小的范围内,数字到字符串的转换是完全符合你直觉的十进制表示。当 Number 绝对值较大或者较小
时,字符串表示则是使用科学计数法
表示的。
三 装箱转换
每一种基本类型 Number、String、Boolean、Symbol 在对象中都有对应的类
。所谓装箱转换,正是把基本类型转换为对应的对象
,它是类型转换中一种相当重要的种类。
性能问题
装箱机制会频繁产生临时对象
,在一些对性能要求较高的场景下,我们应该尽量避免对基本类型做装箱转换。