阅读 203

JavaScript对象的底层数据结构是什么

上一篇文章归纳了javascript的数据类型,归根到底数据类型就分为两类,一种是基础类型,一种是引用类型。如果还没有看的同学这里附上超链接《JavaScript规定了几种语言类型

基本类型

  • 内容:StringNumberBooleanUndefinedNullSymbolBigInt
  • 特点:值不可变,无属性无方法,保存在栈内存中、值比较。

String是一个特殊的基本类型,可以被当成引用类型使用

let a = 'strObject';
a = a.substring(3,9);
console.log(a); // Object
复制代码

引用类型

  • 内容:除了上面的 7 种基本数据类型外,剩下的就是引用类型,统称为Object类型
  • 特点:引用类型的值同时保存在栈内存和堆内存中的对象。栈区内存保存变量标识符,堆内存存储对象的地址

ps:差异:基本类型的值是不可变的,比较是值的比较,引用类型的值是可变的,比较是引用的比较;

const a = '我是a';
let b = a;
console.log(a===b); // true
b = '我现在改了';
console.log(a); // 我是a
console.log(b); // 我现在改了
console.log(a===b); // false
/** =================== **/
const c = {
	name: '张三'
}
const d = c;
const e = {name: '李四'}
d.name = '李四';
console.log(c); // {name: "李四"},引用类型的赋值其实是对象保存在栈区地址指针的赋值,因此两个变量指向同一个对象,任何的操作都会相互影响。
console.log(d); // {name: "李四"}
console.log(e); // {name: "李四"}
console.log(c===d); // true
console.log(d===e); // false,虽然看起来相同,但是两个对象存在堆内存的地址是不相同的,所以返回的是false;
复制代码

现在我们来了解下什么是堆,什么又是栈。

堆(heap)

  • 堆内存的简称,动态分配内存,内存大小不一,不是自动释放。
  • 队列优先,先进先出,方便存储和开辟内存空间。

栈(stack)

  • 栈内存的简称,自动分配相对固定大小的内存空间,并由系统自动释放。基本类型存储在栈内存的好处就是,内存可以及时的得到回收。
  • 线性结构,后进先出,便于管理。

ps:看完堆和栈的简单介绍,我们再来看下对于数据结构相关的一个问题浅拷贝和深拷贝

浅拷贝

只复制了第一层属性,复制对象是基本类型。

// 浅拷贝的方法
const a = {
	name: '张三'
}
// Object.assign或=
const b = Object.assign(a);// {name: '张三'}
b.name = '李四';
console.log(a.name); // 李四
const c = b;
c.name = '王五'
console.log(a.name); // 王五
console.log(b.name); // 王五
复制代码

深拷贝

对属性中所有引用类型的值,遍历到是基本类型的值为止,利用递归来实现深拷贝。

// Object.assign和扩展符针对对象值都是基本类型
const a = {
	name: '张三';
}
const b = Object.assign({}, a); // 或者{...a}
b.name = '李四';
console.log(a.name);// 张三
// 递归循环
function clone(obj){
    let _obj = Array.isArray(obj) ? [] : {};
    if(obj && typeof obj === "object"){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                // 判断obj子元素是否为对象,如果是,递归复制
                if(obj[key] && typeof obj[key] === "object"){
                    _obj[key] = clone(obj[key]);
                } else {
                    // 如果不是,简单复制
                    _obj[key] = obj[key];
                }
            }
        }
    }
    return _obj;
};
const c = clone(a);
c.name = '王五';
console.log(a.name); // 张三
复制代码

结尾附上一个有趣的问题typeof(null),打印出来的是object,原因JavaScript中的数据在底层是以二进制存储,比如null所有存储值都是0,但是底层的判断机制,只要前三位为0,就会判定为object

ps:文末附上汇总文章链接《一名【合格】前端工程师的自检清单【持续更新】

文章分类
前端
文章标签