Recursive handwriting deep copy ===== js data type judgment

Recursive handwritten deep copy

premise:

Deep copy and shallow copy are only for reference data types such as Object and Array.

1. Stack memory

For details, see another blog data type and stack storage

2. Shallow copy and deep copy

The schematic diagrams of deep copy and shallow copy are roughly as follows:

Insert picture description here

Shallow copy only copies the pointer to an object, not the object itself. The old and new objects still share the same memory. But a deep copy will create another exactly the same object. The new object does not share memory with the original object. Modifying the new object will not change to the original object.

The difference between assignment and shallow copy
Assignment:

When assigning an object to a new variable, it is actually the address of the object on the stack, not the data in the heap. That is, two objects point to the same storage space. No matter which object changes, it is actually the content of the changed storage space. Therefore, the two objects are linked.

Shallow copy:

Shallow copy is a bitwise copy of an object. It creates a new object with an exact copy of the original object's attribute values. If the attribute is a basic type, the value of the basic type is copied; if the attribute is a memory address (reference type), the memory address is copied, so if one object changes this address, it will affect the other object. That is, the default copy constructor only performs a shallow copy copy of the object (copy member by member in turn), that is, only copy the object space without copying the resources.

Handwritten deep copy (recursive):

/**
 * 深拷贝
 */

const obj1 = {
    
    
    age: 20,
    name: 'xxx',
    address: {
    
    
        city: 'beijing'
    },
    arr: ['a', 'b', 'c']
}

const obj2 = deepClone(obj1)
obj2.address.city = 'shanghai'
obj2.arr[0] = 'a1'
console.log(obj1.address.city)
console.log(obj1.arr[0])

/**
 * 深拷贝
 * @param {Object} obj 要拷贝的对象
 */
function deepClone(obj = {
    
    }) {
    
    
    if (typeof obj !== 'object' || obj == null) {
    
    
        // obj 是 null ,或者不是对象和数组,直接返回
        return obj
    }

    // 初始化返回结果
    let result
    if (obj instanceof Array) {
    
    
        result = []
    } else {
    
    
        result = {
    
    }
    }

    for (let key in obj) {
    
    
        // 保证 key 不是原型的属性
        if (obj.hasOwnProperty(key)) {
    
    
            // 递归调用!!!
            result[key] = deepClone(obj[key])
        }
    }

    // 返回结果
    return result
}

js data type judgment

Four methods

typeof、instanceof、constructor、Object.prototype.toString.call()、jquery.type()

1 .typeof

console.log(
    typeof 100, //"number"
    typeof 'abc', //"string"
    typeof false, //"boolean"
    typeof undefined, //"undefined"
    typeof null, //"object"
    typeof [1,2,3], //"object"
    typeof {
    
    a:1,b:2,c:3}, //"object"
    typeof function(){
    
    console.log('aaa');}, //"function"
    typeof new Date(), //"object"
    typeof /^[a-zA-Z]{
    
    5,20}$/, //"object"
    typeof new Error() //"object"
    typeof new Number(100), //'object'
    typeof new String('abc'),// 'string'
    typeof new Boolean(true),//'boolean'
);

In the basic data types: Number, String, Boolean, undefined and Function in the reference data type, you can use typeof to detect the data type, and return the lowercase characters of the corresponding data type respectively.
Another: Use typeof to detect the Number, String, Boolean created by the constructor all return object
Among the basic data types: null. Reference data types: Array, Object, Date, RegExp. Can not use typeof detection. Will return lowercase object

2 . instanceof

In addition to using typeof to judge, you can also use instanceof. The instanceof operator needs to specify a constructor, or specify a specific type, which is used to determine whether the prototype of this constructor is on the prototype chain of a given object.

console.log(
    100 instanceof Number, //false
    'dsfsf' instanceof String, //false
    false instanceof Boolean, //false
    undefined instanceof Object, //false
    null instanceof Object, //false
    [1,2,3] instanceof Array, //true
    {
    
    a:1,b:2,c:3} instanceof Object, //true
    function(){
    
    console.log('aaa');} instanceof Function, //true
    new Date() instanceof Date, //true
    /^[a-zA-Z]{
    
    5,20}$/ instanceof RegExp, //true
    new Error() instanceof Error //true
)

Among the basic data types: Number, String, Boolean. The literal value cannot be detected by instanceof, but the value created by the constructor can be, as follows:

var num = new Number(123);
var str = new String('dsfsf');
var boolean = new Boolean(false);

Also note that both null and undefined return false, this is because their type is itself, not Object created them, so false is returned.
3 .constructor
The constructor is a property on the prototype object, pointing to the constructor. According to the order in which the instance objects are searched for attributes, if there are no instance attributes or methods on the instance objects, they will be searched on the prototype chain. Therefore, the instance objects can also use the constructor attribute.
If you output a constructor of an instance of a type, it looks like this:

console.log(new Number(123).constructor)
//ƒ Number() { [native code] }

You can see that it points to the constructor of Number. Therefore, you can use num.constructor==Number to determine whether a variable is of type Number.

var num  = 123;
var str  = 'abcdef';
var bool = true;
var arr  = [1, 2, 3, 4];
var json = {
    
    name:'wenzi', age:25};
var func = function(){
    
     console.log('this is function'); }
var und  = undefined;
var nul  = null;
var date = new Date();
var reg  = /^[a-zA-Z]{5,20}$/;
var error= new Error();

function Person(){
    
    
  
}
var tom = new Person();

// undefined和null没有constructor属性
console.log(
    tom.constructor==Person,
    num.constructor==Number,
    str.constructor==String,
    bool.constructor==Boolean,
    arr.constructor==Array,
    json.constructor==Object,
    func.constructor==Function,
    date.constructor==Date,
    reg.constructor==RegExp,
    error.constructor==Error
);
//所有结果均为true

Except for undefined and null, other types can be judged by the constructor attribute.
4. Use Object.prototype.toString.call() to detect the object type
You can get the type of each object through toString(). In order for each object to be detected by Object.prototype.toString(), it needs to be called in the form of Function.prototype.call() or Function.prototype.apply(), passing the object to be checked as the first parameter, Called thisArg.

var toString = Object.prototype.toString;

toString.call(123); //"[object Number]"
toString.call('abcdef'); //"[object String]"
toString.call(true); //"[object Boolean]"
toString.call([1, 2, 3, 4]); //"[object Array]"
toString.call({
    
    name:'wenzi', age:25}); //"[object Object]"
toString.call(function(){
    
     console.log('this is function'); }); //"[object Function]"
toString.call(undefined); //"[object Undefined]"
toString.call(null); //"[object Null]"
toString.call(new Date()); //"[object Date]"
toString.call(/^[a-zA-Z]{5,20}$/); //"[object RegExp]"
toString.call(new Error()); //"[object Error]"

In this way, you can see that Object.prototype.toString.call()the most accurate way to determine the type of a variable is the way it is used.
5. Invincible almighty method: jquery.type()
If the object is undefined or null, the corresponding "undefined" or "null" is returned. \

jQuery.type( undefined ) === "undefined"
jQuery.type() === "undefined"
jQuery.type( window.notDefined ) === "undefined"
jQuery.type( null ) === "null"
/*如果对象有一个内部的[[Class]]和一个浏览器的内置对象的 [[Class]] 相同,
我们返回相应的 [[Class]] 名字。 (有关此技术的更多细节。 )*/
jQuery.type( true ) === "boolean"
jQuery.type( 3 ) === "number"
jQuery.type( "test" ) === "string"
jQuery.type( function(){
    
    } ) === "function"
jQuery.type( [] ) === "array"
jQuery.type( new Date() ) === "date"
jQuery.type( new Error() ) === "error" // as of jQuery 1.9
jQuery.type( /test/ ) === "regexp"
其他一切都将返回它的类型“object”

6. You can also encapsulate a function to get the exact type of the variable

function gettype(obj) {
    
    
  var type = typeof obj;

  if (type !== 'object') {
    
    
    return type;
  }
  //如果不是object类型的数据,直接用typeof就能判断出来

  //如果是object类型数据,准确判断类型必须使用Object.prototype.toString.call(obj)的方式才能判断
  return Object.prototype.toString.call(obj).replace(/^\[object (\S+)\]$/, '$1');
}

Guess you like

Origin blog.csdn.net/WLIULIANBO/article/details/110672434