JS 中的类型 & 类型判断 & 类型转换

简介: JS 中的类型 & 类型判断 & 类型转换

image.png


一、内置类型

JS 中有 8 种内置类型,⼜分为两⼤类型: 7 种【基本类型】 和 【对象或复杂类型】:

  • 基本类型: null , undefined , boolean , number , string , symbol , bigInt .
  • 对象或复杂类型: array , object , function .
  • PS:  undefined 派生自 null 但它们的意义是不一样的. undefined 指定义了变量却未初始化. null 指定义了当前变量且这个变量未来是用于存储 object 类型的值.

注意:对于【基本类型】来说,如果使⽤字⾯量的⽅式,那么这个变量只是个字⾯量,只有在必要的时候才会转换为对应的类型.

let num = 666;
num.toString(); // 虽然 num 属于基本类型,但是它可以调用方法,并且不会报错
// 上面相当于
// 1. 字面量声明
let num = 666;
// 2. 转为对应构造函数的实例, 并调用方法, 调用结束后,直接删除生成的这个实例
new Number(num).toString();
复制代码

二、类型判断 — typeof & instanceof &  Object.prototype.toString.call(obj)

typeof

直接看判断结果

// 基本类型
console.log(typeof null);          // object
console.log(typeof undefined);     // undefined
console.log(typeof true);          // boolean
console.log(typeof '666');         // string
console.log(typeof 1);             // number
console.log(typeof 1n);            // bigint
console.log(typeof Symbol());      // symbol
// 复杂类型
console.log(typeof []);                // object
console.log(typeof {});                // object
console.log(typeof function add(){});  // function   
复制代码

从以上判断结果可以看出来:

  • 基本类型中除了对 null 的判断错误之外,其他的都是正常的.
  • PS: 【typeof null 为 object,是因为最初的 js 版本使用的是 32 位系统,为了性能考虑使用低位存储变量的类型信息,其中 000 开头的代表的是对象,然而 null 是用全 0 表示,所以将它错误的判断为 object 】
  • 复杂类型中除了对 function 和 {} 类型判断正确之外,其他的都是错误的.

instanceof

用于判断一个变量是否属于某个对象的实例,既然是实例意味着该变量是通过 new 操作得到的.

var bool = new Boolean(true);
    var str = new String('666');
    var num = new Number(1);
    var date = new Date();
    var reg = new RegExp(/.+/);
    var arr = new Array();
    var obj = new Object({});
    var add = function () {}
    console.log(bool instanceof Boolean);           // true
    console.log(str instanceof String);             // true
    console.log(num instanceof Number);             // true
    console.log(date instanceof Date);              // true
    console.log(reg instanceof RegExp);             // true
    console.log(arr instanceof Array);              // true
    console.log([] instanceof Array);               // true
    console.log(obj instanceof Object);             // true
    console.log({} instanceof Object);              // true
    console.log(add instanceof Function);           // true
    // 自定义类
    class Person{
      constructor(name){
        this.name = name;
      }
    }
    var person = new Person('zs'); 
    console.log(person instanceof Person);        // true
复制代码
  • 注意:null、undefined、symbol、bigint 没有自己专属的构造函数,因此不可以进行 new 操作,所以不适用于 instanceof 判断
  • 作用:
  • 判断某个实例是否属于某构造函数
  • 在继承关系中用来判断一个实例是否属于它的父类型或者祖先类型的实例
  • 如:left instanceof right ,只要  right.prototype  存在于 left.__proto__ 的原型链上,则会返回 true , 否则返回 false .
  • 缺点:
  • 并不适用于所有的类型
  • 由于它依赖于构造函数去判断,所以当某个实例的构造函数指向被强行修改,那么判断将出现错误

Object.prototype.toString.call(obj)

使用以上方式可以很好的区分各种类型:(无法区分自定义对象类型,自定义类型可以采用 instanceof 区分)

console.log(Object.prototype.toString.call("str"));   //[object String]
console.log(Object.prototype.toString.call(1));        //[object Number]
console.log(Object.prototype.toString.call(true));      //[object Boolean]
console.log(Object.prototype.toString.call(undefined)); //[object Undefined]
console.log(Object.prototype.toString.call(null));      //[object Null]
console.log(Object.prototype.toString.call({name: "zs"})); //[object Object]
console.log(Object.prototype.toString.call(function(){}));   //[object Function]
console.log(Object.prototype.toString.call([]));  //[object Array]
console.log(Object.prototype.toString.call(new Date));  //[object Date]
console.log(Object.prototype.toString.call(/\d/));  //[object RegExp]
function Person(){};
console.log(Object.prototype.toString.call(new Person));  //[object Object]
复制代码
  • 为什么不直接使用 obj.toString() ?
  • 因为 toString 是 Object.prototype 上的方法,而 Array、Function 等类型虽然作为 Object 的实例,但它们都重写了 toString 方法,因此 obj.toString() 直接调用只能得到重写后的值.
console.log(({}).toString()); // [object Object]
console.log("zs".toString()); // zs
console.log((1).toString()); // 1
console.log([1,2].toString()); // 1,2
console.log(new Date().toString()); // Thu Oct 14 2021 22:25:11 GMT+0800 (中国标准时间)
console.log(function(){}.toString()); // function (){}
console.log(null.toString()); // error
console.log(undefined.toString()); // error
复制代码
  • 如果删除了被重写的 toString 后,可以发现结果和 Object.prototype.toString.call(obj) 是一致的
var arr = [1, 2, 3];
   var func = function (){};
   // 调用重写的 toString
   console.log(Array.prototype.hasOwnProperty("toString")); //true
   console.log(Function.prototype.hasOwnProperty("toString")); //true
   console.log(arr.toString()); //  '1,2,3'
   console.log(func.toString()); // 'function (){}'
   // delete 操作符删除实例属性
   delete Array.prototype.toString;
   delete Function.prototype.toString;
   // 本质上是调用 Object.prototype.toString
   console.log(Array.prototype.hasOwnProperty("toString")); //false  
   console.log(Function.prototype.hasOwnProperty("toString")); //false
   console.log(arr.toString()); // "[object Array]"
   console.log(func.toString()); // "[object Function]"
复制代码

三、类型转换

转 Boolean

在条件判断时,除了undefined ,null , false , NaN , '' , 0 , -0 ,其他所有值都转为 true ,包括所有对象。

对象转基本类型

  • 对象在转换基本类型时,⾸先会调⽤ valueOf ,然后调⽤ toString 。并且这两个⽅法是可以被重写的。
  • 当然你也可以重写 Symbol.toPrimitive ,该⽅法在转基本类型时调⽤优先级最⾼。

四则运算符(+、-、*、/)

  • 只有当加法运算时,其中⼀⽅是字符串类型,就会把另⼀个也转为字符串类型。
  • 其他运算只要其中⼀⽅是数字,那么另⼀⽅就转为数字。
  • 并且加法运算会触发三种类型转换:将值转换为原始值,转换为数字,转换为字符串。
1 + '1' // '11'
2 * '2' // 4
[1, 2] + [2, 1] // '1,22,1'
// [1, 2].toString() -> '1,2'
// [2, 1].toString() -> '2,1'
// '1,2' + '2,1' = '1,22,1'
复制代码
  • 对于加号需要注意这个表达式 'a' + + 'b'
'a' + + 'b' // -> "aNaN"
// 因为 + 'b' -> NaN
// 你也许在⼀些代码中看到过 + '1' -> 1
复制代码

== 操作符

例子:x == y

  • x,y 为 number || string => 先把 string 转 number ,后进行比较
  • x,y 为 number || boolean => 先把 boolean 转 number ,后进行比较
  • 任何与 NaN 进行的比较都返回 false
  • x,y 为 string || boolean => 先把 string 和 boolean 转 number ,后进行比较
  • x,y 为 undefined || null => 返回 true
  • x,y 为 number => -0 == +0 返回 true ,其他正负不相等
  • x,y 为 (number || string) || object => 先把 object 转基本类型,后进行对比
  • object => [Symbol.toPrimitive] () || valueOf() || toString()
  • x,y 为 boolean || object => 先把 boolean 转 number ,按上述规则 5 比较

> || < || =< || => 比较运算符

  • x,y 为 object || other => object 转成 基本类型,然后比较
  • x,y 为 string => 通过 unicode 字符索引来⽐较


目录
相关文章
|
10天前
|
JavaScript 前端开发 开发者
如何在 JavaScript 中处理不同类型的错误?
【10月更文挑战第29天】通过对不同类型错误的准确识别和恰当处理,可以提高JavaScript程序的可靠性和稳定性,减少错误对程序运行的影响。
|
1月前
|
JavaScript 前端开发 安全
深入理解TypeScript:增强JavaScript的类型安全性
【10月更文挑战第8天】深入理解TypeScript:增强JavaScript的类型安全性
45 0
|
3月前
|
前端开发 JavaScript 搜索推荐
Next.js 适合什么类型的项目开发?
【8月更文挑战第4天】Next.js 适合什么类型的项目开发?
192 3
|
9天前
|
JavaScript 前端开发 Java
除了 JavaScript,还有哪些编程语言支持 Set 类型
【10月更文挑战第30天】这些编程语言中的 `Set` 类型虽然在语法和具体实现细节上有所不同,但都提供了类似的集合操作功能,方便开发者在不同的编程场景中处理集合相关的数据和逻辑。
|
10天前
|
存储 JavaScript 前端开发
js的基础类型和引用类型
【10月更文挑战第29天】理解 JavaScript 中的基础类型和引用类型的区别对于正确地编写代码和理解程序的行为非常重要。在实际开发中,需要根据具体的需求合理地选择和使用不同的数据类型,以避免出现一些意想不到的错误和问题。同时,在处理引用类型数据时,要特别注意对象的引用关系,避免因共享引用而导致的数据不一致等问题。
|
5月前
|
JavaScript 前端开发
JavaScript中的布尔类型与数字类型详解
JavaScript中的布尔类型与数字类型详解
|
28天前
|
JavaScript 前端开发 安全
如何处理 JavaScript 中的类型转换错误?
【10月更文挑战第9天】处理类型转换错误需要综合运用多种方法和策略,同时要保持对潜在问题的警惕性。通过合理的错误处理,可以提高程序的健壮性,减少因类型转换错误带来的负面影响。
16 0
|
28天前
|
JavaScript 前端开发
JS隐式类型转换规则
【10月更文挑战第9天】 不同的 JavaScript 引擎可能在隐式类型转换的具体实现上存在一些细微差别。理解这些隐式类型转换规则对于正确处理数据和避免错误非常重要。
16 0
|
1月前
|
JavaScript 前端开发
JavaScript返回判断类型有哪些?
JavaScript返回判断类型有哪些?
27 0
|
2月前
|
JavaScript 前端开发
JavaScript 类型转换
JavaScript 类型转换
25 4