一 种类 - 目前8种
JavaScript默认有6种类型:
- null
- undefined
- number
- string
- boolean
- object
ES6新增类型
- symbol(使用内置Symbol函数创建)
ES10新增类型
- bigint (在数字后缀加上n)
二 类型判断 - typeof使用
在JS中,可以使用 typeof 来进行辨别
当对function使用typeof时候,会返回类型 functiontypeof undefined === 'undefined';typeof 23 === 'number';typeof "23" === 'string';typeof true === 'boolean';typeof {} === 'object';// ES6 新类型typeof Symbol() === 'symbol';// ES10 新类型typeof 999999999999999999999999n === 'bigint';
这样搞得好像function也是JavaScript的一种内置类型一样。typeof function a(){} === 'function';
可以实际function其实也是object类型下的一个子类型,只是其内置调用属性[[Call]]属性实现了调用。
其实数组也是object下的一个子类型
所以有的场景下会说:JavaScript内皆是对象。(虽然该说法有局限,但在日常开发中经常如此。)。typeof [] === 'object';
在typeof使用中还有个例外:null,如果使用 typeof 进行辨别,会出现很奇怪的结果
typeof null === 'object';
这个bug由来已久,已经存在JavaScript中存在了二十多年,如果要判断对象是否是 null 可以使用如下判断
var a = null;(!a && typeof a === "object")
null在typeof下为何为”object”
该问题可以追溯到 JavaScript第一个版本,单个值在栈中占用32位的储存单元。
而32位储存单元中分为:3个类型标签位,29个实际数据位。
这三个类型标签处于低位,即:第0~2位
故可以分为五种情况:
000 —> object
001 —> number
010 —> number(浮点数)
100 —> string
110 —> boolean
而undefined为 -230 在整数范围之外。
null是从第0位到第31位数都为0,所以正好和object的第0~3位数全为0的情况吻合
所以typeof会认为 null 是 object 类型,这算是一个bug吧,目前看来 JavaScript团队还没有修复的打算。
三 值和类型
在JavaScript中,变量是没有类型的,只有值才有,且变量所持有的值可以随时变化为任何类型。
所以JavaScript也被称为“弱语言”。
个人感觉这也是为什么JavaScript是一门非常容易上手的语言,新手甚至都不需要花专门时间看专业书籍,仅需看看前人的代码就可以开始愉快的开发之旅!
(但从后期大型工程开发来看,这种模式也有很严重的弊端。所以出现了像TypeScript这种JS超集的”加强包”来强化JS。但综合来看,JavaScript是一门很优秀且对新手很友好的语言。)
神奇的undefined
在大多数开发者心里undefined其实等同于undeclared(为声明)。
这也不能怪开发者,毕竟在typeof下它也是这么认为的
// 声明但为赋值var a;typeof a; // 'undefined'typeof b; // 'undefined'b; // ReferenceError: b is not defined
这就让人很抓狂了,且在对象中直接引用未声明的属性也是如此
const a = {}a.b; // undefined
这就是为什么大多数开发者认为:undefined(声明未赋值) === undeclared(未声明)。
其实这算是JavaScript的一种安全防范机制,避免在开发过程中过多出现 ReferenceError 错误。
在大部分的开发场景下这样的处理方式也无伤大雅。
但注意!!!在 ES6 中要注意一种情况要格外小心
const a = { one: 1 };const b = { one: undefined };const c = { };// 会覆盖{ ...a, ...b }; // { one: undefined }// 不会覆盖{ ...a, ...c }; // { one: 1 }
在使用 展开运算符 进行对象合并时候,undefined(声明未赋值)和undeclared(未声明)是有质的区别的!
只要后整对象的内部声明了,哪怕真的值是 undefined 也是会覆盖前面对象内的属性。这里要注意!
