前言
JavaScript有八种基本数据类型,把它归纳为两大类,分别是原始类型(基本数据类型)和引用类型
原始类型
String:表示字符序列,可以用单引号、双引号或反引号括起来的文本。Number:表示双精度64位二进制格式的浮点数,可以表示整数和浮点数。特殊值包括NaN(Not a Number)和Infinity。Boolean:只有两个值:true和false,用于逻辑判断。Null:表示一个空的值或一个不存在的对象。null是一个特殊的关键字,它代表“无值”。Undefined:表示变量未初始化。一个变量声明后但未赋值时,它的默认值的undefined。Symbol:用于创建一个唯一且不可变的值,主要用于对象属性的唯一标识,避免属性名冲突。BigInt:用于表示任意精度的大整数,允许操作超过Number能表示范围的整数。
引用类型
Object(包括普通对象、数组、函数等)
两者区别
存储区别
- 原始类型存储在
栈(stack)中,值直接保存在变量访问的位置,由于其大小固定且频繁使用,存储在栈中具有更高的性能。 - 引用类型存储在
堆(heap)中,占用空间较大且大小不固定,变量保存的是对实际对象的引用(指针),这些引用存储在栈中。
赋值方式的区别
- 原始类型:复制的是
值本身。例如,将一个Number类型的变量赋值给另一个变量,两个变量互不影响。 - 引用类型:复制的是
引用(指针)。多个变量引用同一个对象时,一个变量的修改会影响其他变量(也就是我们常说的浅拷贝)。
扩展
类型检测
- 使用
typeof检查原始类型 - 使用
instanceof检查引用类型 - null是一个特殊情况,
typeof null返回"object",这是JavaScript早期实现的一个bug,但被保留下来了。
类型转换
- 自动类型转换:如数字与字符串
相加时,数字会被转换为字符串。 - 显示类型转换:使用
Number()、String()、Boolean()等函数将值转换为指定类型。
堆与栈区别
栈,内存分配效率高,自动管理(由编译器分配和释放)堆,内存分配灵活,但需要由开发者手动管理内存(通过垃圾回收机制)
JavaScript是弱类型语言
我们知道JavaScript是弱类型语言,JavaScript声明变量的时候并没有预先确定类型,变量的类型就是其值的类型,也就是说变量当前的类型由其值所决定,夸张点说就是,上一秒的String,下一秒就成为了Number类型,这个过程可能就进行了某些操作发生了强制类型转换。虽然弱类型语言的这种不需要预先确定的类型给我们带来了便利,但同时也会给我们带来困扰,为了充分利用该特性就必须掌握类型转换的规则。
接下来,我们进入类型转换部分吧~
类型转换
其他值到字符串的转换规则
基本数据类型到字符串的转换
1)Null和Undefined类型
null会转换为"null",undefined会转换为"undefined"
console.log(String(null)); //"null"
console.log(String(undefined)) //"undefined"
2)Boolean类型
true转换为"true",false转换为"false"
console.log(String(true)); //"true"
console.log(String(false)); //"false"
3)Number类型
数字直接转换为字符串,极小或极大的数字使用指数形式
console.log(String(4)); //"42"
console.log(String(3.14)); //"3.14"
console.log(String(1e21)); //"1e+21"
console.log(String(1 / 7)); //"0.14285714285714285"
4)Symbol类型
Symbol类型只能显示地转换为字符串,隐式转换会抛出错误
let sym = Symbol('desc');
console.log(String(sym)); //"Symbol(desc)"
console.log(sym.toString()); //"Symbol(desc)"
console.log(sym + ""); //TypeError:cannot convert a Symbol value to a string(不能将一个Symbol类型的值转换为String)
对象到字符串的转换
1)普通对象
如果对象没有toString()方法,会调用Object.prototype.toString()返回"[object Object]"。如果对象有自己的toString()方法,字符串化时会调用该方法并使用其返回值。
let obj = {};
console.log(String(obj)); //"[object Object]"
let objWithToString = {
toString() {
return "custom Object"
}
};
console.log(String(objWithToString)); //"custom Object"
2)数组对象
数组调用默认的toString()方法,会将数组元素转化为字符串并以逗号分隔
let arr = [1, 2, 3];
console.log(String(arr)); //"1,2,3"
3)日期对象
日期对象调用默认的toString()方法,会返回日期的字符串表示
let date = new Date();
console.log(String(date)); // "Wed Jun 28 2023 10:30:45 GMT+0200 (Central European Summer Time)"
4)函数对象
调用Function.prototype.toString(),返回函数的代码字符串
function foo() {
return "bar";
}
console.log(String(foo)) //"function foo(){ return "bar"; }"
其他值到数字值的转换规则
基本数据类型到数字的转换
1)undefined类型
undefined会转换为NaN
console.log(Number(undefined)); //NaN
2)Null类型
null会转换为0
console.log(Number(null)); //0
3)Boolean类型
true会转换为1,false转换为0
console.log(Number(true)); //1
console.log(Number(false)); //0
4)String类型
字符串按照Number()函数进行转换。如果字符串包含非法数字,转换为NaN,空字符串转换为0
console.log(Number("3.14")); //3.14
console.log(Number("38")); //38
console.log(Number("")); //0
console.log(Number("hello")); //NaN
console.log(Number("c4a8b")); //NaN
普通对象到数字的转换
对象(包含)数组会首先转换到相应的基本数据类型值,然后再根据基本数据类型值的转换规则进行强制类型转换,步骤如下:
- JavaScript尝试将对象转为基本类型的值。内部会首先检查该对象是否有
valueOf()方法。 - 如果该对象
有valueOf()方法并且该方法返回了基本类型的值,则使用该值进行强制类型转换。 - 如果
valueOf()方法不存在或者其返回值不是基本类型,则使用toString()方法的返回值进行转换。 - 如果
valueOf()和toString()方法均不返回基本类型的值,会产生TypeError错误。
let obj1 = {
valueOf() {
return 42;
};
}
console.log(Number(obj1)); //42
let obj2 = {
toString() {
return "3.14";
}
}
console.log(Number(obj2)); //3.14
//(上边输出是先拿到了toString()的返回值,也就是字符串"3.14",然后在转换为数字3.14)
let obj3 = {
valueOf() {
return {};
},
toString() {
return {};
}
}
console.log(Number(obj3)); //TypeError: Cannot convert object to primitive value
数组到数字的转换
数组在转换为数字时,会先转为字符串,然后再根据字符串的转换规则进行转换。如果数组包含多个元素,结果通常为NaN,因为转换后的字符串中含逗号分隔的元素
console.log(Number([1, 2, 3])) //NaN
console.log(Number([42])) //42
console.log(Number([])) //0
console.log(Number(["3.14"])) //3.14
其他值到布尔值的转换规则
大家只要记住以下值在转换为布尔值时会被转换为false:
- undefined
- null
- false
- +0
- -0
- 0
- NaN
- ""(空字符串)
console.log(Boolean(undefined)); // false
console.log(Boolean(null)); // false
console.log(Boolean(false)); // false
console.log(Boolean(0)); // false
console.log(Boolean(-0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean("")); // false
除了上述之外的所有值,在转换为布尔值时都会被转换为true。这包括:
- 非空字符串
- 非零数字(包括整数和负数)
- 对象(包括空对象)
- 数组(包括空数组)
- 函数
console.log(Boolean(undefined)); // false
console.log(Boolean(null)); // false
console.log(Boolean(false)); // false
console.log(Boolean(0)); // false
console.log(Boolean(-0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean("")); // false
了解完上边的数据类型及类型转换的规则后,接下来带大家复习下
typeof和instanceof这两个关键字。
typeof和instanceof的区别
typeof和instanceof是JavaScript中用于检测变量类型的两个关键字,但它们在使用场景和功能上有所不同。
typeof
功能:typeof操作符用于检测变量的类型,返回一个字符串,表示操作数和数据类型。
instanceof
功能:instanceof用于检测某个对象是否是另一个对象(构造函数)的实例,返回一个布尔类型的值。
使用场景如下:
- 用于
检测复杂类型,比如对象、数组、函数等 - 检测
某个对象是否继承自某个构造函数的原型链
两者区别
检测类型的范围:typeof主要用于检测基本数据类型以及函数、未定义类型和symbol,而instanceof主要用于检测对象的具体类型,检测某个对象是否是某个构造函数的实例。检测能力:typeof对基本数据类型非常有用,但对于复杂引用类型只会返回"object",而instanceof只能用于引用数据类型,不能用于检测基本数据类型。特殊情况:typeof null返回"object",这是一个JavaScript语言的历史遗留问题,而instanceof可以用来检测自定义对象的类型,通过检查原型链来确定实例的关系。
以上就是本篇的所有内容了,如果对你有一丁点帮助的话,都请点点赞支持一下哈哈,如有补充的也欢迎评论区留言讨论~