Verificación del tipo de prototipo de copia profunda y copia superficial

premisa:

La copia profunda y la copia superficial son solo para tipos de datos de referencia como Objeto y Matriz.

1. Pila de memoria

Para obtener más información, consulte otro tipo de datos de blog y almacenamiento de pila

2. Copia superficial y copia profunda

Los diagramas esquemáticos de copia profunda y copia superficial son aproximadamente los siguientes:
Inserte la descripción de la imagen aquí

La copia superficial solo copia el puntero a un objeto, no al objeto en sí. Los objetos antiguos y nuevos aún comparten la misma memoria. Pero una copia profunda creará otro exactamente el mismo objeto. El nuevo objeto no comparte memoria con el objeto original. La modificación del nuevo objeto no cambiará al objeto original.

La diferencia entre asignación y copia superficial
Asignación:

Al asignar un objeto a una nueva variable, en realidad es la dirección del objeto en la pila, no los datos en el montón. Es decir, dos objetos apuntan al mismo espacio de almacenamiento. No importa qué objeto cambie, en realidad es el contenido del espacio de almacenamiento modificado. Por lo tanto, los dos objetos están vinculados.

Copia superficial:

La copia superficial es una copia bit a bit de un objeto. Crea un nuevo objeto con una copia exacta de los valores de atributo del objeto original. Si el atributo es un tipo básico, se copia el valor del tipo básico; si el atributo es una dirección de memoria (tipo de referencia), se copia la dirección de memoria, por lo que si un objeto cambia esta dirección, afectará al otro objeto. Es decir, el constructor de copia predeterminado solo realiza una copia superficial del objeto (copia miembro por miembro a su vez), es decir, solo copia el espacio del objeto sin copiar los recursos.

Copia profunda manuscrita (recursiva):
/**
 * 深拷贝
 */

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
}

Prototipo de JavaScript y cadena de prototipos

1. prototipo

Cada función tiene una propiedad de prototipo, que se denomina prototipo de visualización.

2._ proto _

Cada objeto de instancia tendrá el atributo _ proto , que se denomina prototipo implícito. El prototipo implícito de
cada objeto de instancia. El
atributo proto _ apunta al prototipo de prototipo explícito de su propio constructor.

3. constructor

Cada prototipo tiene un atributo de constructor, que apunta a su constructor asociado.

4. Cadena de prototipos

Al obtener las propiedades del objeto, si el objeto en sí no tiene esta propiedad, se dirigirá a su prototipo __proto__ para encontrarlo, si aún no se encuentra, buscará el prototipo del prototipo hasta la parte superior (Object. prototipo). Los objetos Object.prototype también tienen el valor de propiedad __proto__ de null.

Cabe señalar aquí que Object pertenece al nivel superior de la cadena de prototipos, y los prototipos de todos los constructores apuntan a Object.prototype

Inserte la descripción de la imagen aquí


function Fun(){
    
    

  }
//    我创造了一个函数Fn
//   这个函数由Function生成(Function作为构造函数)
     var fn=new Fun()
//   我创建了一个函数fn
//   这个函数由构造函数Fun生成
     console.log(fn.__proto__===Fun.prototype)    //true
//   fn的__proto__指向其构造函数Fun的prototype
     console.log(Fun.__proto__===Function.prototype)        //true
//   Fun的__proto__指向其构造函数Function的prototype
     console.log(Function.__proto__===Function.prototype)    //true
//   Function的__proto__指向其构造函数Function的prototype
//   构造函数自身是一个函数,他是被自身构造的
     console.log(Function.prototype.__proto__===Object.prototype)    //true
//   Function.prototype的__proto__指向其构造函数Object的prototype
//   Function.prototype是一个对象,同样是一个方法,方法是函数,所以它必须有自己的构造函数也就是Object
     console.log(Fun.prototype.__proto__===Object.prototype)         //true
//   与上条相同
//   此处可以知道一点,所有构造函数的的prototype方法的__都指向__Object.prototype(除了....Object.prototype自身)
     console.log(Object.__proto__===Function.prototype)        //true
//   Object作为一个构造函数(是一个函数对象!!函数对象!!),所以他的__proto__指向Function.prototype
     console.log(Object.prototype.__proto__===null)        //true
//   Object.prototype作为一切的源头,他的__proto__是null

//  下面是一个新的,额外的例子

    var obj={
    
    }
//  创建了一个obj
    console.log(obj.__proto__===Object.prototype)        //true
//   obj作为一个直接以字面量创建的对象,所以obj__proto__直接指向了Object.prototype,而不需要经过Function了!!

//    下面是根据原型链延伸的内容
/*还有一个上文并未提到的constructor,  constructor在原型链中,是作为对象prototype的一个属性存在的,它指向构造函数
(由于主要讲原型链,这个就没在意、);*/

 console.log(obj.__proto__.__proto__===null)        //true
 console.log(obj.__proto__.constructor===Object)        //true
 console.log(obj.__proto__.constructor.__proto__===Function.prototype)        //true
 console.log(obj.__proto__.constructor.__proto__.__proto__===Object.prototype)    //true
 console.log(obj.__proto__.constructor.__proto__.__proto__.__proto__===null)        //true
 console.log(obj.__proto__.constructor.__proto__.__proto__.constructor.__proto__===Function.prototype)    //true

//            以上,有兴趣的可以一一验证  F12搞起.

juicio de tipo de datos js

Cuatro métodos

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

1 .tipo de

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'
);

En los tipos de datos básicos: Número, Cadena, Booleano, Indefinido y Función en el tipo de datos de referencia, puede usar typeof para detectar el tipo de datos y devolver los caracteres en minúscula del tipo de datos correspondiente, respectivamente.
Otro: Número, Cadena, Booleano creado por el constructor de detección typeof todos regresan al
tipo de datos básico del objeto : nulo. Tipos de datos de referencia: matriz, objeto, fecha, expresión regular. No se puede utilizar el tipo de detección. Devolverá el objeto en minúsculas

2. en vez de

Además de usar typeof para juzgar, también puede usar instanceof. El operador instanceof necesita especificar un constructor, o especificar un tipo específico, que se usa para determinar si el prototipo de este constructor está en la cadena de prototipos de un objeto dado.


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
)

Entre los tipos de datos básicos: Número, Cadena, Booleano. El valor literal no puede ser detectado por instanceof, pero el valor creado por el constructor puede ser el siguiente:


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

También tenga en cuenta que tanto el valor nulo como el indefinido devuelven falso, esto se debe a que su tipo es él mismo, no el objeto que los creó, por lo que se devuelve falso.

3 .constructor

El constructor es una propiedad del objeto prototipo que apunta al constructor. Según el orden en que se busquen los atributos de los objetos de instancia, si no hay atributos o métodos de instancia en los objetos de instancia, se buscarán en la cadena de prototipos, por lo que los objetos de instancia también pueden utilizar el atributo constructor.

Si genera un constructor de una instancia de un tipo, se ve así:


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

Puede ver que apunta al constructor de Número. Por lo tanto, puede usar num.constructor == Número para determinar si una variable es de tipo Número.


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

A excepción de undefined y null, otros tipos se pueden juzgar por el atributo constructor.

4. Utilice Object.prototype.toString.call () para detectar el tipo de objeto

Puede obtener el tipo de cada objeto a través de toString (). Para que cada objeto sea detectado por Object.prototype.toString (), debe llamarse en la forma de Function.prototype.call () o Function.prototype.apply (), pasando el objeto a comprobar como el primer parámetro, llamado 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]"

De esta forma, puede ver que Object.prototype.toString.call()la forma más precisa de determinar el tipo de variable es la forma en que se utiliza.

5. Método todopoderoso invencible: jquery.type ()

Si el objeto no está definido o es nulo, se devuelve el "indefinido" o "nulo" correspondiente.

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. También puede encapsular una función para obtener el tipo exacto de variable

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

if (type! == 'object') { return type; } // Si no es un dato de tipo de objeto, se puede juzgar directamente con typeof


// Si se trata de datos de tipo de objeto, debe utilizar Object.prototype.toString.call (obj) para determinar con precisión el tipo para determinar el
retorno Object.prototype.toString.call (obj) .replace (/ ^ [object (\ S + )] $ /, '$ 1');
}

Supongo que te gusta

Origin blog.csdn.net/WLIULIANBO/article/details/112584734
Recomendado
Clasificación