基本概念
JS有以下这些数据类型:undefined
、null
、string
、boolean
、number
、symbol
、bigint
、object
。
其中,前面 7 个被称为基本类型
,又叫原始类型
(Primitive Type
);
object
,被称为引用类型
(Reference Type
),或叫做对象类型
(Object Type
)。
区别
基本类型在栈
中存储,而引用类型对象部分在堆
中存储,栈
中存储的对象的引用地址
。
let str = 'hello world';
let num = 123;
let obj1 = {a: 1, b: 2};
let obj2 = obj1;
let arr = [1, 2, 3];
它们的存储如下图:
基本类型的值是不可变
的,向基本类型变量赋值时,实际是赋予它一个新值,而不是改变旧值。因此原始类型
这个表述可能更贴切,原始
就是不可再分,无法修改的意思。
let str = 'hello wrold';
str = 'hello'; // 将'hello'赋值给str,而非将'hello world'修改成'hello'
引用类型往往由基本类型或其他对象组成,它是可变
的。
修改对象的值:
let obj1 = {a: 1, b: 2};
obj1.c = 3;
console.log(obj1); // {a: 1, b: 2, c: 3}
let arr = [1, 2, 3];
arr.push(4);
console.log(arr); // [1, 2, 3, 4]
注意,这里我们说的
可变
和不可变
,都是针对值
的,而不是针对变量,变量是可变的。
在传参方面,基本类型是值传递
,引用类型是引用传递
。
let str = 'hello world';
(function(str) { str = 'hello';})(str);
console.log(str); // 'hello world'
let obj = {a: 1, b: 2};
(function(obj) { obj.c = 3;})(obj);
console.log(obj ); // {a: 1, b: 2, c: 3}
在值的相等比较上,要区分是严格相等(===
),还是宽松相等(==
)。
对于严格相等,基本类型比较值是否相等,而引用类型比较引用地址是否相等(是否视同一个对象)。
对于宽松相等,不管是基本类型,还是引用类型,或者基本类型和引用类型比较,它们都是比较值,这中间可能伴随着类型转化
。感兴趣可以看我的另一篇文章,js 类型转换保姆级讲解。
对于类型检查,基本类型使用typeof
,有个特例,typeof null
结果为object
,需要注意一下。引用类型使用instanceof
。
总结
对比项 | 基本类型 | 引用类型 |
---|---|---|
存储 | 栈 | 引用存在栈 ,值存在堆 |
是否可变 | 不可变 | 可变 |
传递类型 | 值传递 | 引用传递 |
比较 | 比较值 | 严格相等比较引用地址 ,宽松相等比较值 |
类型检查 | typeof | instanceof |