数据类型

💡Tips: 在数据类型中,值得注意的是要Null与Undefined的区分以及Number与BigInt的差别

JavaScript 语言中类型集合由原始值对象组成。其中原始值有Undefined、Null、Boolean、String、Number、BigInt(es6新增)、Symbol(es6新增);对象有Object。
本文在这里就不再详细叙述,具体可请看JavaScript数据类型与数据结构。而如果想要深入了解JavaScript的变量在内存中的具体存储形式,可以参考JS中的栈内存堆内存
接下来让我们看看JavaScript中的类型判断。

类型判断

💡Tips: 通常的类型判断中,有typeof、instanceof、constructor、Object.prototype.toString.call()、Array.isArray()等方法,本文只讲述其中三种。

typeof

**typeof** 操作符返回一个字符串,表示未经计算的操作数的类型。一般来说,数组、对象、null 都会被判断为object,其余判断正确。

类型 结果
undefined “undefined”
Boolean “boolean”
Number/NaN “number”
BigInt “bigInt”
String “string”
Function “function”
其他任何对象/ Null “object”

instanceof

**instanceof** 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上,它主要用来判别引用数据类型,不能用于判断基本数据类型

  1. function Car(make, model, year) {
  2. this.make = make;
  3. this.model = model;
  4. this.year = year;
  5. }
  6. function Plane(){}
  7. const auto = new Car('Honda', 'Accord', 1998);
  8. console.log(auto instanceof Car); // true
  9. console.log(auto instanceof Object); // true
  10. console.log(auto instanceof Plane); // false
  11. // 当改变实例对象的原型链时,员表达式的值可能会改变
  12. Car.prototype = {}
  13. console.log(auto instanceof Car) // false

instanceof原理

  1. function instance_of(leftVaule, rightVaule) {
  2. let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值
  3. leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值
  4. while (true) {
  5. if (leftVaule === null) {
  6. return false;
  7. }
  8. if (leftVaule === rightProto) {
  9. return true;
  10. }
  11. leftVaule = leftVaule.__proto__
  12. }
  13. }
  14. function Foo1() {}
  15. function Foo2() {}
  16. Foo1.prototype = new Foo2() {}
  17. let f1 = new Foo1()
  18. console.log(instance_of(f1, Foo1)) // true
  19. console.log(instance_of(f1, Object)) // true
  20. console.log(instance_of(f1, Foo2)) // true
  21. let a = []
  22. let b = {}
  23. console.log(instance_of(a, Array)) // true
  24. console.log(instance_of(b, Array)) // false

如上代码所示,instanceof主要的实现原理就是右边变量的prototype在左边变量的原型链上即可。因此,instanceof在查找过程中会遍历左边变量的原型链,直到找到右边变量的prototype,如果查找失败,返回false。
为了能更好的了解instanceof原理,可以参考js的原型继承原理,如下图:
JS类型判断与转换 - 图1

Object.prototype.toString.call()

想了解上述的方法,我们可以先了解toString()方法。toString()默认返回一个表示给对象的字符串,通过[object type]的方式来表示。我们可以通过该方法来获取每个对象的类型,并且通过使用call()apply()能够获得更为精确的值。如下图:
image.png
为什么会发生这种情况呢?原因在于当对象的**toString()**方法未被重写时,将会正常返回类型;但是大多数对象都重写了**toString()**,这个时候需要用**call()****Reflext.apply()**来调用。

  1. // 1.未重写toString()
  2. ({}).toString(); // => "[object Object]"
  3. Math.toString(); // => "[object Math]"
  4. // 2.重写toString()
  5. var x = {
  6. toString() {
  7. return "X";
  8. },
  9. };
  10. x.toString(); // => "X"
  11. Object.prototype.toString.call(x); // => "[object Object]"

原理

对于 Object.prototype.toString.call(arg),若参数为 null 或 undefined,直接返回结果。若参数不为nullundefined,则将参数转为对象,再做判断。
转为对象后,取得该对象的 [Symbol.toStringTag] 属性值作为 tag,如无该属性,或该属性值不为字符串类型,则依下表取得 tag, 然后返回 "[object " + tag + "]" 形式的字符串。

  1. Object.prototype.toString.call(null); // => "[object Null]"
  2. Object.prototype.toString.call(undefined); // => "[object Undefined]"
  3. // Boolean 类型,tag 为 "Boolean"
  4. Object.prototype.toString.call(true); // => "[object Boolean]"
  5. // Number 类型,tag 为 "Number"
  6. Object.prototype.toString.call(1); // => "[object Number]"
  7. // ...

类型转换

💡 Tips:类型转换是JS中情况繁杂且容易出错的知识点,列举全部知识点繁多,本文在这里只列举开发中的常见情况。想要深入了解可以参考JavaScript深入之头疼的类型转换(上)JavaScript深入之头疼的类型转换(下)

开发中有三种常用的类型转换:转换为 string 类型、转换为 number 类型和转换为 boolean 类型。
字符串转换: 发生在输出内容的时候,也可以通过String(value)进行显示转换。
数字型转换:发生在进行算术操作时,也可以通过Number(value)进行显示转换。

转换成
true/false 1/0
undefined NaN
null 0
string “按原样读取”字符串,两端的空格会被忽略。空字符串变成 0。转换出错则输出 NaN。

布尔型转换:发生在进行逻辑操作时,也可以通过Boolean(value)进行显示变换

转换成
0、null、undefined、NaN、“” false
其他值,比如“0”、“ ” true

关于类型转换暂时就讲述到这里。