IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Contribuez Discussion :

Tester l'existence d'objects imbriqués [Sources]


Sujet :

Contribuez

  1. #1
    Membre expérimenté Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Points : 1 519
    Points
    1 519
    Par défaut Tester l'existence d'objects imbriqués
    Bonjour,

    Ca fait longtemp que je n'étais plus venu ici, mais j'aimerai partager une petite fonction que je viens de me coder pour tester si un sous-(sous-sous-...)objet existe dans un objet parent.

    Exemple de cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var test = {level1: {level2: {level:'ok'} }};
    Typiquement, si on ne sait pas si test et ses sous-objets existent, nous devrons tester de la façon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if(test && test.level1 && test.level1.level2){
      alert(test.level1.level2.level3);
    }
    Ce qui est fastidieux à écrire je trouve.

    Je propose donc une première solution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function get_if_exist(str){
      try{return eval(str)}
      catch(e){return undefined}
    }
     
    // appel 
    alert(get_if_exist('test.level1.level2.level3'));
    Qui a pour principale contrainte que l'objet 'test' doit être global (ou du moins dans la porté de la fonction get_if_exist ... dépendant du comportement du (diabolique) "eval" selon la version du navigateur).

    Je propose donc une seconde solution un peu plus compliquée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function get_if_exist(obj){
      var a=arguments, b=a.callee; // replace a.callee by the function name you choose, in this case : get_if_exist
      // version 1 faisant appel à la version 2
      if(a[1] && ~a[1].indexOf('.')) 
        return b.apply(this,[obj].concat(a[1].split('.')));
      // version 2
      return a.length==1 ? a[0] : (obj[a[1]] && b.apply(this,[obj[a[1]]].concat([].slice.call(a,2))));
    }
     
    // appel (version 1)
    alert(get_if_exist(test,'level1.level2.level3'));
     
    // ou alternative (version 2)
    alert(get_if_exist(test,'level1','level2','level3'));
    Vous noterez que j'ai utilisé "callee" bien que déprécié en faveur du nom de la fonction, afin de laisser ceux qui reprendront ma fonction, l'utiliser en la nommant autrement (ou en ne la nommant pas du tout) sans avoir besoin de modifier son contenu pour déclencher l'appel récursif.

    Pour le puristes, il suffit de modifier le contenu et de remplacer a.callee par le nom que vous aurez choisi (pour une fonction nommée).

    Voila, faites-en bon usage.

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    eval(a='eval(a)')
    recursive make it evil
    eval make it eval

  2. #2
    Membre expérimenté Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Points : 1 519
    Points
    1 519
    Par défaut
    Zut, il y a un délai pour pouvoir éditer un poste :/


    J'ai un peu compressé le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function get_if_exist(o){
    	var a=arguments, b=a.callee; // don't use "use strict"; or replace "a.callee" by "get_if_exist" (or you name for this function)
    	return a[1]&&~a[1].indexOf('.')?b.apply(this,[o].concat(a[1].split('.'))):a.length>1?typeof o[a[1]]=='undefined'?undefined:b.apply(this,[o[a[1]]].concat([].slice.call(a,2))):a[0];
    }
    Utilisations:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // sample of object to test
    var obj = {l1:{0:{'false':'ok'}}};
     
    // use with each arguments as properties : return "ok"
    alert(get_if_exist(obj,'l1',0,'false'));
     
    // use with one string argument : return "ok"
    alert(get_if_exist(obj,'l1.0.false'));
     
    // use width invalid properties : return "undefined"
    alert(get_if_exist(obj,'l1','l2','l3','l4'));
     
    // use in condition
    if(get_if_exist(obj,'l1.0.false')){
    	// traitement
    };
     
    // use in condition with verification strict to prevent bug with values : 0, '', [], false, ..
    if(get_if_exist(obj,'l1.0.false')!=undefined){
    	// traitement
    };
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    eval(a='eval(a)')
    recursive make it evil
    eval make it eval

  3. #3
    Membre expérimenté Avatar de Willpower
    Homme Profil pro
    sans emploi
    Inscrit en
    Décembre 2010
    Messages
    1 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : sans emploi

    Informations forums :
    Inscription : Décembre 2010
    Messages : 1 009
    Points : 1 519
    Points
    1 519
    Par défaut
    Et juste pour le plaisir d'utiliser tous les mots clés / opérateurs les plus tordus possible dans une seule petite fonction :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    eval
    try catch
    apply
    call
    callee
    caller
    arguments
    typeof
    undefined
    ? : 
    ~
    Voici un mixte des 3 versions permettant les 3 types d'appels possibles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    function get_if_exist(o,p){
    	var a=arguments,b=a.callee,u=undefined,l=a.length; // don't use "use strict";
    	try{
    		return b.caller!=b&&l<2?eval(o):p&&~p.indexOf('.')?b.apply(this,[o].concat(p.split('.'))):l>1?typeof o[p]==u?u:b.apply(this,[o[p]].concat([].slice.call(a,2))):a[0]
    	}
    	catch(e){return u}
    }
    Exemples d'utilisations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    var obj2 = (function(){
    	var obj = {l1:{l2:{l3:'ok'}}};
     
    	// use with global version : return "undefined" (cause "get_if_exist" is defined outside of the scope)
    	alert(get_if_exist('obj.l1.l2.l3')); 
     
    	// use with each arguments as properties : return "ok"
    	alert(get_if_exist(obj,'l1','l2','l3'));
     
    	// use with one string argument : return "ok"
    	alert(get_if_exist(obj,'l1.l2.l3'));
     
    	// use width invalid properties : return "undefined"
    	alert(get_if_exist(obj,'l1','l2','l3','l4'));
     
    	// use in condition
    	if(get_if_exist(obj,'l1.l2.l3')){
    		// traitement
    		alert(1);
    	};
     
    	// use in condition with verification strict to prevent bug with values : 0, '', [], false, ..
    	if(get_if_exist(obj,'l1.l2.l3')!=undefined){
    		// traitement
    		alert(2);
    	};
     
    	return obj;
    })();
     
     
    // use with global version : return "ok"
    alert(get_if_exist('obj2.l1.l2.l3'));
    (oui, je m'ennuyais )

    Ai-je droit à la médaille de la fonction la plus dégueulasse au monde ?



    NB: Aussi surprenant soit-il, les 3 tests donnent exactement les même résultats sous IE, Firefox et Chrome.
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    eval(a='eval(a)')
    recursive make it evil
    eval make it eval

  4. #4
    Membre émérite
    Avatar de Kaamo
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    1 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 1 165
    Points : 2 778
    Points
    2 778
    Par défaut
    Malin !!
    Quid de parcourir tout l'arbre de l'objet jusqu'à ce qu'on trouve la propriété recherchée ? (ce que j'utilise dans un cas spécifique si on ne sait pas à quel niveau se trouve la propriété ... à voir niveau traitement, c'est assez gourmand)

    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var objTest = {level1: {level11: {level12:'ok1'} }, level2: {level21: {level22:'ok2'} }, level3: 'ok3'};
    function funcTest(obj, find) {
      for (var prop in obj) if (obj.hasOwnProperty(prop)){
        if (prop == find) {
          return true;
        } else if (typeof obj[prop] == 'object') {
          return funcTest(obj[prop], find);
        }
      }
      return false;
    }
     
    console.log(funcTest(objTest, 'level2')); // true
    console.log(funcTest(objTest, 'level12')); // true
    console.log(funcTest(objTest, 'coucou')); // false

  5. #5
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Points : 22 933
    Points
    22 933
    Billets dans le blog
    125
    Par défaut
    Suite à une question, petite précision sur le comportement de la méthode hasOwnProperty, elle détecte si un objet définit (en excluant son prototype) un élément.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var test = {
    	"level1" : {
    		"level2" : {
    			"level" : 'ok'
    		}
    	}
    };
     
    console.log( 'test.hasOwnProperty( "level1" ) = ', test.hasOwnProperty( "level1" ) ); // true
    console.log( 'test.level1.hasOwnProperty( "level2" ) = ', test.level1.hasOwnProperty( "level2" ) ); // true
    console.log( 'test.level1.level2.hasOwnProperty( "level" ) = ', test.level1.level2.hasOwnProperty( "level" ) ); // true
     
    console.log( 'test.hasOwnProperty( "level2" ) = ', test.hasOwnProperty( "level2" ) ); // false
    console.log( 'test.hasOwnProperty( "level" ) = ', test.hasOwnProperty( "level" ) ); // false

    Blog

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

Discussions similaires

  1. [JDBC]Tester l'existence d une table
    Par juflata dans le forum JDBC
    Réponses: 7
    Dernier message: 29/06/2004, 15h27
  2. tester l'existance d'un enregistrement
    Par LoLoSS dans le forum Langage SQL
    Réponses: 5
    Dernier message: 07/05/2004, 14h58
  3. tester l existence d un fichier sous turbo pascal
    Par Newllite dans le forum Turbo Pascal
    Réponses: 5
    Dernier message: 25/01/2004, 12h47
  4. Peut on tester l'existence d'un fichier ?
    Par Alamassepointcom dans le forum Flash
    Réponses: 2
    Dernier message: 10/10/2002, 12h10
  5. [ADO] Tester l'existence d'une table
    Par nd25 dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 05/09/2002, 13h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo