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 字符索引来⽐较
相关推荐
EricWang13581 分钟前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning1 分钟前
React.lazy() 懒加载
前端·react.js·前端框架
晴天飛 雪11 分钟前
React 守卫路由
前端框架·reactjs
web行路人11 分钟前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
番茄小酱00112 分钟前
Expo|ReactNative 中实现扫描二维码功能
javascript·react native·react.js
子非鱼92131 分钟前
【Ajax】跨域
javascript·ajax·cors·jsonp
超雄代码狂33 分钟前
ajax关于axios库的运用小案例
前端·javascript·ajax
长弓三石42 分钟前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
小马哥编程43 分钟前
【前端基础】CSS基础
前端·css
嚣张农民1 小时前
推荐3个实用的760°全景框架
前端·vue.js·程序员