Ajoutant à la propriété json qui peut ou non exister

Disons que je veux faire cela

var dasboard = {}; var page = "index"; $('.check').click(function(){ $(this).toggleClass("active").siblings().slideToggle('slow', function() { dashboard['pages'][page][$(this).closest('li').attr("id")]['show'] = $(this).is(":hidden") ? 'collapsed' : 'expanded'; }); } 

Je reçois une erreur en disant 'dashboard.pages is indefined'

Est-il là pour ajouter de façon dynamique les «pages» et les enfants qui suivent sans avoir à faire le travail de vérification pour voir si c'est défini d'abord alors s'il ne le fait pas

  dashboard['pages'] = {}; 

Parce que parfois ils peuvent déjà exister et je ne veux pas d'abord inspecter l'arbre, je veux simplement construire les branches au besoin

EDIT J'ai changé 'pagename' en page pour montrer que les noms de page vont changer et alo je veux souligner que les pages pourraient vraiment être n'importe quoi aussi. L'idée est que vous avez un objet qui peut contenir des ojbjecs avec des paramètres sans vérifier si les branches existent

Il semble que $ extend, comme indiqué, sera le chemin à suivre, pas sûr de la façon dont cela fonctionne. Je devais comprendre

Définissez les méthodes get et set sur un Object . En fait, il pourrait être défini juste sur l'objet dashboard et seulement ses descendants, mais c'est facile à faire.

 Object.prototype.get = function(prop) { this[prop] = this[prop] || {}; return this[prop]; }; Object.prototype.set = function(prop, value) { this[prop] = value; } 

Iterate à travers les propriétés imbriquées à l'aide de cette méthode get() et de l' set() appel set() chaque fois qu'une valeur doit être définie.

 var dashboard = {}; dashboard.get('pages').get('user').set('settings', 'oh crap'); // could also set settings directly without using set() dashboard.get('pages').get('user').settings = 'oh crap'; console.log(dashboard); //​​​​​​​​​​​​​​​ {pages: {user: {settings: "oh crap"}}}; 

Vous pouvez également étendre / modifier la méthode get pour accepter les propriétés imbriquées comme des arguments individuels ou un tableau ou une chaîne. En utilisant cela, vous devriez seulement appeler une fois:

 // get accepts multiple arguments here dashboard.get('pages', 'user').set('settings', 'something'); // get accepts an array here dashboard.get(['pages', 'user']).set('settings', 'something'); // no reason why get can't also accept dotted parameters // note: you don't have to call set(), could directly add the property dashboard.get('pages.user').settings = 'something'; 

Mise à jour :

Étant donné que la méthode get renvoie génétiquement un objet et ne sait pas si vous avez besoin d'un tableau ou d'un autre type d'objet, alors vous devriez spécifier que vous-mêmes:

 dashboard.get('pages.user').settings = []; 

Ensuite, vous pouvez pousser les éléments dans le tableau des paramètres comme

 dashboard.get('pages.user').settings.push('something'); dashboard.get('pages.user').settings.push('something else'); 

Pour avoir réellement la fonction get construire la hiérarchie d'objet d'une chaîne donnée telle que pages.user, vous devriez diviser la chaîne en parties et vérifier si chaque objet imbriqué existe. Voici une version modifiée de get that just that:

 Object.prototype.get = function(prop) { var parts = prop.split('.'); var obj = this; for(var i = 0; i < parts.length; i++) { var p = parts[i]; if(obj[p] === undefined) { obj[p] = {}; } obj = obj[p]; } return obj; } // example use var user = dashboard.get('pages.user'); user.settings = []; user.settings.push('something'); user.settings.push('else'); console.log(dashboard); // {pages: {user: {settings: ["something", "else"] }}} // can also add to settings directly dashboard.get('pages.user.settings').push('etc'); 

Je le ferais avec l'opérateur ternaire:

 dashboard['pages'][page] = dashboard['pages'][page] ? dashboard['pages'][page] : {}; 

Cela fera l'enjeu, peu importe s'il est défini / nul ou quoi que ce soit.

Je ne pense pas qu'il y ait une bonne façon de le faire, mais vous pouvez toujours l'abstraire avec une fonction.

 function getProperty(obj,prop){ if( typeof( obj[prop] ) == 'undefined' ){ obj[prop] = {}; } return obj[prop]; } 

Ensuite, vous utilisez

getProperty(dashboard,'pages')['pagename']

ou

 getProperty(getProperty(dashboard,'pages'),'pagename'); 

Comme mentionné, $ .extend rendra cela moins onéreux.

 var foo = dashboard['pages'] || {}; foo['pagename'] = 'your thing here'; dashboard['pages'] = foo; 

En expliquant: la première ligne vérifiera si la première valeur est nulle, non définie ou … fausse (ne pense pas que ceci soit un problème ici): si c'est le cas, créez un nouvel objet, sinon l'utiliserez.

$ .extend est le chemin à parcourir

 function elem(a,b){ var r={'pages':{'pagename':{}}}; r.pages.pagename[a]={'show':b}; return r; } data={}; //inside the event handler or something: data = $.extend(true,data,elem($(this).closest('li').attr("id"),$(this).is(":hidden") ? 'collapsed' : 'expanded')); 

Mais honnêtement – c'est une idée plutôt désordonnée de stocker cette information de toute façon. Je parie que si vous avez besoin de cette information plus tard, cela pourrait être fait avec un bon sélecteur ou avec jQuery.data ()

Eh bien, je suppose que vous avez besoin de ceci:

 var dashBoard = new Array(); if(!dashboard['page123']) { dashBoard.push('page123'); } else { ...do what you want } 

On dirait que vous avez affaire à XML.

La meilleure solution pour mon cas était de faire un prototype d'objet

  /** * OBJECT GET * Used to get an object property securely * @param object * @param property * @returns {*} */ Object.get = function(object, property) { var properties = property.split('.'); for (var i = 0; i < properties.length; i++) { if (object && object[properties[i]]) { object = object[properties[i]]; } else { return null; } } return object; }; 

Et puis vous pouvez obtenir votre propriété comme celle-ci

 var object = {step1:{step2:{step3:'test'}}} Object.get(object, 'step1.step2.step3'); // return 'test' 

J'espère que cela aide 🙂