目录
- const obj = {
- name: 'star',
- age: 18,
- friend: {
- name: 'coder'
- }
- };
-
- // 浅拷贝
- const info = Object.assign({}, obj);
- console.log(info); // { name: 'star', age: 18, friend: { name: 'coder' } }
-
- // 修改引用类型数据,同时会更改
- obj.friend.name = '123';
- console.log(info); // { name: 'star', age: 18, friend: { name: '123' } }
-
-
- const obj = {
- name: 'star',
- age: 18,
- friend: {
- name: 'coder'
- }
- };
-
- // 浅拷贝
- const info = { ...obj };
- console.log(info); // { name: 'star', age: 18, friend: { name: 'coder' } }
-
- // 修改引用类型数据,同时会更改
- obj.friend.name = '123';
- console.log(info); // { name: 'star', age: 18, friend: { name: '123' } }
- const arr = [1, { name: 'coder' }, '4'];
-
- // 浅拷贝
- const info = [].concat.call(arr, [{ age: 18 }]);
- // const info = Array.prototype.concat.call(arr, [{ age: 18 }]);
-
- console.log(info); //[ 1, { name: 'coder' }, '4', { age: 18 } ]
-
- // 修改引用类型数据,同时会更改
- arr[1].name = '123';
- console.log(info); // [ 1, { name: '123' }, '4', { age: 18 } ]
- const arr = [1, 2, { name: 'coder' }, '4'];
-
- // 浅拷贝
- const info = [].slice.call(arr);
- // const info = [].slice.call(arr, 0);
- // const info = [].slice.call(arr, 0, 4);
- // const info = Array.prototype.slice.call(arr);
-
- console.log(info); // [ 1, 2, { name: 'coder' }, '4' ]
-
- // 修改引用类型数据,同时会更改
- arr[2].name = '123';
- console.log(info); // [ 1, 2, { name: '123' }, '4' ]
- // 判断一个标识符是否是对象类型
- function isObject(value) {
- const valueType = typeof value;
- return value !== null && (valueType === 'object' || valueType === 'function');
- }
- const obj = {
- name: 'star',
- age: 18,
- friend: {
- name: 'coder',
- arr: [1, 2, 3, 4]
- }
- };
-
- // 深拷贝
- const info = JSON.parse(JSON.stringify(obj));
- console.log(info);
-
- // 修改原来属性,不会影响新创建的对象
- obj.friend.name = '123';
-
- console.log(info);
缺点 :
1. function 不会被转化,直接忽略掉了
2. symbal 不会被转化,直接忽略掉了
3. 存在undefined、NaN 之类情况会转化错误
4. 存在循环引用的情况直接报错
- function isObject(value) {
- const valueType = typeof value;
- return value !== null && (valueType === 'object' || valueType === 'function');
- }
-
- function deepCopy(originValue) {
- // 1. 如果不是引用类型,直接返回
- if (!isObject(originValue)) {
- return originValue;
- }
- // 2. 创建新对象
- const newObj = {};
- for (const key in originValue) {
- // 3. 赋值的时候,进行递归
- newObj[key] = deepCopy(originValue[key]);
- }
- // 4. 返回新对象
- return newObj;
- }
-
- const obj = {
- name: 'star',
- age: 18,
- friend: {
- name: 'coder'
- }
- };
-
- // 深拷贝
- const info = deepCopy(obj);
- console.log(info);
-
- // 修改原来属性,不会影响新创建的对象
- obj.friend.name = '123';
-
- console.log(info);
- function isObject(value) {
- const valueType = typeof value;
- return value !== null && (valueType === 'object' || valueType === 'function');
- }
-
- function deepCopy(originValue) {
- // 1. 如果不是引用类型,直接返回
- if (!isObject(originValue)) {
- return originValue;
- }
- // 2. 创建新对象 | 数组
- const newObj = Array.isArray(originValue) ? [] : {};
- for (const key in originValue) {
- // 3. 赋值的时候,进行递归
- newObj[key] = deepCopy(originValue[key]);
- }
- // 4. 返回新对象
- return newObj;
- }
-
- const obj = {
- name: 'star',
- age: 18,
- friend: {
- name: 'coder',
- info: [1, 2, 3, 4, 5]
- }
- };
-
- // 深拷贝
- const info = deepCopy(obj);
- console.log(info);
- obj.age = 20;
- console.log(info);
- function isObject(value) {
- const valueType = typeof value;
- return value !== null && (valueType === 'object' || valueType === 'function');
- }
-
- // 深拷贝函数
- function deepCopy(originValue) {
- /**
- * 值是 symbol数据类型
- * 需写在基本数据类型之前,否则会被返回错误
- */
- if (typeof originValue === 'symbol') {
- return Symbol(originValue.description);
- }
- /**
- * 基本数据类型,直接返回
- */
- if (!isObject(originValue)) {
- return originValue;
- }
- /**
- * 函数类型
- * 不需要拷贝,直接返回
- */
- if (typeof originValue === 'function') {
- return originValue;
- }
- /**
- * set类型
- * 因为set类型不能被for...in,所以单独处理
- */
- if (originValue instanceof Set) {
- const newSet = new Set();
- for (const item of originValue) {
- newSet.add(deepCopy(item));
- }
- return newSet;
- }
- /**
- * map类型
- * 因为set类型不能被for...in,所以单独处理
- */
- if (originValue instanceof Map) {
- const newMap = new Map();
- for (const [key, value] of originValue) {
- newMap.set(deepCopy(key), deepCopy(value));
- }
- return newMap;
- }
- /**
- * 对象,数组类型
- */
- const newObj = Array.isArray(originValue) ? [] : {};
- // one - 遍历普通的key
- for (const key in originValue) {
- newObj[key] = deepCopy(originValue[key]);
- }
- // two - 遍历Symbol的key
- const symbolKeys = Object.getOwnPropertySymbols(originValue);
- for (const symbolKey of symbolKeys) {
- newObj[Symbol(symbolKey.description)] = deepCopy(originValue[symbolKey]);
- }
- // 4. 返回新对象 | 数组
- return newObj;
- }
-
- const symbolKey = Symbol('key是Symbol');
- const obj = {
- name: 'star',
- age: 18,
- friend: {
- name: 'coder',
- info: [1, 2, 3, 4, 5]
- },
- play() {
- console.log('playing!');
- },
- set: new Set([1, 22, 3]),
- map: new Map([
- [{ name: 5 }, 5],
- [6, { name: 6 }]
- ]),
- [symbolKey]: 'key是Symbol',
- symbolValue: Symbol('value是Symbol')
- };
-
- // 深拷贝
- const info = deepCopy(obj);
- console.log(info);
- function isObject(value) {
- const valueType = typeof value;
- return value !== null && (valueType === 'object' || valueType === 'function');
- }
-
- /**
- * 循环引用解决方案 :
- * 拷贝过的对象,不需要再次拷贝,直接返回即可
- * 1. 使用 WeakMap 进行弱引用,用来判断是否拷贝过
- * 2. 使用同一个 WeakMap
- */
- function deepCopy(originValue, map = new WeakMap()) {
- if (typeof originValue === 'symbol') {
- return Symbol(originValue.description);
- }
-
- if (!isObject(originValue)) {
- return originValue;
- }
-
- if (typeof originValue === 'function') {
- return originValue;
- }
-
- if (originValue instanceof Set) {
- const newSet = new Set();
- for (const item of originValue) {
- // 为了使得使用的 map 都为同一个,调用时把map传入,使得map 都为最开始创建的那一个
- newSet.add(deepCopy(item, map));
- }
- return newSet;
- }
-
- if (originValue instanceof Map) {
- const newMap = new Map();
- for (const [key, value] of originValue) {
- // 为了使得使用的 map 都为同一个,调用时把map传入,使得map 都为最开始创建的那一个
- newMap.set(deepCopy(key, map), deepCopy(value, map));
- }
- return newMap;
- }
-
- /**
- * 每次创建对象前,判断map中是否已经拥有了 => 即是否已经拷贝过了
- * 如果有,直接返回以前创建的对象
- */
- if (map.get(originValue)) {
- return map.get(originValue);
- }
- const newObj = Array.isArray(originValue) ? [] : {};
- /**
- * 1. 每次创建新对象后,推入 WeakMap 中,用来保存
- * 2. 当前的对象的地址作为 key ,值为新创建出来的对象
- */
- map.set(originValue, newObj);
-
- for (const key in originValue) {
- // 为了使得使用的 map 都为同一个,调用时把map传入,使得map 都为最开始创建的那一个
- newObj[key] = deepCopy(originValue[key], map);
- }
- const symbolKeys = Object.getOwnPropertySymbols(originValue);
- for (const symbolKey of symbolKeys) {
- // 为了使得使用的 map 都为同一个,调用时把map传入,使得map 都为最开始创建的那一个
- newObj[Symbol(symbolKey.description)] = deepCopy(originValue[symbolKey], map);
- }
- return newObj;
- }
-
- const symbolKey = Symbol('key是Symbol');
- const obj = {
- name: 'star',
- age: 18,
- friend: {
- name: 'coder',
- info: [1, 2, 3, 4, 5]
- }
- };
- // 自己引用自己
- obj.obj = obj;
-
- // 深拷贝
- const info = deepCopy(obj);
- console.log(info);
- // 判断一个值是否是对象类型
- function isObject(value) {
- const valueType = typeof value;
- return value !== null && (valueType === 'object' || valueType === 'function');
- }
- // 深拷贝函数
- function deepCopy(originValue, map = new WeakMap()) {
- if (typeof originValue === 'symbol') {
- return Symbol(originValue.description);
- }
- if (!isObject(originValue)) {
- return originValue;
- }
- if (typeof originValue === 'function') {
- return originValue;
- }
- if (originValue instanceof Set) {
- const newSet = new Set();
- for (const item of originValue) {
- newSet.add(deepCopy(item, map));
- }
- return newSet;
- }
- if (originValue instanceof Map) {
- const newMap = new Map();
- for (const [key, value] of originValue) {
- newMap.set(deepCopy(key, map), deepCopy(value, map));
- }
- return newMap;
- }
-
- if (map.get(originValue)) {
- return map.get(originValue);
- }
- const newObj = Array.isArray(originValue) ? [] : {};
- map.set(originValue, newObj);
- for (const key in originValue) {
- newObj[key] = deepCopy(originValue[key], map);
- }
- const symbolKeys = Object.getOwnPropertySymbols(originValue);
- for (const symbolKey of symbolKeys) {
- newObj[Symbol(symbolKey.description)] = deepCopy(originValue[symbolKey], map);
- }
- return newObj;
- }