notes
  • Introduction
  • 语言
    • JS
      • JS原型到原型链
      • JS继承的实现
      • this对象
      • Promise基本概念
      • Promise实现
      • Promise实战
      • JS的EventLoop
      • JS容易出现误区的运算符
      • JS容易出现误区的操作符
      • JS深拷贝
      • JS节流与防抖
      • ES5实现原生/ES6方法
    • TS
      • 声明文件
      • 项目配置
    • CSS
      • CSS引入方式以及优先级计算
      • BFC神奇背后的原理-文摘
      • 回流reflow与重绘repaint
      • 三栏式布局
      • 垂直居中
      • 清除浮动的方法
      • 移动端适配方案
      • 纯CSS斜切角实现
      • CSS揭秘
      • 背景图片轮播
      • CSS绘制序列帧动画
      • transform实现一个多面体
    • HTML
  • ES6
  • Node.js
    • xxx
  • 前端框架
    • Vue.js
      • Vue双向数据绑定原理
      • Vue-Router原理及实现
    • React
    • AngularJS
  • 工程构建
    • Webpack
      • 01-webpack概述及背景
      • 03-webpack热更新原理
      • 04-splitChunks原理分析
      • 05-webpack工作流程
      • 07-webpack构建流程
      • 07-webpack构建流程
      • 10-webpack 如何进行性能分析
    • Gulp
    • Lint
      • ESLint
      • TSLint
    • Bable
  • 工程化
    • 模块化
    • 组件化
    • 规范化
      • 编码规范
    • 自动化
  • 运维
    • Nginx
    • GIT
    • CDN
    • VPS
    • DBA
  • 小程序
  • 跨端
  • 测试
  • 计算机技术
    • 计算机网络
      • 同源策略到前端跨域解决方案
      • TCP数据传输
      • TCP和UDP的区别
      • HTTP协议概述
      • HTTP缓存详解
      • HTTPS以及SSL建立过程
      • HTTPS的七个误解(译文)
      • cookie与Session机制区别以及Cookie SessionStorage LocalStorage异同
      • HTTP状态码Status
      • DNS原理入门
      • 网络攻击与防御
      • HTTP转发与重定向
      • 登录认证设计
    • 操作系统
      • shell脚本命令
    • Linux
      • Linux命令大全
      • vim命令
    • 浏览器
      • 浏览器内核、JS 引擎、页面呈现原理及其优化
      • 九种浏览器端缓存机制概览
      • 性能优化-网络请求方面
      • webkit解析CSS过程详解
  • 前端面试
    • 算法
Powered by GitBook
On this page
  • 浅拷贝
  • Object.assign
  • ...扩展运算符
  • 深复制
  • JSON的全局对象parse和stringify方法
  1. 语言
  2. JS

JS深拷贝

js对象是引用类型,对于=直接赋值的场景,复制的是存在栈内存里面的引用指针,并不是存放在堆内存中的内容,当对一个对象下面的属性值进行修改时,所有的都会变化。

/** 浅复制 **/
let person1 = {
  'name': 'Jack',
  'age': 29
};
let person2 = person1;
person2.name = "Kai";

console.log(person1.name);  //'Kai'
console.log(person2.name);  //'Kai'

浅拷贝

可以解决一般问题,如果对象只有一层,可以使用浅拷贝。以下几种方式可以实现浅拷贝:

  • Object.assign()

  • ...扩展运算符

Object.assign

let a = {
  age: 1,
};
let b = Object.assign({}, a);
a.age = 2;
console.log(b.age); // 1

...扩展运算符

let a = {
  age: 1,
};
let b = { ...a };
a.age = 2;
console.log(b.age); // 1

深复制

深复制想实现把对象里面属性值也给复制,当修改复制后的对象某个属性值时,原对象对应的属性值不会被修改。

有以下几种:

  1. JSON的全局对象parse和stringify方法(有限制)

  2. 遍历实现深度复制

JSON的全局对象parse和stringify方法

这种方法好处是非常简单易用,对于Number, String,Object等来说基本实现。但是坏处也显而易见,对于正则表达式类型、函数类型等无法进行深拷贝(而且会直接丢失相应的值)。还有一点不好的地方是它会抛弃对象的constructor,也就是深复制之后,无论这个对象原本的构造函数是什么,在深复制之后都会变成Object。

function deepClone(source){
  return JSON.parse(JSON.stringify(source));
}

let person1 = {
  'name': 'Jack',
  'age': 29,
  'fn':function (){
      console.log('fn')
  },
  'reg': new RegExp('e')
};

let person2 = deepClone(person1);
console.log(person1.name);  // 'Jack'
console.log(person2.name);  // 'Kai'
console.log(person2.fn);    // undefined
console.log(person2.reg);   // Object 

递归遍历实现深复制

通过遍历到对象的每一层,实现深度复制,对引用类型中的function,reg,Date特殊处理。推荐使用

function deepClone(obj, c) {
  let newObj = c || {}
  for (let i in obj) {
    // 引用类型拷贝
    if (obj[i] instanceof Object) {
      if (obj[i] instanceof Function) {
        // function
        newObj[i] = function () {
          return obj[i].call(this, ...arguments);
        }
      } else if (obj[i] instanceof RegExp) {
        // reg
        newObj[i] = new RegExp(obj[i]);
      } else if (obj[i] instanceof Date) {
        // Date
        newObj[i] = new Date(obj[i]);
      } else {
        // 普通对象和数组
        newObj[i] = obj[i] instanceof Array ? [] : {};
        deepClone(obj[i], newObj[i]);
      }
    } else {
      // 普通类型拷贝
      newObj[i] = obj[i];
    }
  }
  return newObj;
}
PreviousJS容易出现误区的操作符NextJS节流与防抖

Last updated 3 years ago