面试题:了解对象在内存中的储存原理,深拷贝,浅拷贝,js的预解析与执行的过程

110 阅读3分钟

1.对象在内存中的储存原理

答:对象的数据储存在内存中的堆区中,同时在栈区存放数据在堆区的地址(引用)

2.深拷贝,浅拷贝

概念

深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。

浅拷贝

浅拷贝:只拷贝了对象的引用(内存地址), 当原对象发生了改变, 新对象也跟着发生改变, 因为它们都是指向了同一个对象

 var money = {
  bank:'平安银行',
  count: 1000000
}

var money2 = money;
money.count = 100;
console.log(money2.count); //100

深拷贝

深拷贝:在计算机中开辟一块新的内存地址用于存放复制的对象。

注:三点运算符(例:...obj)也只能深拷贝一层,要想完全拷贝,还是要递归穷尽

//实现深拷贝的两种方法
var obj = {
            name: 'wqr',
            age: 18,
            a: null,
            info: {
                height: 175,
                money: {
                    name: '建设',
                    count: 1000,
                }
            }
        }

        // 第一种方法递归穷尽
        var newObj = {};
        for (v in obj) {
            if (obj[v] && typeof obj[v] === 'object') {
                newObj[v] = {}
                for (v2 in obj[v]) {
                    newObj[v][v2] = obj[v][v2]
                }

            } else {
                newObj[v] = obj[v]
            }
        }
        obj.info.height = 170;
        console.log(newObj.info.height);

        // 封装为函数
        function getNewObj(obj) {
            var newData = {};
            for (v in obj) {
                if (obj[v] && typeof obj[v] === 'object') { //obj[v] 防止为null,因为typeof null 为object
                    // 递归穷尽
                    newData[v] = getNewObj(obj[v]);
                } else {
                    newData[v] = obj[v];
                }
            }

            return newData
        }
        var n = getNewObj(obj);
        obj.info.money.count = 1111111111111;
        console.log(n.info.money.count);
        console.log(obj);
        console.log(n);

        // 第二种方法:利用JSON的方法
        var jsonStr = JSON.stringify(obj);
        var o = JSON.parse(jsonStr);
        obj.info.money.name = 'PINGAN'
        console.log(obj);
        console.log(o);

3.js的预解析与执行的过程

概念

预解析:程序在执行过程,会先将代码读取到内存中检查,会将所有的声明在此处进行标记,所谓的标记就是让js解析器知道这个名字,后面在使用这个名字的时候,不会出现未定义的错误,‘这个标记过程就是提升。

一,全局代码处理过程

预解析阶段

  1. 先函数提升再变量提升
    1. 函数声明有冲突,会覆盖
    2. 变量声明有冲突,会忽略
  2. 变量的提升
    1. 变量的名字提升
    2. 变量并没有任何数据与之对应,所以为undefined
  3. 函数的提升
    1. 首先告诉解析器有这个函数名字的存在,该阶段与变量的名字声明一致
    2. 然后告诉解析器这个名字连接的函数体
  4. 将找到的函数和变量保存到一个对象中(全局的保存到window对象中)
  5. 变量的值是undefined,函数的值则指向该函数

运行阶段

从上至下,顺序执行

二,函数处理过程

预解析阶段

  1. 将函数的参数添加到对象中
  2. 先函数提升再变量提升
    1. 函数声明有冲突,会覆盖
    2. 变量声明有冲突,会忽略
  3. 变量的提升
    1. 变量的名字提升
    2. 变量并没有任何数据与之对应,所以为undefined
  4. 函数的提升
    1. 首先告诉解析器有这个函数名字的存在,该阶段与变量的名字声明一致
    2. 然后告诉解析器这个名字连接的函数体
  5. 将找到的函数和变量保存到一个对象中(全局的保存到window对象中)
  6. 变量的值是undefined,函数的值则指向该函数

运行阶段

从上至下,顺序执行