O que é o $$ hashKey adicionado ao meu resultado JSON.stringify

288

Eu tentei procurar na página do Mozilla JSON stringify de seus documentos, bem como aqui no SO e no Google, mas não encontrei nenhuma explicação. Eu usei o JSOn stringify muitas vezes, mas nunca me deparei com esse resultado

Eu tenho uma 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"
    }
]

anexado ao meu $scopee, para POSTeles como um paramater, usei o método JSON.stringify () e recebo o seguinte:

   [
        {
            "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"
        }
    ]

Estou curioso para saber exatamente o que é o hashkey $$, pois esperava algo mais semelhante ao seguinte no 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"
        }
    }
]

Não tenho certeza se é um fator, mas estou usando Angularjs 1.1.5, JQuery 1.8.2 and Spring 3.0.4 and Spring security 3.0.7 on the Server side

Não está causando nenhum problema, mas eu gostaria de saber a causa e o motivo da $$hashkey

Jonnie
fonte
8
é adicionado por angularjs
Arun P Johny
69
em vez de JSON.stringify uso angular.toJson ()
Arun P Johny
Obrigado pessoal, se alguém quiser adicionar a sua explicação como resposta, ficaria feliz em aceitar #
61313 Jonnie
1
Esta resposta é uma ótima explicação .. stackoverflow.com/questions/12336897/…
Charlie Martin

Respostas:

530

Angular adiciona isso para acompanhar suas alterações, para que ele saiba quando precisa atualizar o DOM.

Se você usar em angular.toJson(obj)vez de JSON.stringify(obj), o Angular removerá esses valores de uso interno para você.

Além disso, se você alterar sua expressão de repetição para usar o track by {uniqueProperty}sufixo, Angular não precisará adicionar $$hashKeynada. Por exemplo

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

Lembre-se sempre de que você precisa do "link". parte da expressão - eu sempre esqueço isso. Só track by hrefcertamente não vai funcionar.

David Boike
fonte
Existem testes de desempenho sobre «rastrear por» vs «$$ hashKey»? (UPD Ok, eu pesquisei e «pista por» é mais preferível.)
artuska
@artuska rastreamento por id é muito simples como há hashes têm de ser computados você apenas ids reutilização existentes ou incrementar um contador ...
Christophe Roussy
3
e se você tiver um filtro para aplicar, eis a ordem correta: item in somelist | filter:somefilter track by item.keynão escreva o filtro no final da linha!
Lewen
1
Nota! Eu estava usando uma matriz com um método clone que copiava os elementos inseridos em uma matriz, que era renderizada por um ng-repeat. Eu estava recebendo erros angulares de 'chave duplicada' ao usar o JSON.parse (JSON.stringify (obj)) para clonar meu elemento. Usando JSON.parse (angular.toJson (obj)); coisas consertadas. Obrigado!
SAL
1
Você também pode usar o recurso Vinculação única usando dois pontos :: para impedir sua atualização se você estiver exibindo apenas dados. <a ng-href="link.href"> {{:: link.title}} </a>
phil
70

No meu caso de uso (alimentando o objeto resultante para X2JS), a abordagem recomendada

data = angular.toJson(source);

ajuda a remover as $$hashKeypropriedades, mas o resultado não pôde mais ser processado pelo X2JS .

data = angular.copy(source);

removeu as $$hashKeypropriedades também, mas o resultado permaneceu utilizável como parâmetro para o X2JS.

rob2universe
fonte
37

Geralmente, ele vem com a diretiva ng-repeat. Para manipular o Dom, o AngularJS sinaliza objetos com um ID especial.

Isso é comum no Angular. Por exemplo, se você obtiver um objeto com ngResource, seu objeto incorporará toda a API do recurso e você verá métodos como $ save, etc. Com os cookies também, o AngularJS adicionará uma propriedade __ngDebug.

Thomas Pons
fonte
como devo remover essas propriedades? O angular fornece alguma maneira de fazer isso?
Nilesh
1
Modelos angulares serão interrompidos se você tentar remover essa propriedade, recomendo copiar a variável. Veja a resposta de @ David-Boike sobre como filtrar o hashkey
Josue Alexander Ibarra
23

Se você não deseja adicionar IDs aos seus dados, pode rastrear pelo índice na matriz, o que fará com que os itens sejam digitados pela posição na matriz, e não pelo valor.

Como isso:

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

<li ng-repeat="item in myArray track by $index">
Michael Falck Wedelgård
fonte
Isso requer a suposição de que a ordem dos seus itens nunca será alterada. :)
neatcoding
8

Se você estiver usando o Angular 1.3 ou superior, recomendo que você use "track by" no seu ng-repeat. Angular não adiciona uma propriedade "$$ hashKey" aos objetos em sua matriz se você usar "rastrear por". Você também obtém benefícios de desempenho, se algo em sua matriz mudar, o angular não recriará toda a estrutura do DOM para o ng-repeat, mas recriará a parte do DOM para os valores em sua matriz que foram alterados.

Ajay Ullal
fonte
4

Atualização: No Angular v1.5, rastrear $indexagora é a sintaxe padrão em vez de usar o link, pois isso me deu um ng-repeaterro enganador.

Encontrei isso por um aninhado ng-repeate o abaixo funcionou.

<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
fonte
Apenas para esclarecer - o atributo usado na trilha por expressão deve ser único na coleção repetida. $ index é uma opção. Na maioria dos casos, é suficiente, mas às vezes você pode achar útil para monitorar por atributo único (id, ...).
Martin Hlavná
Isso requer a suposição de que a ordem dos seus itens nunca será alterada. :)
neatcoding
3

Aqui está como você pode remover facilmente o $$ hashKey do objeto:

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

$scope.myObject - Refere-se ao objeto no qual você deseja executar a operação, por exemplo, remova o $$ hashKey de

$scope.myNewObject - Atribua o objeto original modificado ao novo objeto para que possa ser usado conforme necessário

Devner
fonte
Acho isso desnecessariamente complexo. Você pode simplesmente remover esse campo único - ou todos os campos começando com $. Mas provavelmente você não precisa - veja as outras respostas.
sevcsik
1

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

Angular é bastante mágico na primeira vez que as pessoas o veem. O DOM é atualizado automaticamente quando você atualiza uma variável em seu JS, e a mesma variável é atualizada em seu arquivo JS quando alguém atualiza seu valor no DOM. Essa mesma funcionalidade funciona nos elementos da página e nos controladores.

A chave para tudo isso é o $$ hashKey Angular anexado a objetos e matrizes usados ​​em ng-repeats.

Esse $$ hashKey causa muita confusão para as pessoas que estão enviando objetos completos para uma API que não retira dados extras. A API retornará um 400 para todas as suas solicitações, mas esse $$ hashKey simplesmente não desaparecerá dos seus objetos.

Angular usa $$ hashKey para controlar quais elementos no DOM pertencem a qual item em uma matriz que está sendo repetida em um ng-repeat. Sem o $$ hashKey, o Angular não teria como aplicar as alterações ocorridas no JavaScript ou DOM ao seu homólogo, que é um dos principais usos do Angular.

Considere esta matriz:

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

Se transformássemos isso em uma lista usando ng-repeat = "usuário em usuários", cada objeto receberia uma $$ hashKey para fins de rastreamento da Angular. Aqui estão duas maneiras de evitar esse $$ hashKey.

alfishan aqeel
fonte