现象
有人问,为什么null === null 输出值true,但是[ null ] === [ null ]输出值却是false?
那么,
先来展示几个代码,看看你认为的输出值,是不是正确的
console.log('null log:',null == null); // true
console.log('null array log:',[] === []); // false
console.log('null object log:',{
} === {
}); // false
console.log('array log:', ['1']=== ['1']); // false
console.log('object log:',{
name: 'look'} === {
name: 'look'}); // false
const array1 = ['item'];
const array2 = ['item1', 'item'];
console.log('array item log:', array1[0]=== array2[1]); // true
const object1 = {
name: 'look'};
const object2 = {
name: 'look'};
console.log('object key log:', object1.name === object2.name); // true
原因
如上可知,如论是空的数组还是空的对象,或者有值的数组或对象,使用 === 的时候,都是输出的false。
发挥一下思维,数组和对象在javaScript中,广义的都被称为object,想不明白的话,输出一下
console.log(typeof({
}))
console.log(typeof({
}))
还不明白吗?
栈 stack 和 堆 heap
栈(stack):
- 先进后出;
- 自动分配内存空间;
- 由系统自动释放;
- 使用的是一级缓存,他们通常都是被调用时处于存储空间中,调用完立即释放。
堆(heap):队列优先
- 先进先出;
- 动态分配内存,大小不定也不会自动释放;
- 存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定;一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。
数据类型:(7种)
存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配。
Undefined / Null / Boolean / Number / String,它们是直接按值存放的,可以直接访问。
Object/Symbol,当我们需要访问引用数据类型 (对象 / 数组 / 函数) 的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。
- 对象(Object):表示复杂的数据结构,可以包含其他数据类型和对象,例如数组、函数、日期等
- Symbol:ES6 新增的一种数据类型,表示独一无二的值,通常用于对象的属性名。
变量a实际保存的是指向堆内存中对象的一个指针,而b保存的是指向堆内存中另一个对象的一个指针;虽然这两个对象的值是一样的,但它们是独立的2个对象,占了2份内存空间;所以 ab 为 false。
如果 var a = {}; var b = a; 这时变量b复制了变量a保存的指针,它们都指向堆内存中同一个对象;所以 ab 为 true。
到这里问题已经解决了,但我们需要深入学习一下;
传值与传址?
基本类型与引用类型最大的区别实际就是 传值与传址的区别。
var a = [1,2,3,4,5];
var b = a;
var c = a[0];
console.log(b); // [1,2,3,4,5]
console.log(c); // 1
b[4] = 6;
c = 7;
console.log(a[4]); //6
console.log(a[0]); //1
从上面代码可以得知,当改变b中的数据时,a也发生了变化;但是当我们改变c的数值时,a却没有发生改变。
这就是传值与传址的区别。因为a是数组,属于引用类型,所以a给b传的是栈中的地址,而不是堆内存中的对象。而c仅仅是从a堆内存中获取的一个数值,并保存在栈中。所以b修改的时候,会根据地址回到a堆内存中修改;c则直接在栈中修改,并且不能指向a堆内存中。
const one = 1;
const two;
if ( one ) {
two = one;
} else {
two = "222";
}
return two;
寄语
知其然,知其所以然