JavaScript类型判断方法:避免常见陷阱,写出更可靠的代码

JavaScript 是一种动态弱类型的语言,变量被赋值时可以自动推断其类型,这在一定程度上方便了开发,但同时也可能导致一些类型相关的问题。为了解决这些问题,我们需要使用 JavaScript 中的类型判断方法。今天我们将详细讲解各种方法和使用它们需要注意的问题。

数据类型

先来回顾一下数据类型:

- 原始类型:

  1. number数值型: let num = 123
  2. string字符串:let str = 'hello'
  3. boolean布尔型:let bool = true
  4. undefined未定义: let un = undefined
  5. null空值:let nl = null

在es6后,还新增了两种原始类型:

6. Symbol类型:let s = Symbol(123)

它表示一个独一无二的值,可以用作对象属性的键。Symbol值是不可变且唯一的,每个Symbol值都是独立的,不会和其他任何值相等。

创建Symbol可以使用Symbol()构造函数或Symbol.for()方法。Symbol()构造函数创建的Symbol是临时的,而Symbol.for()方法创建的Symbol是全局的,它会先在全局Symbol注册表中搜索键为传入参数的Symbol,如果找到则返回该Symbol,否则创建一个新的Symbol并添加到全局Symbol注册表中。

Symbol可以作为对象的属性键,用于解决属性名冲突的问题。由于每个Symbol值都是唯一的,所以可以保证不会与其他属性名冲突。例如:

ini 复制代码
const mySymbol = Symbol();
const obj = {};

obj[mySymbol] = 'Hello Symbol';
console.log(obj[mySymbol]); // 输出 'Hello Symbol'

需要注意的是,Symbol值并不具有字符串的隐式转换功能,如果需要显示转换为字符串,可以使用Symbol的toString()方法或将其与一个空字符串进行连接。

7. BigInt大整型:let big = 123n

BigInt类型用于存储超出JavaScript固有数字限制的大整数。JavaScript中的Number类型可以精确表示最大值为2^53-1的整数值,超过这个值的整数计算可能会产生精度丢失。而BigInt类型则可以表示任意大的整数,不受JavaScript固有数字限制的影响。

使用BigInt类型可以通过在整数值后面加上n来创建,例如:const bigNum = 123456789012345678901234567890n;

BigInt类型支持包括加减乘除、位运算等在内的多种算术运算和比较操作。需要注意的是,在进行数值运算时,BigInt类型只能与其他BigInt类型进行运算,不能与普通Number类型混合运算。

例如,可以使用以下代码创建两个BigInt类型的变量并进行加法运算:

ini 复制代码
const bigNum1 = 123456789012345678901234567890n;
const bigNum2 = 987654321098765432109876543210n;
const result = bigNum1 + bigNum2;
console.log(result);

- 引用类型:

  1. Object对象:let obj = {}
  2. Function函数:let fn = function(){}
  3. Array数组:let arr = []
  4. Date日期:let date = new Date()

(本文类型判断中引用类型就只讨论这几种,还有其他正则表达式等就不提了)

类型判断

接下来我们进入正题,类型判断有哪几种方法呢?

1. typeof

用typeof进行类型判断,需要注意以下两点:

  1. typeof可以准确判定原始类型,除了null,用typeof判断null会输出object。

  2. typeof不能判定引用类型,除了function,用typeof判断引用类型都会输出object,但除了function,function类型它可以判断出来。

    javascript 复制代码
     console.log(typeof 'hello'); 
     console.log(typeof 123);
     console.log(typeof true);
     console.log(typeof undefined);
     console.log(typeof Symbol(1));
     console.log(typeof 123n);
     console.log(typeof null);  
    
     console.log(typeof ({})); //object
     console.log(typeof ([])); //object
     console.log(typeof (new Date())); //object
     console.log(typeof (function(){})); //function
     

输出结果是:

2. instanceof

使用instanceof运算符来判断是否是某种类型需要知道的是:

  1. 只能判断引用类型,当我们用instanceof去判断原始类型时,输出值一律为false。

  2. instanceof的原理是通过原型链的查找来判断的。所以当我们去判断数组、函数、日期类型是否为对象类型时,也会返回true。

    javascript 复制代码
     let str = 'hello'
     console.log(str instanceof String); //不能判断,专门为引用类型打造的
     
     let obj = {}
     let arr = [1,3]
     let date = new Date()
     let fn = function(){}
    
     console.log(obj instanceof Object);
     console.log(arr instanceof Array);
     console.log(date instanceof Date);
     console.log(fn instanceof Function);
    
     console.log(arr instanceof Object);// 输出true

输出结果为:

我们来看一下instanceof的原理,如果有对原型链不太懂的掘友可以先去看下我这篇 JavaScript原型与原型链:理解核心概念,构建强大的前端技能哦,里面有详细讲解。

在JavaScript中,每个对象都有一个原型(prototype),原型又是一个对象,同时也有自己的原型。这样形成了一个原型链,直到最顶层的原型为null。

instanceof操作符会检查对象的原型链,看是否能在链上找到与指定构造函数的原型相匹配的原型。

如果在原型链中找到了匹配的原型,instanceof返回true;如果顺着原型链一直往上找到null都没有找到匹配的原型,则返回false。

javascript 复制代码
//instanceof 的原理

function myInstance(l,r){

    let left = l.__proto__
    let right = r.prototype

    while(left !== null){
        if(left === right){
            return true
        }
        left = left.__proto__
    }
    return false
}

3. Object.prototype.toString()

Object.prototype.toString() 方法是 JavaScript 中最古老的方法之一,它可以比较准确地判断一个值的类型,包括原始类型和对象类型。当我们调用 Object.prototype.toString() 方法时,会根据传入的值的 [[Class]] 内部属性的值返回一个形如 "[object class]" 的字符串,其中 class 是实际类型的字符串表示。

typescript 复制代码
let str = 'hello'
let num = 123
let bigint = 123n

let obj = {}
let arr = [1,2]

console.log(Object.prototype.toString.call(str));
console.log(Object.prototype.toString.call(num));
console.log(Object.prototype.toString.call(bigint));
console.log(Object.prototype.toString.call(obj));
console.log(Object.prototype.toString.call(arr));

输出结果为:

需要注意的是,Object.prototype.toString() 方法返回的是一个形如 "[object class]" 的字符串,我们可以通过对返回结果进行处理来判断类型,将返回结果进行字符串切割。以代码里的str = 'hello'为例:

vbnet 复制代码
console.log(Object.prototype.toString.call(str).slice(8,-1));
// 进行切割后将由输出[object String]变为输出String

如果想要详细了解这个方法的原理,可以点此15.2.4.2Object.prototype.toString ( )官方文档里去查看。

4. Array.isArray()

Array.isArray() 方法用于判断一个值是否为数组类型,它只能用于数组类型的判断,对于其他引用类型则返回 false。

以下是使用 Array.isArray() 方法进行数组类型判断的示例代码:

ini 复制代码
let arr = [];

console.log(Array.isArray(arr)); // 输出 true

需要注意的是,Array.isArray() 方法位于 Array 对象上,而不是在它的原型上,因此我们可以直接调用该方法来进行数组类型的判断,但不能arr.isArray()这样去用。

今天类型判断的方法到这就讲完啦!欢迎下次再来一起学习哦ヾ(◍°∇°◍)ノ゙

相关推荐
小小小小宇3 分钟前
请求竞态问题统一封装
前端
loriloy4 分钟前
前端资源帖
前端
源码超级联盟6 分钟前
display的block和inline-block有什么区别
前端
GISer_Jing12 分钟前
前端构建工具(Webpack\Vite\esbuild\Rspack)拆包能力深度解析
前端·webpack·node.js
让梦想疯狂14 分钟前
开源、免费、美观的 Vue 后台管理系统模板
前端·javascript·vue.js
海云前端37 分钟前
前端写简历有个很大的误区,就是夸张自己做过的东西。
前端
葡萄糖o_o1 小时前
ResizeObserver的错误
前端·javascript·html
AntBlack1 小时前
Python : AI 太牛了 ,撸了两个 Markdown 阅读器 ,谈谈使用感受
前端·人工智能·后端
MK-mm1 小时前
CSS盒子 flex弹性布局
前端·css·html
小小小小宇1 小时前
CSP的使用
前端