数据类型

基本数据类型

  • Number
  • String
  • Boolean
  • undefined
  • null
  • Symbol(ES2015)
  • BigInt(ES2020)

    引用数据类型

  • Object

  • Array
  • Function

    Date,Math,Set,Map,WeakSet,WeakMap,WeakRef

区别

  • 基本数据类型的数据称为原始值,即最简单的数据。原始值保存在栈(Stack)中,按值(by value)访问。其占据内存空间是固定的,更适合放在空间较小的栈中,查询速度较快。

  • 引用数据类型的数据称为引用值,是由多个值构成的对象。引用值散乱地保存在堆(Heap)中,按引用(by reference)访问,因此当作为参数传递时,实际上是传递了引用值所在的内存地址。在堆中可占据的内存空间较大且灵活,但查询速度较慢。

    1. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/1499486/1630314813907-390bfb23-e2b9-4e6b-a5c0-d9b95324db0a.png#clientId=u384942bb-854a-4&from=paste&height=353&id=ubfb8c1d6&margin=%5Bobject%20Object%5D&name=image.png&originHeight=271&originWidth=295&originalType=binary&ratio=1&size=16400&status=done&style=none&taskId=u7c5ba5c9-df4b-4a89-914f-df261b59bf2&width=384.48614501953125)

类型判断

typeof

用法:typeof instance | typeof(instance)

typeof 返回数据类型

  • 对于基本数据类型及Function类型,typeof 将返回正确的数据类型

    1. typeof 'str'; // string;
    2. typeof 1; // number
    3. typeof true; // boolean
    4. typeof undefined; // undefined
    5. typeof Symbol(); // symbol
    6. typeof BigInt(123); // bigint
    7. typeof Function(); // function
  • 除Function之外的引用数据类型,通过 new 生成的实例,特殊数据结构,typeof 将返回 object ```javascript typeof new String(); typeof new Date(); typeof Math; // js内置Math对象 typeof new Map(); typeof new Set(); typeof new WeakMap(); typeof new WeakSet();

// object

  1. - 对于`null` 返回 `object`
  2. > JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null 代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0typeof null 也因此返回 "object"
  3. ```bash
  4. typeof null === 'object'; // true

instanceof

通过原型链的 prototype 检测对象是否是构造函数的实例,返回一个布尔值

  1. const str = new String();
  2. const date = new Date();
  3. const weakmap = new WeakMap();
  4. function Person(name) { this.name = name };
  5. const man = new Person();
  6. str instanceof String; // true
  7. date instanceof Date; // true
  8. weakmap instanceof WeakMap; // true
  9. man instanceof Person; // true

instanceof 将通过原型链的 prototype 向上查询,因此派生类的实例对于基类也将返回 true

  1. // 接上述例子
  2. date instanceof Object; // true
  3. man instanceof Object; // true
  4. Math instanceof Object; // true

同时需要注意的是,若 prototype 指向的值被修改,返回结果也将发生变化,但应避免这种情况发生

Object.prototype.toString()

toString() 是对象内置方法,对于对象将返回 [Object type],因此可以借用 Function.prototype.call()Function.prototype.apply() 方法,使实例通过 Object.prototype.toString() 获取类型

对于基本数据类型,调用**toString()**时实际上是通过包装类创建一个实例调用方法返回结果,再销毁实例

原始值被当作构造函数创建的一个对象来使用时,JavaScript会将其转换为一个对象,以便可以使用对象的特性,而后抛弃对象性质,并将它变回原始值

出自《JavaScript启示录》

  1. Object.prototype.toString.call(date); // [object Date]
  2. Object.prototype.toString.call(man); // [object Object]
  3. Object.prototype.toString.call(Math); // [object Math]

因此可以封装一个方法获取数据类型

  1. function _typeof(data) {
  2. return Object.prototype.toString.call(data).slice(8, -1).toLowerCase();
  3. }

Array.isArray()

判断是否是数组

  1. Array.isArray([]); // true
  2. Array.isArray('str'); // false

类型转换

在JavaScript中,只有三种类型转换,分别是:

  • 转换成 number 类型
  • 转换成 string 类型
  • 转换成 boolean 类型

    强制转换

    强制转换主要是使用三种基本数据类型的包装类即 Number()String()Boolean(),除此之外转换成number类型还可使用parseInt()parseFloat()

    Number()

    引用红宝书中的具体规则如下:
    image.png
    主要难点在于对象的转换规则:
    1. if (typeof obj.valueOf() === 'object') {
    2. Number(obj.toString());
    3. } else {
    4. Number(obj.valueOf());
    5. }
    我们结合下具体例子加以理解: ```javascript const obj = { a: 1 }; const arr = []; const obj1 = { valueOf() { return {} }, toString() { return {} } };

Number(obj); // NaN Number(arr); // 0 Number(obj1); // Uncaught TypeError: Cannot convert object to primitive value

  1. - `obj.valueOf()` 为对象,调用`toString()`获取字符串`[object Object]`,转换结果为`NaN`
  2. - `arr.valueOf()` 为数组对象,调用`toString()`获取空字符串,转换结果为 `0`
  3. - 我们将 `obj1` `valueOf()``toString()` 返回值都设为对象,此时 `Number()` 执行转换将报错
  4. 此外,对于字符串转换为数值,还可以使用`parseInt()``parseFloat()`<br />两者用法相似,但有些区别:
  5. - `parseInt()` 会取整,`parseFloat()` 不会
  6. - `parseInt()` 可以传入第二个参数指明转换进制,`parseFloat()` 则不支持
  7. ```javascript
  8. // parseInt 与 Number 主要区别
  9. Number(1.3); // 1.3
  10. parseInt(1.3); // 1
  11. Number('123aa'); // NaN
  12. parseInt('123aa'); // 123
  13. Number(true); // 1
  14. parseInt(true); // NaN
  15. Number(null); // 0
  16. parseInt(null); // NaN
  17. Number(undefined); // NaN
  18. parseInt(undefined); // NaN
  19. Number([]); // 0
  20. parseInt([]); // NaN
  21. Number({}); // NaN
  22. parseInt({}); // NaN

String()

  • 对于 number 类型,转换成相应的字符串
  • nullundefinedtruefalse 转换成相应的字符串
  • 字符串不变
  • 对象,调用 toString(),对原始类型按上述规则转换;如果是对象,则调用valueOf(),对原始类型同上,若valueOf()返回对象,则报错。

针对对象的转换规则,和Number()相似,只是互换了toString()valueOf()方法

  1. if (typeof obj.toString() === 'object') {
  2. String(obj.valueOf());
  3. } else {
  4. String(obj.toString());
  5. }
  1. const obj = { a: 1 };
  2. const arr = [];
  3. const obj1 = {
  4. valueOf() { return {} },
  5. toString() { return {} }
  6. };
  7. String(obj); // [object Object]
  8. String(arr); // ''
  9. String(obj1); // Uncaught TypeError: Cannot convert object to primitive value

Boolean()

布尔值转换规则较为简单,仅下面几种情况转换结果为 false

  • false
  • 空字符串
  • 0、NaN
  • null
  • undefined

== 、 ===、Object.is()

== 相等运算符
在比较左边两边时仅对比值是否相同,且涉及类型转换,其规则如下:

  • nullundefined 相等
  • 两边都为 number 类型直接对比值大小
  • 一方为 string/boolean,一方为 number,将 string/boolean 转换成 number,再进行比较
  • 只有一方为对象,则调用valueOf() 获取原始值,再根据上述规则进行
  • 两边都为对象,则判断两边对象引用地址是否相等

=== 严格相等运算符
左右两边不仅值要想等,其类型也必须一致,但是对于 NaN 类型,将返回false

  1. NaN === NaN; // false

Object.is()就是在 === 基础上正确返回对 NaN 类型的判断, 同时还有 +0-0 不想等

  1. Object.is(NaN, NaN); // true
  2. Object.is(+0, -0); // false

参考文献