一次对JS数据存储的总结

159 阅读3分钟

 一. JS数据类型

  1. Number
  2. String
  3. Boolean
  4. Object
  5. Null
  6. Undefined
  7. Array
  8. Symbol

   基本数据类型 : String, Number, Boolean, Null, Undefined,Symbol

   引用数据类型 : Object,Array

二. 数据存储

         对于基本数据类型存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配,是直接按值存放的。

        对于引用类型object),堆内存中存储其值,栈内存中存储其值在堆内存中的指针。每个空间大小不一样,要根据情况进行特定的分配 。

             


三. 赋值与深拷贝与浅拷贝

  •  赋值:

        在对对象赋值的过程中,我们赋予的是指针地址。在进行ObjectA = ObjectB后,ObjectA与ObjectB共同指向了相同的堆内存地址。无论是ObjectA 还是ObjectB进行了任何修改,另外一个也会相对应的更改。

let a = {    'name' : 'xiaowang',    'age' : 20}let b = ab.name = 'laowang'console.log(a);console.log(b);// { name: 'laowang', age: 20 }
// { name: 'laowang', age: 20 }

  • 浅拷贝

         创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。即默认拷贝构造函数只是对对象进行浅拷贝复制(逐个成员依次拷贝),即只复制对象空间而不复制资源。

  • 深拷贝

       深拷贝后的两个对象拥有一样的资源内容,但完全指向两个不同的内存地址。深拷贝后的对象再无任何关联。

四. 实现浅拷贝

// 浅拷贝let objA = {  'name' : '小明',  'age' : 18,  'house' : [1,2,3,4,5,6]}function shallowCopy(param){   let result = {}   for (const key in param) {     if (param.hasOwnProperty(key)) {       result[key] = param[key]     }   }   return result}let result = shallowCopy(objA)result.house[0] = 0console.log(result);console.log(objA);
// { name: '小明', age: 18, house: [ 0, 2, 3, 4, 5, 6 ] }
// { name: '小明', age: 18, house: [ 0, 2, 3, 4, 5, 6 ] }

   

五. 实现深拷贝

// 深拷贝    //定义检测数据类型的功能函数    function checkedType(target) {      return Object.prototype.toString.call(target).slice(8, -1)    }    //实现深度克隆---对象/数组    function clone(target) {      //判断拷贝的数据类型      //初始化变量result 成为最终克隆的数据      let result, targetType = checkedType(target)      if (targetType === 'Object') {        result = {}      } else if (targetType === 'Array') {        result = []      } else {        return target      }      //遍历目标数据      for (let i in target) {        //获取遍历数据结构的每一项值。        let value = target[i]        //判断目标结构里的每一值是否存在对象/数组        if (checkedType(value) === 'Object' ||          checkedType(value) === 'Array') { //对象/数组里嵌套了对象/数组          //继续遍历获取到value值          result[i] = clone(value)        } else { //获取到value值是基本的数据类型或者是函数。          result[i] = value;        }      }      return result    }

很简单,主要是进行递归循环将判断为Object以及Array类型的字段继续深拷贝。

六. 总结思考

      了解了JS对于引用类型数据的存储方式后很多面试题都可以游刃有余。例如:

let arr = new Array(10000000),那么读取arr[0]跟arr[9999999]的速度一样吗?

答案肯定是一样的。