Question

Je suis passé par la plupart des questions. Également quelques articles bon et mauvais.

Une chose que je cherche des éclaircissements supplémentaires sur la façon dont est définie et non variables déclarées sont traitées.

Prenez le code ci-dessous.

var a;

if(a == null) // True - Due to Type Coercion

if(a == 'null') // False

if(a === null) // False

if(a === 'null') // False

if(a == undefined) // True

if(a === undefined) // True

if(a == 'undefined') // False

if(a === 'undefined') // False

if(a) // False - A is undefined

alert(typeof(a)) // undefined

Tous qui précède, je comprends. Mais les choses deviennent bizarre quand vous regardez une variable non déclarée. Note J'omets spécifiquement un "var b;".

 alert(typeof(b)) // undefined

 if(typeof(b) == 'undefined') // True

 if(typeof(b) === 'undefined') // True - This tells me the function typeof is returning a string value

 if(typeof(b) == 'null') // False

 if(typeof(b) === 'null') // False

 if(typeof(b) == null) // False

 if(typeof(b) === null) // False

 if(b) // Runtime Error - B is undefined

Toute autre opération puis typeof (b) entraîne une erreur d'exécution. Cependant, je peux comprendre la logique derrière la façon dont le laguage évalue les expressions.

Alors maintenant, je regarde une propriété non existante d'un et je suis vraiment confus.

if(a.c) // Runtime Error - c is null or not an object
alert(typeof(a.c)) // Runtime Error - undefined is null or not an object

Je pense que c dans ce cas serait traité comme b dans l'exemple précédent, mais ce ne est pas. Vous devez initialiser en fait un à quelque chose, vous pouvez l'obtenir à se comporter comme b fait. Et l'empêcher de lancer des erreurs d'exécution.

Pourquoi est-ce le cas? Y at-il un traitement spécial du type non défini ou est la fonction typeof faire quelque chose récursive pour évaluer la propriété sous qui jette l'erreur d'exécution?

  1. Je suppose que la question pratique est ici si je vérifie un objet imbriqué c dans a.c je peux immédiatement supposer c est indéfini si un est indéfini?

  2. Et quelle est la meilleure façon alors si je voulais vérifier un objet extrêmement imbriqué pour voir si elle a été définie comme x dans MyObject.Something.Something.Something.x? Je dois naviguer à travers l'élément de structure par élément en veillant à chacun existe avant d'aller à la suivante dans la chaîne?

Était-ce utile?

La solution

  

Je peux immédiatement supposer c est   undefined si un est indéfini?

Oui.

  

Je dois naviguer dans le   élément de structure par l'élément de décision   chacun existe que avant d'aller   la suivante dans la Chanin?

Oui.

Autres conseils

La raison pour laquelle

alert(typeof(a.c))

provoque une erreur d'exécution et

alert(typeof(b))

ne pas est que dans le premier exemple que vous essayez accéder à une propriété sur un objet non défini, ce qui provoque une erreur d'exécution avant le résultat peut être introduit dans typeof()

Ne pas oublier que undefined est variable globale, et vous (ou quelqu'un d'autre) peut lui attribuer une valeur, de sorte que votre exemple peut se tromper ici (!):

if(a == undefined) // True

if(a === undefined) // True

Si vous avez vraiment besoin non défini, vous pouvez obtenir votre propre « copie » de celui-ci

var local_undefined;

Normalement, vous ne rencontrerez la nécessité de tester un très (plus de trois niveaux) imbriqué objet où any des parents pourraient être undefined. Ainsi, lorsque vous avez besoin de tester, j'écrire quelque chose comme ceci:

if( typeof(a) != 'undefined' && a.c ) {
   // Do something won't run because a is undefined
}

var a = {};

if( typeof(a) != 'undefined' && a.c ) {
   // Do something won't run because though a is defined,
   // a.c is undefined. This expression tests to see if a.c evaluates
   // to true, but won't throw an error even if it is 
   // undefined.
}

Si a.c pourrait à tout moment contenir 0 ou false mais vous avez encore besoin le test à passer, utiliser le test complet typeof:

var a = {};
a.c = false;

if( typeof(a) != 'undefined' && typeof(a.c) != 'undefined' ) {
   // Do something will run because though both a and a.c are defined.
}

JavaScript est bizarre, (aussi undefined) la valeur typeof a === "undefined" est ce que les variables ont jusqu'à ce qu'ils reçoivent une valeur. null est une valeur distincte qui est différente de undefined. Étant donné que le système de type JavaScript est lâche il y a une contrainte de type implicite qui se produit lorsque l'on compare et tester les valeurs des variables.

Si une variable est noir, alors vous pouvez pas faire référence sans erreurs, mais vous pouvez le tester avec l'opérateur typeof (et son résultat sera la chaîne "undefined"). Une variable qui a été déclarée mais non affecté est en mesure d'être référencé, mais contient encore la valeur undefined. Vous pouvez toujours référencer des propriétés non définies d'objets et si elles ne sont pas affectés alors ils auront la valeur undefined.

Voir cette réponse aussi que je suis allé plus en détail sur la coercition de type JavaScript et des valeurs différentes qui sont souvent utiles à considérer vide:

Est-ce que EstVide de VBScript ont un équivalent en JavaScript?

  1. Lors du test des objets imbriqués, si le parent est undefined (ou null), il n'a pas d'enfant si aucun test supplémentaire est nécessaire.

  2. Pour tester en toute sécurité un objet fortement imbriqué vous devez tester le plus élevé parent à l'aide typeof mais vous pouvez tester tous les enfants pour les valeurs réelles ( voir le test de vide réponse). En effet, le haut niveau peut ne pas avoir été déclarée, mais vous pouvez toujours référencer des propriétés non définies d'objets.

profondément imbriquées enfants

try{ if(a.b.c.d.e) {
    // do your stuff
}}catch(e){}

try-catch route est un plus élégant et beaucoup moins solution de codage de type

Et voici un exemple:

grand=""
a={ b:{ c:{ d:{ e:"Hello Ancestor" } } } }

try{ if(a.b.c.d.e) {
    grand = a.b.c.d.e
}}catch(e){}

alert( grand )
  

juste jeter un oeil à la méthode typeof ennuyeux:

if(typeof a === undefined) {
    if(typeof a.b === undefined) {
        if(typeof a.b.c === undefined) {
            if(typeof a.b.c.d === undefined) {
                if(typeof a.b.c.d.e === undefined) {
                    // your stuff
                }
            }
        }
    }
}
  

Il pourrait être une solution encore plus élégante et idéale après avoir enveloppé le bloc try-catch dans une fonction, mais il n'y a aucun moyen connu de remplacer un nom variable référencée, ce qui pourrait être passé comme une « chaîne » à une fonction, avec la variable Contenu. par exemple. ci-dessous est pas possible:

function isDefined(v) {
    if (typeof valueOfVar(v) !== undefined)
        return true
    else
        return false
}
alert( isDefined('a.b.c.d.e') ) // must be passed as a string to avoid runtime error

il n'y a pas valueOfVar () existe en JavaScript, c'est juste un exemple

  

mais devinez quoi, je suis un enlightment, un mal solution:)

// a={ b:{ c:{ d:{ e:0 } } } }

function exist(v) {
    var local_undefined
    try{ if( eval(v) !== local_undefined ) {
        return true
    }}catch(e){}
    return false
}
alert( exist('a.b.c.d.e') )

Une mise à jour importante à la fonction existe () - deux fonctions supplémentaires qui utilisent existe ()

Ceux-ci couvrent tout ce qui est toujours nécessaire pour vérifier si un variable / propriété / object tout niveau d'imbrication défini / vide / noir sans jamais provoquer une erreur d'exécution JavaScript

function exists (v) {
    var local_undefined;
    try{ if( eval(v) !== local_undefined ) {
        return true
    }}catch(e){}
    return false
}

function empty (v) {
    if (exists(v)) {
        v = eval(v);
        if (typeof v == 'object') {
            return Object.keys(v).length === 0
        } else if (v)
            return false
    }
    return true
}

function value (v) {
    var local_undefined;
    if (exists(v))
        return eval(v)
    return local_undefined
}


/////////////////////////////////////////
// TEST

ref = 'a.b.c.d.e';

alert( ref +' : '+ value(ref) + '\n'
        + '\nexists\t' + exists(ref)
        + '\nempty\t' + empty(ref)
        + '\nvalue\t' + value(ref)
    );

a = { b:{ c:{ d:{ e:"Hello Ancestor" } } } };
alert( ref +' : '+ value(ref) + '\n'
        + '\nexists\t' + exists(ref)
        + '\nempty\t' + empty(ref)
        + '\nvalue\t' + value(ref)
    )

a = { b:{ c:{ d:{ e:0 } } } };
alert( ref +' : '+ value(ref) + '\n'
        + '\nexists\t' + exists(ref)
        + '\nempty\t' + empty(ref)
        + '\nvalue\t' + value(ref)
    );

b='a'; obj={a:5}; ref='obj[b]';
alert( ref +' : '+ value(ref) + '\n'
        + '\nexists\t' + exists(ref)
        + '\nempty\t' + empty(ref)
        + '\nvalue\t' + value(ref)
    );

Cependant, ces procédés travaillent que lorsque les fonctions de exists() empty() value() ont accès à ces variables, à savoir la fonction et les variables sont définies dans la même portée.

qui est nécessaire pour pouvoir tester les variables de la fonction locale trop, sinon les variables de la fonction locale qui sont déclarées avec var vont être undefined dans la fonction appelée exists() empty() value()

Pour tester la variable locale d'une fonction sans inclure exists() empty() value(), le bloc try/catch doit être utilisé dans cette fonction

  

Voici une alternative mal solution pour tester les variables de la fonction locale Ces extraits de code peuvent être définis dans le contexte global, puis appelé avec eval ()

is_ = "v_='"
var_ = "v_='"
get_ = "v_='"
set_ = "v_='"

_exists = "';\nvar local_undefined;\n"
        + "try{ if( eval(v_) === local_undefined ) false; else true }\n"
        + "catch(e){false}\n"

_empty = "';\nif ( eval(\"'\"+_exists) ) {\n"
        + " v_ = eval(v_);\n"
        + " if (typeof v_ == 'object') {\n"
        + "     Object.keys(v_).length === 0;\n"
        + " }\n\telse if (v_)\n"
        + "     false;\n"
        + " else true\n"
        + "} else true"

_value = "';\nif ( eval(\"'\"+_exists) )\n"
    + " eval(v_);\n"
    + "else local_undefined"

_valOrEmpty = "';\n( eval(\"'\"+_exists) )\n"
    + " ? eval(\"'\"+_value) : ''"

_valOrDefault_ = "';\n( eval(\"'\"+_exists) )\n"
    + " ? eval(\"'\"+_value) : "

function f() {
    var a = { b:{ c:{ d:{ e:"Hello Ancestor" } } } };
    ref = 'a.b.c.d.e'
    alert( ref+'\n'   
        +'\nexists\t\t'     + eval(is_  +ref+ _exists)
        +'\nempty\t\t'      + eval(is_  +ref+ _empty)
        +'\nvalue\t\t'      + eval(get_ +ref+ _value)
        +'\n'
        +'\nvalOrEmpty\t'   + eval(get_ +ref+ _valOrEmpty)
        +'\nvalOrDefault\t' + eval(get_ +ref+ _valOrDefault_ +'"Default Value"')
        )
}

d=""; while (d.length < 20) d="—"+d; d="\n\n// "+d+"\n// "
jsCode  ='// ( is_  +var+ _exists )\n\n'                + is_ +'a.b.c.d.e'+_exists
        +d+' ( is_  +var+ _empty )\n\n'                 + is_ +'a.b.c.d.e'+_empty
        +d+' ( get_ +var+ _value )\n\n'                 + get_+'a.b.c.d.e'+_value
        +d+' ( get_ +var+ _valOrEmpty )\n\n'            + var_+'a.b.c.d.e'+_valOrEmpty
        +d+' ( get_ +var+ _valOrDefault_ default )\n\n' + var_+'a.b.c.d.e'+_valOrDefault_+"'Default Value'"

alert(jsCode)

f()
// even though that looks ugly, this is the tidiest solution
// to the awkward 17-year old JavaScript error-handling

Cette sagesse

if ( eval(is_  +'any.var.or.property.from.local.or.global.scope'+ _exists) ) {
    // do your stuff
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top