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

一、内置类型

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

  • 基本类型: null , undefined , boolean , number , string , symbol , bigInt .
  • 对象或复杂类型: array , object , function .

PS: undefined 派生自 null 但它们的意义是不一样的. undefined 指定义了变量却未初始化. null 指定义了当前变量且这个变量未来是用于存储 object 类型的值.

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

js 复制代码
let num = 666;
num.toString(); // 虽然 num 属于基本类型,但是它可以调用方法,并且不会报错

// 上面相当于

// 1. 字面量声明
let num = 666;
// 2. 转为对应构造函数的实例, 并调用方法, 调用结束后,直接删除生成的这个实例
new Number(num).toString();

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

typeof

直接看判断结果

js 复制代码
// 基本类型
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 操作得到的.

js 复制代码
    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 区分)

js 复制代码
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() 直接调用只能得到重写后的值.
js 复制代码
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) 是一致的
js 复制代码
   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 ,该⽅法在转基本类型时调⽤优先级最⾼

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

  • 只有当加法运算时,其中⼀⽅是字符串类型,就会把另⼀个也转为字符串类型
  • 其他运算只要其中⼀⽅是数字,那么另⼀⽅就转为数字
  • 并且加法运算会触发三种类型转换:将值转换为原始值,转换为数字,转换为字符串
js 复制代码
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'
js 复制代码
'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 字符索引来⽐较
相关推荐
Kiros_Jiang25 分钟前
开源低代码平台-Microi吾码 打印引擎使用
javascript·开源·json·.net·pip
╰つ゛木槿26 分钟前
深入了解 React:从入门到高级应用
前端·react.js·前端框架
LCG元38 分钟前
Vue.js实例开发-如何通过Props传递数据
vue.js
m0_748241231 小时前
ElasticPDF-新国产 PDF 编辑器开发框架(基于 pdf.js Web PDF批注开发,实现高亮多边形橡皮擦历史记录保存注释文字)
前端·pdf·编辑器
m0_694938011 小时前
Leetcode打卡:考场就坐
javascript·算法·leetcode
前端青山1 小时前
JavaScript 数组操作与排序算法详解
开发语言·javascript·排序算法
huapiaoy1 小时前
JavaSE---String(含一些源码)
java·linux·前端
rkmhr_sef1 小时前
frp内网穿透云服务器。云服务器映射多个家庭局域网内网端口。家庭Windows主机内网运行多个web程序
服务器·前端·windows
带多刺的玫瑰1 小时前
Leecode刷题C语言之考场就座
c语言·前端·javascript