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 字符索引来⽐较
相关推荐
码蜂窝编程官方3 分钟前
【含开题报告+文档+PPT+源码】基于SpringBoot+Vue的虎鲸旅游攻略网的设计与实现
java·vue.js·spring boot·后端·spring·旅游
gqkmiss3 分钟前
Chrome 浏览器 131 版本开发者工具(DevTools)更新内容
前端·chrome·浏览器·chrome devtools
Summer不秃9 分钟前
Flutter之使用mqtt进行连接和信息传输的使用案例
前端·flutter
旭日猎鹰13 分钟前
Flutter踩坑记录(二)-- GestureDetector+Expanded点击无效果
前端·javascript·flutter
Viktor_Ye20 分钟前
高效集成易快报与金蝶应付单的方案
java·前端·数据库
hummhumm22 分钟前
第 25 章 - Golang 项目结构
java·开发语言·前端·后端·python·elasticsearch·golang
_半夏曲37 分钟前
node.js、nginx、iis、tomcat针对部署方面的简述
nginx·node.js·tomcat
乐闻x1 小时前
Vue.js 性能优化指南:掌握 keep-alive 的使用技巧
前端·vue.js·性能优化
一条晒干的咸魚1 小时前
【Web前端】创建我的第一个 Web 表单
服务器·前端·javascript·json·对象·表单
花海少爷1 小时前
第十章 JavaScript的应用课后习题
开发语言·javascript·ecmascript