xgqfrms / learning-javascript-with-mdn

Learning JavaScript with MDN / 使用 MDN 学习 JavaScript
https://learning-javascript-with-mdn.xgqfrms.xyz
MIT License
1 stars 0 forks source link

06. shallow copy & deep copy #6

Open xgqfrms opened 5 years ago

xgqfrms commented 5 years ago

shallow copy & deep copy

js 浅拷贝和深拷贝

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

https://repl.it/@xgqfrms/shallow-copy-and-deep-copy

updates, 2023.02.20

js data types

image

基本数据类型:(栈)

7种基本数据类型 Undefined、Null、Boolean、Number 和 String,Symbol, BigInt; 变量是直接按值存放的; 存放在栈内存中的简单数据段,可以直接访问;

引用数据类型:(堆)

Array, Object, Function, Date, Math, RegExp, ...

TypedArray: Uint8Array, Int8Array, ... DataView, ArrayBuffer, ...

Map, Set, WeakMap, WeakSet, Intl, ... Reflect, Proxy, ...

存放在堆内存中的对象,变量保存的是一个指针,这个指针指向另一个位置; 当需要访问引用类型(如对象,数组等)的值时,首先从栈中获得该对象的指针地址, 然后再从堆内存中取得所需的数据;

JavaScript 存储对象都是存的内存地址;

所以浅拷贝会导致 obj1 和obj2 指向同一块内存地址; 改变了其中一方的内容,都是在原来的内存上做修改会导致拷贝对象和源对象都发生改变;

深拷贝是开辟一块新的内存地址,将原对象的各个属性逐个复制进去, 对拷贝对象和源对象各自的操作互不影响;

const origin = {
  num: 1,
  arr: [2012, 2023],
  func: (v) => console.log(v),
  obj: {msg: 'bug'},
  date: new Date(`2012-01-01`),
  u: undefined,
  nil: null,
  nan: NaN,
  bool: true,
  str: 'string',
  s: Symbol(`s`),
  bi: BigInt(10**32),
  set: new Set([1, 2, 3]),
  map: new Map([['a', 11], ['b', 22], ['c', 33]]),
  // reg: /^0+/g,
  reg: new RegExp(/^0+/g),
};

image

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects

xgqfrms commented 5 years ago

solutions

shallow copy

  1. re-assignment

  2. Object.assign()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

  1. Array.slice()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice

  1. Array.from()

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2019-08-29
 * @modified
 *
 * @description 数组(深拷贝 / 浅拷贝) shallow-copy deep-copy
 * @augments
 * @example
 * @link
 *
 */

let log = console.log;

const shallowCopy = () => {
    const arr = [1, 2, 3];
    const arrNested = [[1, 2, 3], {key: "value"}];
    let arrShallowCopy = arr;
    let arrNestedShallowCopy = arrNested;
    log(`arr =`, arr);
    log(`arrNested =`, arrNested);
    log(`arrShallowCopy =`, arrShallowCopy);
    log(`arrNestedShallowCopy =`, arrNestedShallowCopy);
    // compare to pointer
    log(`shallowCopy`, arrShallowCopy === arr);
    log(`shallowCopy Nested`, arrNestedShallowCopy === arrNested);
    // modify arr
    arr[0] = "A";
    log(`arr =`, arr);
    log(`arrShallowCopy =`, arrShallowCopy);
    // modify arr copy
    arrNestedShallowCopy[1] = ["a", "b", "c"];
    log(`arrNested =`, arrNested);
    log(`arrNestedShallowCopy =`, arrNestedShallowCopy);
};

shallowCopy();
// true
// true

// [ 'A', 2, 3 ]
// [ 'A', 2, 3 ]

// [ [ 1, 2, 3 ], [ 'a', 'b', 'c' ] ]
// [ [ 1, 2, 3 ], [ 'a', 'b', 'c' ] ]

deep copy

  1. JSON.parse(JSON.stringify());
  1. recursive & Array.map() & Array.isArray()
const clone = (items) => items.map(item => Array.isArray(item) ? clone(item) : item);
  1. recursive object properties

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

// hasOwnProperty
// Object.keys() & own enumerable property 
  1. recursive & Array.form() & Array.isArray()

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2019-08-29
 * @modified
 *
 * @description 数组(深拷贝 / 浅拷贝) shallow-copy deep-copy
 * @augments
 * @example
 * @link
 *
 */

let log = console.log;

function recursiveClone(val) {
    return Array.isArray(val) ? Array.from(val, recursiveClone) : val;
}

const deepCopy = () => {
    const arr = [1, 2, 3];
    const arrNested = [[1, 2, 3], {key: "value"}];
    let arrDeepCopy = recursiveClone(arr);
    let arrNestedDeepCopy = recursiveClone(arrNested);
    log(`arr =`, arr);
    log(`arrNested =`, arrNested);
    log(`deepCopy`, arrDeepCopy);
    log(`deepCopy Nested`, arrNestedDeepCopy);
    // compare to pointer
    log(`deepCopy`, arrDeepCopy === arr);
    log(`deepCopy Nested`, arrNestedDeepCopy === arrNested);
    // modify arr
    arr[0] = "A";
    log(`arr =`, arr);
    log(`deepCopy`, arrDeepCopy);
    // modify arr copy
    arrNestedDeepCopy[1] = ["a", "b", "c"];
    log(`arrNested =`, arrNested);
    log(`deepCopy Nested`, arrNestedDeepCopy);
};

deepCopy();
// false
// false

// [ 'A', 2, 3 ]
// [ 1, 2, 3 ]

// [ [ 1, 2, 3 ], { key: 'value' } ]
// [ [ 1, 2, 3 ], [ 'a', 'b', 'c' ] ]
xgqfrms commented 5 years ago

[...arr] & Object.assign({}, obj)

https://www.samanthaming.com/tidbits/35-es6-way-to-clone-an-array

https://dev.to/samanthaming/how-to-deep-clone-an-array-in-javascript-3cig

image

"use strict";

/**
 *
 * @author xgqfrms
 * @license MIT
 * @copyright xgqfrms
 * @created 2019-08-30
 *
 * @description deep-copy-shallow-copy.js
 * @augments
 * @example
 * @link
 *
 */

let log = console.log;

const sheeps = ['🐑', '🐑', '🐑'];

// Old way
const cloneSheeps = sheeps.slice();

// ES6 way
const cloneSheepsES6 = [...sheeps];

const fakeSheeps = sheeps;

log(`sheeps === fakeSheeps`, sheeps === fakeSheeps);
// true --> it's pointing to the same memory space

log(`sheeps === cloneSheeps`, sheeps === cloneSheeps);
// false --> it's pointing to a new memory space

log(`sheeps === cloneSheepsES6`, sheeps === cloneSheepsES6);
// false --> it's pointing to a new memory space
xgqfrms commented 5 years ago

https://stackoverflow.com/questions/597588/how-do-you-clone-an-array-of-objects-in-javascript

  1. Array.slice()

  2. Array.map()

  3. Array.form()

  4. Object.assign()

  5. [...arr]

for in / for of & Object..hasOwnProperty()

https://stackoverflow.com/questions/728360/how-do-i-correctly-clone-a-javascript-object


function clone(obj) {
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
    }
    return copy;
}
xgqfrms commented 4 years ago

BigInt


const origin = {
  num: 1,
  arr: [2012, 2023],
  func: (v) => console.log(v),
  obj: {msg: 'bug'},
  date: new Date(`2012-01-01`),
  u: undefined,
  nil: null,
  nan: NaN,
  bool: true,
  str: 'string',
  s: Symbol(`s`),
  bi: BigInt(10**32),
  set: new Set([1, 2, 3]),
  map: new Map([['a', 11], ['b', 22], ['c', 33]]),
  // reg: /^0+/g,
  reg: new RegExp(/^0+/g),
};

https://hacks.mozilla.org/2019/07/firefox-68-bigints-contrast-checks-and-the-quantumbar/

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

https://www.infoq.cn/article/ytp*FXkIc6jfP0tSYwY8

https://www.cnblogs.com/xgqfrms/p/11365400.html

xgqfrms commented 3 years ago

deep clone & constructor

obj = {};
{}
arr = [];
[]
obj.constructor
// ƒ Object() { [native code] }

arr.constructor
// ƒ Array() { [native code] }

https://juejin.cn/post/6934500357091360781#heading-6

xgqfrms commented 1 year ago

structuredClone


const origin = {
  num: 1,
  arr: [2012, 2023],
  func: (v) => console.log(v),
  obj: {msg: 'bug'},
  date: new Date(`2012-01-01`),
  u: undefined,
  nil: null,
  nan: NaN,
  bool: true,
  str: 'string',
  s: Symbol(`s`),
  bi: BigInt(10**32),
  set: new Set([1, 2, 3]),
  map: new Map([['a', 11], ['b', 22], ['c', 33]]),
  // reg: /^0+/g,
  reg: new RegExp(/^0+/g),
};

https://developer.mozilla.org/en-US/docs/Web/API/structuredClone

https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm


structuredClone(value)
structuredClone(value, options)

bugs

image

image

image

Uncaught DOMException: Failed to execute 'structuredClone' on 'Window': function (v) {console.log(v)} could not be cloned.

Uncaught DOMException: Failed to execute 'structuredClone' on 'Window': Symbol(s) could not be cloned.

const origin = {
  num: 1,
  arr: [2012, 2023],
  // func: function (v) {console.log(v)},
  obj: {msg: 'bug'},
  date: new Date(`2012-01-01`),
  u: undefined,
  nil: null,
  nan: NaN,
  bool: true,
  str: 'string',
  // s: Symbol(`s`),
  bi: BigInt(10**32),
  set: new Set([1, 2, 3]),
  map: new Map([['a', 11], ['b', 22], ['c', 33]]),
  // reg: /^0+/g,
  reg: new RegExp(/^0+/g),
};

deepClone = structuredClone(origin);

image

refs

https://www.cnblogs.com/xgqfrms/p/17060969.html

https://juejin.cn/post/7080433165264748557

xgqfrms commented 1 year ago
2**32;
4294967296
10**32;
1e+32
BigInt(4294967296);
4294967296n
BigInt(10**32);
100000000000000005366162204393472n
b = 100000000000000005366162204393472n;
100000000000000005366162204393472n

typeof b;
'bigint'

bi = BigInt(10**32);
100000000000000005366162204393472n

typeof bi;
'bigint'

32位整数范围 2**32 - 1; = 4294967295

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

xgqfrms commented 1 year ago

cnblogs

https://www.cnblogs.com/xgqfrms/p/13080460.html

https://www.cnblogs.com/xgqfrms/p/7000492.html