Pila y pila de JavaScript, copia superficial y copia profunda

¿Qué son el montón y la pila, y cómo se relacionan con la copia superficial y la copia profunda?

En el campo de la computadora, la pila son dos tipos de estructuras de datos, las cuales son estructuras de datos en las que los elementos de datos se organizan en secuencia, y los elementos de datos solo se pueden insertar y eliminar en un extremo (llamado la parte superior de la pila).

La principal diferencia entre la copia profunda y la copia superficial es que tienen diferentes tipos de almacenamiento en la memoria, mientras que el montón y la pila son áreas divididas en almacenamiento en la memoria.

La pila es el espacio de memoria asignado automáticamente por el sistema, que es liberado automáticamente por el sistema; mientras que el montón es memoria asignada dinámicamente, y el tamaño es variable y no se liberará automáticamente.

Tipos de datos ECMAScript

Por lo tanto, antes de comprender la copia superficial y la copia profunda, primero comprendamos los tipos de datos en ECMAScript.

tipo básico

Los tipos básicos son:undefined,boolean,number,string,null

El tipo básico es un segmento de datos simple almacenado en la memoria de la pila , se determina el tamaño de los datos, se puede asignar el tamaño del espacio de memoria y se almacena directamente por valor, por lo que se puede acceder directamente.

Tipo de referencia

Los principales tipos de referencia son:object,array,function

Los tipos de referencia son objetos almacenados en la memoria del montón . La variable real de la pila tiene un puntero en la memoria, el puntero para amontonar un espacio. El tamaño de cada espacio es diferente y se debe realizar una asignación específica según la situación. Cuando necesitamos acceder al valor de un tipo de referencia, primero obtenemos el puntero de dirección del objeto de la pila y luego obtenemos los datos requeridos de la memoria del montón .

La principal diferencia entre tipos básicos y tipos de referencia.

La mayor diferencia entre los tipos básicos y los tipos de referencia es en realidad la diferencia entre pasar por valor y pasar por dirección .

 

var a = [1,2,3,4,5];
var b = a; //传址
var c = a[0]; //传值
console.log(b); //1,2,3,4,5
console.log(c); //1
b[4] = 6; //改变b数组的某一项值
c = 7; //改变c的值
console.log(a[4]); //6 
console.log(a[0]); //1

Por lo anterior, podemos saber que cuando cambio la matriz b, la matriz a también cambia. Pero cuando cambio el valor de c, a no cambia. Ésta es la diferencia entre el paso de valores y el paso de direcciones .

Debido a que a es una matriz y pertenece a un tipo de referencia, cuando se asigna ab, pasa la dirección en la pila (equivalente a crear un nuevo "puntero" con un nombre diferente), no un objeto en la memoria del montón, por lo que ayb apuntan al mismo montón de memoria. Y c es solo un valor de datos obtenido de una memoria de pila y almacenado en la pila. Entonces, cuando se modifica b, se modificará de acuerdo con la dirección de regreso a la memoria del montón a, mientras que c se modifica directamente en la pila y no puede apuntar a la memoria del montón a.

 

Copia superficial

Por el contenido anterior, podemos saber que al definir un objeto o matriz, la variable suele ser solo una dirección de pila. Cuando usamos la copia de objeto, si el atributo es un objeto o una matriz , lo que pasamos en este momento es solo una dirección de pila. Por lo tanto, cuando el objeto hijo accede al atributo, retrocederá a la memoria de montón a la que apunta el objeto padre según la dirección, es decir, cuando los objetos padre e hijo estén asociados , los valores de atributo de los dos apuntarán al mismo espacio de memoria.

 

ejemplo:

 

var a = {
  key1: 123,
  key2: [1,2]
};
function copy(o){
  var obj = {};
  for(var i in o){
    obj[i] = o[i];
  }
  return obj;
}
var b = copy(a);
b.key1 = 1234; //b对象的key1重新赋值
b.key2.push(3); //b对象的key2数组里面插入一个新的值
console.log(b.key1); //1234
console.log(a.key1): //123
console.log(b.key2); //1,2,3
console.log(a.key2); //1,2,3

En el código anterior, se puede ver que el valor de key1 de b ha cambiado, pero el valor de key1 de a no ha cambiado junto con él, pero el valor de key2 de b ha cambiado después de que el valor de key2 de a también haya cambiado. cambió.

Esto se debe a que el valor de key1 pertenece al tipo básico, por lo que el segmento de datos se pasa al copiar. Pero el valor de key2 es un objeto en la memoria del montón, por lo que cuando se copia key2, se pasa la dirección que apunta al objeto key2. No importa cuántas key2 se copien, el valor es siempre el espacio de memoria del objeto key2 que apunta a a.

Copia profunda

A veces, no queremos la relación entre los objetos padre e hijo , entonces se puede usar una copia profunda en este momento. Dado que el tipo de valor de atributo es una matriz o una imagen, solo se pasa la dirección, entonces usamos el siguiente método para resolver este problema, y ​​todos los tipos de atributo que pertenecen al objeto en el objeto padre se pueden atravesar y asignar al hijo objeto.

 

  • Método JSON

    function deepCopy(o){
      return JSON.parse(JSON.stringify(o));
    }
    var a = {
      key: [1,2]
    };
    var b = deepCopy(a); //拷贝a
    b.key.push(3); //往b的key中插入新的值
    console.log(a); //1,2
    console.log(b); //1,2,3
    
  • Usar recursividad

    function deepCopy(o,c){
      var c = c || {};
      for(var i in o){
        if(typeof o[i] === 'object'){
          c[i] = (o[i].constructor === Array) ? [] : {};
          deepCopy(o[i], c[i]);
        }else{
          c[i] = o[i];
        }
      }
      return c;
    }
    var a = {
      key: [1,2]
    };
    var b = deepCopy(a); //拷贝a
    b.key.push(3); //往b的key中插入新的值
    console.log(a); //1,2
    console.log(b); //1,2,3

 

Supongo que te gusta

Origin blog.csdn.net/AN0692/article/details/107997256
Recomendado
Clasificación