2010-08-15 5 views
0

J'ai eu des problèmes avec les gens qui sautent aux conclusions sur ce dont j'ai besoin ici, donc s'il vous plaît lisez ceci et pensez-y avant de répondre.Cibler des emplacements (non) connus dans un objet avec Javascript

Voici le cas:

Vous avez un objet entrant. Vous ne connaissez pas la structure de cet objet. Vous avez cependant une "cible" à quelque chose dans l'objet. Alors faisons comme si il y a myObject, et vous avez une sorte de cible définie comme un tableau de niveaux d'association:

var objectTarget = [ 'firstLevel', 'secondLevel' ,'targetProperty' ]; 

Maintenant, le myObject entrant ressemble à ceci:

{ 
    firstLevel: { 
     secondLevel: { 
      targetProperty: "The goods!" 
     } 
    } 
} 

Mais comme indiqué précédemment, vous Je ne connais pas la structure. Tout ce que vous savez, c'est ce qui se trouve dans le tableau objectTarget.

Mon problème est de pouvoir adresser un emplacement arbitraire dans un objet basé uniquement sur une cible. Si je savais que la cible serait toujours soit trois niveaux de profondeur, alors je pourrais simplement faire référence comme ceci:

myObject[objectTarget[1]][objectTarget[2]][objectTarget[3]]; 

Cependant, parce que je ne peux pas être sûr du nombre de profondeur de niveau, cela ne suffit pas. La seule façon que j'ai été capable d'accomplir cette tâche est de choisir un nombre maximum de niveaux raisonnables, puis de l'activer. Comme si:

switch (objectTarget.length) { 
    case 1: 
     var result = myObject[objectTarget[1]]; 
     break; 
    case 2: 
     var result = myObject[objectTarget[1]][objectTarget[2]]; 
     break; 
    case 3: 
     var result = myObject[objectTarget[1]][objectTarget[2]][objectTarget[3]]; 
     break; 
    case 4: 
     var result = myObject[objectTarget[1]][objectTarget[2]][objectTarget[3]][objectTarget[1]]; 
     break; 
} 

..etc

Ceci est évidemment extrêmement désordonné, et non la solution optimale.

Est-ce que cela explique correctement mon problème? Y a-t-il une manière plus propre d'accomplir ceci?

Merci d'avance pour tout conseil que vous pouvez fournir.

Répondre

1

Une tentative du haut de ma tête:

function findTarget(obj, targets) { 
    for(var i = 0; i < targets.length; i++) { 
     var prop = targets[i]; 
     if(obj[prop] != undefined) { 
     obj = obj[prop]; 
     } else { 
     return undefined; // Whatever you want when the target does not exist 

     // or, if it's useful to you 
     return obj; // Maximum reachable target 
     } 
    } 

    return obj; 
} 

var target = findTarget(incoming, ['level1', 'level2', ...]); 

if(target == undefined) { 
    // couldn't traverse the entire target list... 
} 
+0

Merci! Side-question: Combien de temps devrais-tu deviner? – Spot

+1

Je ne pense pas que ce soit sensiblement plus lent que si vous connaissiez le chemin à l'avance. Chaque '.' dans quelque chose comme' obj.leve1.level2.target' nécessite une recherche d'exécution de sorte que vous ne gagnez rien avec la connaissance préalable. Bien que pour chaque profondeur parcourue, vous auriez besoin d'un accès supplémentaire pour obtenir le nom de la cible en utilisant cette méthode (la partie 'targets [i]'.) Je ne serais pas inquiet de la vitesse de ce code, sauf 'targets. la longueur devient grande. –

1

Une autre approche si vous pouvez utiliser (ou inclure pour IE) la méthode reduce Array:

function getTarget(obj, target) { 
    return target.reduce(function(a, b) { return a && a[b]; }, obj); 
} 

// usage (assuming that `myObject` is your sample object): 
var target = ['firstLevel', 'secondLevel' ,'targetProperty']; 
getTarget(myObject, target); // "The goods!" 
Questions connexes