堆栈,深拷贝以及浅拷贝

550 阅读3分钟

1 js中的变量有哪几种类型

  • 基本类型: number, string, null(特殊), undefined, boolean, Symbol, ES10 BigInt(任意精度整数)
  • 引用类型: Array, Function, data, RegExp

1.1 栈内存

主要用于存放基本类型和对象变量的指针,给人的感觉就像一个线性排列的空间,每个小单元大小基本相等,存放的变量一般都是已知大小或者已知上限范围的,算是一种简单的存储

栈内存自动分配相对固定大小的内存空间,并由系统自动释放

数据在栈内存中的存储与使用方式类似于数据结构中的堆栈数据结构,遵循 先进后出 的原则。

队列是先进先出

1.2 堆内存

主要用于存放引用类型诸如object这类,存储的对象类型数据对于大小在这方面是未知的(所以这大概也是为什么null作为一个object类型的变量却存储在栈内存的原因)

堆内存是动态分配内存,内存大小不一,也不会自动释放

浅拷贝和深拷贝

深拷贝和浅拷贝的区别

如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。

浅拷贝

 var obj = { a: 1, arr: [2, 3] };
  var shallowObj = Object.assign({}, obj);
  shallowObj.arr[1] = 0;
  shallowObj.a = 'yanbo';
  console.log(obj, 'obj');
  console.log(shallowObj, 'shallowObj');

深拷贝

// 深拷贝    // 获取类型    
function getType(obj) {
      var toString = Object.prototype.toString;
      var map = {
        '[object Boolean]': 'boolean',
        '[object Number]': 'number',
        '[object String]': 'string',
        '[object Null]': 'null',
        '[object Undefined]': 'undefined',
        '[object Array]': 'array',
        '[object Function]': 'function',
        '[object RegExp]': 'regExp',
        '[object Date]': 'date',
        '[object Object]': 'object'
      }
      if (obj instanceof Element) { 
// 因为对不同标签,toString会返回对应不同标签的构造函数
        return 'element';
      }
      return map[toString.call(obj)];
    }
    function deepClone(data) {
      var type = getType(data)
      var obj;
      if (type === 'array') {
       obj = []
        for (var i = 0; i < data.length; i++) {
          obj.push(deepClone(data[i]))
        }
      } else if (type === 'object') {
        obj = {}
        for (var key in data) {
          obj[key] = deepClone(data[key]);
        }
      } else {
        obj = data;
      }
      return obj;
    }
    var oldObj = {
      a: 1,
      b: 2
    }
    const newObj = deepClone(oldObj);
    const newObj1 = newObj.c = 4;
    console.log(oldObj, newObj)
    let oldData = [1, 2, 3, 4, 4];
    const newData = deepClone(oldData);
    const newData1 = newData.push({ a: 4, b: 7 });
    console.log(newData, '--->newData', oldData, '---->oldData');

第二种深拷贝

JSON.parse(JSON.stringify(obj))我们一般用来深拷贝,其过程说白了 就是利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象;序列化的作用是存储(对象本身存储的只是一个地址映射,如果断电,对象将不复存在,因此需将对象的内容转换成字符串的形式再保存在磁盘上 )和传输(例如 如果请求的Content-Type是 application/x-www-form-urlencoded,则前端这边需要使用qs.stringify(data)来序列化参数再传给后端,否则后端接受不到; ps: Content-Type 为 application/json;charset=UTF-8或者 multipart/form-data 则可以不需要 )。

1、如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象;

  var a = {
    name: 'aaa',
    date: [new Date(1536627600000), new Date(1540047600000)]
  }
  let b;
  b = JSON.parse(JSON.stringify(a))
  console.log(a);
  console.log(b);

image.png

2、如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象;

  const test = {
    name: 'a',
    date: new RegExp('\\w+'),
  };
  // debugger
  const copyed = JSON.parse(JSON.stringify(test));
  test.name = 'test'
  console.log(test);
  console.log(copyed);
  console.error('ddd', test, copyed)

3、如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;

  const test = {
    name: 'aaa',
    date: function hello() {
      console.log('ffff');
    }
  }
  const copy = JSON.parse(JSON.stringify(test));
  test.name = 'js';
  console.log(test)
  console.log(copy);

image.png

4、如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null

image.png