This is the 9th day of my participation in the August Gwen Challenge. For details, see: August Gwen Challenge juejin.cn/post/698796…

The data type

It is divided into basic type data and reference type data

Basic type data

  • String, Number, Boolean, Null, Undefined, Symbol, BigInt
  • Values are stored in stack memory

Reference type data

  • Object

    • Math, Date, RegExp, Function, Array
  • Values are stored in heap memory, and reference addresses are stored in stack memory.

Data type detection

Data type detection methods can be divided into three types:

  • typeof
  • insatnceof
  • toString

typeof

  • Basic type data, except null, can return the data type correctly;

    • Typeof null “object”. Is a bug designed by JS itself. If you need to determine whether data is null, you can directly determine XXX === null
  • All types of reference data except function return object;

    • typeof function “function”

insatnceof

This approach is derived from the knowledge of prototype chains.

When the constructor is new, the newly generated object inherits the properties and methods of the constructor. The result on the prototype chain is that the proto of the new object points to the constructor’s prototype, so you can use instanceof to determine if the newly generated object is an instanceof a constructor.

var ObjectFactory = function () {
    // Create an object
    var obj = new Object(a)// Return the first argument as a constructor
    var Constructor = [].shift.call(arguments)
    // Copy the constructor's prototype to the object's prototype
    obj.__proto__ = Constructor.prototype
    // Call the constructor with obj as this, arguments
    var ret = Constructor.apply(obj, arguments)
    If the constructor returns an object, it returns it directly, otherwise we return the object created by this (new)
    return typeof ret === 'object'? ret: obj
}
// The effect is equivalent
var a = ObjectFactory(Person, 'sven');Copy the code
  • Basic type data all return false, the result is not accurate
  • Reference type data returns true, which is more accurate

Instanceof code implementation

function myInstanceof(left,right){
  // Use typeof to determine if it is a basic data type. If so, return false
  if(typeofleft ! = ="object" || left=== null) {return false; }// getProtypeOf is an Object API that can get the parameters of the prototype Object
  let proto = Object.getPrototypeOf(left);
  while(true) {// Loop down until you find objects with the same prototype
    if(proto===null) {return false; }if(proto === right.prototype){return true; } proto =Object.getPrototypeOf(proto); }}Copy the code

toString

Object. The prototype. The toString () method is the archetype of the Object and returns the format for [Object] Xxx (capitalize the first letter)

  • The data type returned is accurate enough to distinguish window from Document
  • The call method is required for values of all data types except ordinary object objects
Object.prototype.toString.call(xxx)
Copy the code

A universal method for determining data types

function getType(obj){
  let type = typeof obj;
  if(type ! = ="object") {// Check typeof first, if it is a basic data type, return directly
    return type;
  }
  // If typeof returns object, regex returns result
  return Object.prototype.toString().call(obj).replace(/^[Object (\S+)]$/.'$1');
}
Copy the code

Depth copy

It’s all about the first layer of data, not the whole outermost layer.

Shallow copy

Create a new object of your own to accept the object values you want to copy or reference again

  • Primitive data: Assign a copy of the value directly to the new data
  • Reference type data: Copied over is the reference address of the value. So if the value of the reference type is changed in the new data, the original data will also be changed

Deep copy

A complete copy of an object from memory to the target object, and a new space in the heap memory to store the new object, and the modification of the new object does not change the original object, the two achieve true separation.

  • Primitive data: Assign a copy of the value directly to the new data
  • Reference type data: copies the heap data directly into the new memory, so that if the value of the reference type is changed in the new data, the original data will not change

Shallow copy method

object.assign()

  • Two arguments: target source(which can be multiple) No return value
  • If the value of the source object is modified after the copy, the changed value is printed before the modification

Note:

  • Do not copy non-enumerable properties
  • Inheritance properties are not copied
  • Property values of type Symbol can be copied

It can be understood as internally looping through the properties of the original object, assigning the properties of the original object to the corresponding properties of the new object.

Extended operator

Just expand the data in the new object.

  • Extended operators are convenient when the first layer of data is all primitive data types

Concat (), slice ()

Shallow copy method for arrays

arr.concat();
arr.slice();
Copy the code

Implement the shallow copy method manually

function shallowClone(target){
    if(typeof target === "object"&& target ! = =null) {let cloneTarget = Array.isArray(target) ? [] : {};
        for(let prop in target){
            if(target.hasOwnProperty(prop)){ cloneTarget[prop] = target(prop); }}return cloneTarget;
    } else {
        returntarget; }}Copy the code

Deep copy method

JSON.stringify()

Parse () serializes an object into a JSON string, converts the contents of the object into a string, and finally generates a new object from the JSON string using json.parse ()

Note:

  • If the object contains data of type function, undefined, symbol, etc., the key-value pair will disappear after copying
  • Copying data of type Date becomes a string
  • Copying RegExp objects becomes empty
  • Non-copy-non-enumerable properties
  • Object prototype chains cannot be copied
  • If the object contains NaN, infinity, etc., it will become NULL after being copied
  • Unable to copy a circular reference to an object

Handwritten base edition deep copy

function deepClone(target){
    let cloneObj = {};
    for(let prop in target){
        if(typeof target[prop] === "object"&& target[prop] ! = =null){
            cloneObj[prop] = deepClone(target[prop]);
        } else {
            cloneObj[prop] = target[prop];
    }
    return cloneObj;
}
Copy the code
  • You still cannot copy non-enumerable properties and values of type symbol
  • Function, Date, and Math cannot be deeply copied only for common objects
  • A circular reference to an object cannot be resolved

Handwritten final deep copy

// Strictly determine whether the data is reference type data
const isComplexDataType = obj= > (typeof obj === 'object' || typeof obj === 'function') && (obj ! = =null)
const deepClone = function (obj,hash = new WeakMap(a)){
    if(obj.constructor === Date) return new Date(obj);  // The date object returns a new date object
    if(obj.constructor === RegExp) return new RegExp(obj);  The regular object returns a new regular object directly
    
    // If the loop is referenced, use weakMap
    if(hash.has(obj)) return hash.get(obj)
    let allDesc = Object.getOwnPropertyDescriptors(obj);
    // Walks through the properties of all keys of the passed argument
    let cloneObj = Object.create(Object.getPrototypeOf(obj),allDesc);
    // Inherit the prototype chain
    hash.set(obj,cloneObj);
    for(let key of Reflect.ownKeys(obj)){
        cloneObj[key] = (isComplexDataType(obj[key]) && typeofobj[key] ! = ='function')? deepClone(obj[key],hash) : obj[key]; }return cloneObj;
}
Copy the code