¿Cuál es el $$ hashKey agregado a mi resultado JSON.stringify?

288

Intenté buscar en la página de Mozilla JSON stringify de sus documentos, así como aquí en SO y Google, pero no encontré ninguna explicación. He usado JSOn stringify muchas veces, pero nunca encontré este resultado

Tengo una matriz de objetos JSON

[
    {
        "param_2": "Description 1",
        "param_0": "Name 1",
        "param_1": "VERSION 1"
    },
    {
        "param_2": "Description 2",
        "param_0": "Name 2",
        "param_1": "VERSION 2"
    },
    {
        "param_2": "Description 3",
        "param_0": "Name 3",
        "param_1": "VERSION 3"
    }
]

adjunto a mi $scopey para POSTellos como un parámetro utilicé el método JSON.stringify () y obtengo lo siguiente:

   [
        {
            "param_2": "Description 1",
            "param_0": "Name 1",
            "param_1": "VERSION 1",
            "$$hashKey": "005"
        },
        {
            "param_2": "Description 2",
            "param_0": "Name 2",
            "param_1": "VERSION 2",
            "$$hashKey": "006"
        },
        {
            "param_2": "Description 3",
            "param_0": "Name 3",
            "param_1": "VERSION 3",
            "$$hashKey": "007"
        }
    ]

Tengo curiosidad por saber qué es exactamente la clave hash $$, ya que esperaba algo más similar al siguiente del método stringify:

[
    {
        "1":{
            "param_2": "Description 1",
            "param_0": "Name 1",
            "param_1": "VERSION 1"
        },
         "2":{
            "param_2": "Description 2",
            "param_0": "Name 2",
            "param_1": "VERSION 2"
        },
         "3":{
            "param_2": "Description 3",
            "param_0": "Name 3",
            "param_1": "VERSION 3"
        }
    }
]

No estoy seguro si es un factor pero estoy usando Angularjs 1.1.5, JQuery 1.8.2 and Spring 3.0.4 and Spring security 3.0.7 on the Server side

No me causa ningún problema, pero me gustaría saber la causa y el motivo de la $$hashkey

jonnie
fuente
8
es agregado por angularjs
Arun P Johny
69
en lugar de JSON.stringify use angular.toJson ()
Arun P Johny
Gracias chicos, si alguien quiere agregar su explicación como respuesta, me complacería aceptarlo
Jonnie
1
Esta respuesta es una gran explicación. Stackoverflow.com/questions/12336897/…
Charlie Martin

Respuestas:

530

Angular agrega esto para realizar un seguimiento de sus cambios, de modo que sepa cuándo necesita actualizar el DOM.

Si usa en angular.toJson(obj)lugar de JSON.stringify(obj)Angular, eliminará estos valores de uso interno por usted.

Además, si cambia su expresión de repetición para usar el track by {uniqueProperty}sufijo, Angular no tendrá que agregar $$hashKeynada. Por ejemplo

<ul>
    <li ng-repeat="link in navLinks track by link.href">
        <a ng-href="link.href">{{link.title}}</a>
    </li>
</ul>

Solo recuerda siempre que necesitas el "enlace". parte de la expresión: siempre tiendo a olvidar eso. Simplemente track by hrefseguramente no funcionará.

David Boike
fuente
¿Hay alguna prueba de rendimiento sobre «track by» vs «$$ hashKey»? (UPD. Ok, lo busqué en Google y «track by» es más preferible)
artuska 17/09/2015
El seguimiento de @artuska por ID es muy sencillo, ya que no se deben calcular hashes, simplemente reutiliza los identificadores existentes o incrementa un contador ...
Christophe Roussy
3
y si tiene que aplicar un filtro, este es el orden correcto: item in somelist | filter:somefilter track by item.key¡no escriba el filtro al final de la línea!
Lewen
1
¡Nota! Estaba usando una matriz con un método de clonación que copiaba y luego insertaba elementos en una matriz, que luego era renderizada por ng-repeat. Recibía errores angulares de 'clave duplicada' cuando usaba JSON.parse (JSON.stringify (obj)) para clonar mi elemento. Usando JSON.parse (angular.toJson (obj)); cosas arregladas ¡Gracias!
SAL
1
También puede usar la función Enlace único con dos puntos dobles :: para evitar que se actualice si solo está mostrando datos. <a ng-href="link.href"> {{:: link.title}} </a>
phil
70

En mi caso de uso (alimentar el objeto resultante a X2JS), el enfoque recomendado

data = angular.toJson(source);

ayuda a eliminar las $$hashKeypropiedades, pero X2JS ya no puede procesar el resultado .

data = angular.copy(source);

eliminó las $$hashKeypropiedades también, pero el resultado se mantuvo utilizable como parámetro para X2JS.

rob2universe
fuente
37

Viene con la directiva ng-repeat generalmente. Para hacer la manipulación dom AngularJS marca objetos con una identificación especial.

Esto es común con Angular. Por ejemplo, si obtiene un objeto con ngResource, su objeto incrustará toda la API de recursos y verá métodos como $ save, etc. Con las cookies también, AngularJS agregará una propiedad __ngDebug.

Thomas Pons
fuente
¿Cómo debo eliminar estas propiedades? ¿Angular proporciona alguna forma de hacer eso?
Nilesh
1
Los modelos angulares se romperán si intenta eliminar esa propiedad, le recomiendo copiar la variable. Vea la respuesta de @ David-Boike sobre cómo filtrar el hashkey
Josue Alexander Ibarra
23

Si no desea agregar identificadores a sus datos, puede realizar un seguimiento por el índice en la matriz, lo que hará que los elementos se clave por su posición en la matriz en lugar de su valor.

Me gusta esto:

var myArray = [1,1,1,1,1];

<li ng-repeat="item in myArray track by $index">
Michael Falck Wedelgård
fuente
Eso requiere suponer que el orden de sus artículos nunca cambiará. :)
codificación
8

Si está utilizando Angular 1.3 o superior, le recomiendo que use "track by" en su ng-repeat. Angular no agrega una propiedad "$$ hashKey" a los objetos en su matriz si usa "track by". También obtiene beneficios de rendimiento, si algo en su matriz cambia, angular no recrea toda la estructura DOM para su ng-repeat, sino que recrea la parte del DOM para los valores en su matriz que han cambiado.

Ajay Ullal
fuente
4

Actualización: desde Angular v1.5, el seguimiento por $indexahora es la sintaxis estándar en lugar de usar el enlace, ya que me dio un ng-repeaterror de duplicación.

Me encontré con esto por un anidado ng-repeaty el siguiente funcionó.

<tbody>
    <tr ng-repeat="row in data track by $index">
    <td ng-repeat="field in headers track by $index">{{row[field.caption] }}</td>
</tr>
Vinay
fuente
Solo para aclarar: el atributo utilizado en la pista por expresión debe ser único en la colección repetida. $ index es una opción. En la mayoría de los casos es suficiente, pero a veces puede ser útil rastrear por un atributo único. (Id, ...)
Martin Hlavňa
Eso requiere suponer que el orden de sus artículos nunca cambiará. :)
codificación
3

Así es como puede eliminar fácilmente la $$ hashKey del objeto:

$scope.myNewObject = JSON.parse(angular.toJson($scope.myObject))

$scope.myObject - Se refiere al objeto sobre el que desea realizar la operación, es decir, elimine $$ hashKey de

$scope.myNewObject - Asigne el objeto original modificado al nuevo objeto para que pueda usarse según sea necesario

Devner
fuente
Esto me parece innecesariamente complejo. Podrías eliminar ese único campo, o todos los campos que comienzan con $. Pero probablemente no sea necesario: vea las otras respuestas.
sevcsik
1

https://www.timcosta.io/angular-js-object-comparisons/

Angular es bastante mágico la primera vez que la gente lo ve. El DOM se actualiza automáticamente cuando actualiza una variable en su JS, y la misma variable se actualizará en su archivo JS cuando alguien actualiza su valor en el DOM. Esta misma funcionalidad funciona en todos los elementos de la página y en todos los controladores.

La clave de todo esto es el $$ hashKey Angular adjuntos a objetos y matrices utilizados en ng-repeats.

Este $$ hashKey causa mucha confusión a las personas que envían objetos completos a una API que no elimina datos adicionales. La API devolverá un 400 para todas sus solicitudes, pero ese $$ hashKey simplemente no desaparecerá de sus objetos.

Angular usa $$ hashKey para realizar un seguimiento de qué elementos del DOM pertenecen a qué elemento de una matriz que se está enlazando en una repetición ng. Sin $$ hashKey Angular no habría forma de aplicar los cambios que ocurren en JavaScript o DOM a su contraparte, que es uno de los principales usos de Angular.

Considere esta matriz:

users = [  
    {
         first_name: "Tim"
         last_name: "Costa"
         email: "[email protected]"
    }
]

Si lo procesamos en una lista usando ng-repeat = "user in users", cada objeto en él recibiría una $$ hashKey para fines de seguimiento de Angular. Aquí hay dos formas de evitar este $$ hashKey.

Alfishan aqeel
fuente