JavaScript数据类型以及类型判断
数据类型
- 基本数据类型:Number、String、Boolean、Null、undefined,ES6新增了BigInt、Symbol
- 引用数据类型:Object、Function
两种数据类型的区别
基本数据类型是存储在栈中的;而引用数据类型是存储在堆中的,它会在栈中存储一个指向内容所在堆空间中的地址。
为什么要有两种数据类型?
基本数据类型是直接存储值的,是存储内容本身;而引用数据类型存储的是内容的地址,指向内容本身。假设数据在多个地方被使用,如果该数据使用基本数据类型存储,那么这些地方拿到的都是该数据的新副本,它们之间是相互独立的,修改源数据也不会引起这些地方的更新。而使用引用数据类型存储,那么这些地方拿到的只是该数据的地址,当修改数据内容时,其它使用了该数据的地方就能拿到更新后的数据。
null与undefined的区别
- undefined:表示未定义,是变量最原始的状态。当一个变量被声明了但还未赋值时,它的默认值是undefined;
- null:表示空值,变量是有赋值的但赋值为空。比如,当一个变量被赋值为某个对象时,该变量存储的是这个对象的地址值,此时把变量赋值为null,相当于切断变量与对象的联系,变量指向的是空对象。
非构造函数形式调用
在非构造函数上下文中(没有new),Number、String、Boolean可被用来执行类型转换。但非构造函数形式与构造函数形式创建的不是同一个对象。
let s1 = '123'; let s2 = String(123); let s3 = new String(123); console.log(s1===s2); //true console.log(s2===s3); //false
数据类型的检测方法
typeof操作符
类型 |
输出结果 |
Undefined |
“undefined” |
Null |
“object” |
Boolean |
“boolean” |
Number |
“number” |
String |
“string” |
Function |
“function” |
BigInt |
“bigint” |
Symbol |
“symbol” |
其他任何对象 |
“object” |
注意事项:
- 使用typeof操作符检测数组类型时输出的是"object";
- 除了new Function()之外,其他所有使用构造函数(new操作符)创建的变量用typeof检测类型输出都是"object";
let arr = []; console.log(typeof arr); //“object” let str1 = new String(" "); let str2 = " "; console.log(typeof str1); //“object” console.log(typeof str2); //"string"
instanceof操作符
语法:object instanceof constructor
用于检测构造函数constructor的prototype属性是否出现在某个实例对象object的原型链上。
let arr = []; let str1 = ""; let str2 = String(""); let str3 = new String(""); console.log(arr instanceof Array); //true console.log(str1 instanceof String); //false console.log(str2 instanceof String); //false console.log(str3 instanceof String); //true console.log(1 instanceof Number); //false console.log(new Number(1) instanceof Number); //true
Object.prototype.constructor属性
返回创建的实例对象的构造函数的引用,该属性的值是对构造函数本身的引用,也就是说,若输出某对象实例的constructor属性,输出的是构造函数代码,而不是包含构造函数名的字符串。
let arr = []; let str1 = ""; let str2 = String(""); let str3 = new String(""); console.log(arr.constructor === Array); //true console.log(str1.constructor === String); //true console.log(str2.constructor === String); //true console.log(str3.constructor === String); //true console.log((1).constructor === Number); //true
console.log((true).constructor === Boolean); //true
注意事项:
- null、undefined类型的原始值是没有constructor属性的;
- 对于自定义类,若重写该类的原型属性,有可能会导致该类的constructor不再指向该类的构造函数;
类的组合继承方式中,重写子类的原型(SubType.prototype = new SuperType();)会导致子类的constructor属性不再指向子类构造函数。
console.log(instance1.constructor === SubType); //false console.log(instance1.constructor === SuperType); //true
Object.prototype.toString方法
每个对象都有toString()方法,当该对象被表示为一个文本值或以预期的字符串方式引用时,都会自动调用该方法。默认情况下,若此方法在自定义类中没有被覆盖,toString()返回["object type"],其中type是对象的类型。
由于非自定义对象(如Array、String等)已经重写了toString()方法,因此要实现数据类型检测功能,应该利用Function.prototype.call()方法来调用原始的Object.prototype.toString(),使其输出[object type],而我们只需要使用slice()方法取字符串的第8位到倒数第二位,即可提取出表示数据类型的字符串type。例如,下面检测字符串类型String:
let str = ""; console.log(Object.prototype.toString.call(str).slice(8,-1)); //String
相等(==)与严格相等(===)
相等操作符(==)与(!=)
相等运算符(==
和!=
)使用抽象相等比较法比较两个操作数:
- 如果两个操作数都是对象,则仅当两个操作数都引用同一个对象时才返回
true
。 - 如果一个操作数是
null
,另一个操作数是undefined
,则返回true
。 - 如果两个操作数是不同类型的,就会尝试在比较之前将它们转换为相同类型:
- 当数字与字符串进行比较时,会尝试将字符串转换为数字值。
- 如果操作数之一是
Boolean
,则将布尔操作数转换为1或0。- 如果是
true
,则转换为1
。 - 如果是
false
,则转换为0
。
- 如果是
- 如果操作数之一是对象,另一个是数字或字符串,会尝试使用对象的
valueOf()
和toString()
方法将对象转换为原始值。
- 如果操作数具有相同的类型,则将它们进行如下比较:
String
:true
仅当两个操作数具有相同顺序的相同字符时才返回。Number
:true
仅当两个操作数具有相同的值时才返回。+0
并被-0
视为相同的值。如果任一操作数为NaN
,则返回false
。Boolean
:true
仅当操作数为两个true
或两个false
时才返回true
。
console.log("1" == 1); // true console.log(0 == false); // true console.log(0 == null); // false console.log(0 == undefined); // false console.log(null == undefined); // true const number1 = new Number(3); const number2 = new Number(3); console.log(number1 == 3); // true console.log(number1 == number2); // false,因为是两个不同的实例
全等操作符(===)与(!==)
全等运算符(
===
和 !==
)使用全等比较法来比较两个操作数:
- 如果操作数的类型不同,则返回
false
。 - 如果两个操作数都是对象,只有当它们指向同一个对象时才返回
true
。 - 如果两个操作数都为
null
,或者两个操作数都为undefined
,返回true
。 - 如果两个操作数有任意一个为
NaN
,返回false
。 - 否则,比较两个操作数的值:
- 数字类型必须拥有相同的数值。
+0
和-0
会被认为是相同的值。 - 字符串类型必须拥有相同顺序的相同字符。
- 布尔运算符必须同时为
true
或同时为false
。
- 数字类型必须拥有相同的数值。
console.log("3" === 3); // false console.log(true === 1); // false console.log(null === undefined); // false const object1 = { name: "hello" } const object2 = { name:"hello" } const object3 = object1; console.log(object1 === object2); // false console.log(object1 === object3); //true
区别
如果操作数的类型不同,==
运算符会在比较之前尝试将它们转换为相同的类型;而严格等于运算符不尝试类型转换,始终将不同类型的操作数视为不同。
关于NaN
NaN(Not a Number),表示不是一个数字。它不管与谁比较都返回false,即使是(NaN == NaN)结果也为false。通常,我们使用isNaN()或Number.isNaN()方法来判断一个值是否为NaN。其中,
- isNaN()在判断前会尝试将当前值强制转换为Number再进行判断;
- Number.isNaN()仅当值为NaN时才返回true。
手写实现isNaN()
利用NaN的“自身永不等于自身”这一特性来实现
var isNaN = function(value) { var n = Number(value); return n !== n; };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)