variable - value is undefined in javascript




Rilevazione di una proprietà dell'oggetto non definita (20)

Qual è il modo migliore per verificare se una proprietà dell'oggetto in JavaScript non è definita?


' if (window.x) {} ' è sicuro da errori

Molto probabilmente lo vorrai if (window.x) . Questo controllo è sicuro anche se x non è stato dichiarato ( var x; ) - il browser non genera un errore.

Esempio: voglio sapere se il mio browser supporta l'API di cronologia

if (window.history) {
    history.call_some_function();
}

Come funziona:

window è un oggetto che contiene tutte le variabili globali come membri ed è legale provare ad accedere a un membro non esistente. Se x non è stato dichiarato o non è stato impostato, window.x restituisce undefined . undefined porta a false quando if () lo valuta.


Cosa significa: "proprietà dell'oggetto non definita" ?

In realtà può significare due cose completamente diverse! Primo, può significare la proprietà che non è mai stata definita nell'oggetto e, in secondo luogo, può significare la proprietà che ha un valore non definito . Diamo un'occhiata a questo codice:

var o = { a: undefined }

oa è indefinito? Sì! Il suo valore non è definito. ob è undefined? Sicuro! Non esiste affatto la proprietà "b"! OK, vedi ora come si comportano i diversi approcci in entrambe le situazioni:

typeof o.a == 'undefined' // true
typeof o.b == 'undefined' // true
o.a === undefined // true
o.b === undefined // true
'a' in o // true
'b' in o // false

Possiamo chiaramente vedere che typeof obj.prop == 'undefined' e obj.prop === undefined sono equivalenti e non distinguono queste diverse situazioni. E 'prop' in obj grado di rilevare la situazione quando una proprietà non è stata definita affatto e non presta attenzione al valore della proprietà che può essere indefinito.

Quindi che si fa?

1) Vuoi sapere se una proprietà non è definita dal primo o dal secondo significato (la situazione più tipica).

obj.prop === undefined // IMHO, see "final fight" below

2) Vuoi solo sapere se l'oggetto ha qualche proprietà e non importa del suo valore.

'prop' in obj

Gli appunti:

  • Non è possibile controllare un oggetto e le sue proprietà contemporaneamente. Ad esempio, questo xa === undefined o questo typeof xa == 'undefined' solleva ReferenceError: x is not defined se x non è definito.
  • La variabile undefined è una variabile globale (quindi in realtà è window.undefined nei browser). È stato supportato dalla prima edizione di ECMAScript e poiché ECMAScript 5 è di sola lettura . Quindi nei browser moderni non può essere ridefinito in modo vero come molti autori amano spaventarci, ma questo è ancora vero per i browser più vecchi.

Final fight: obj.prop === undefined vs typeof obj.prop == 'undefined'

Plus di obj.prop === undefined :

  • È un po 'più corto e sembra un po' più carino
  • Il motore JavaScript ti darà un errore se hai sbagliato l'ortografia undefined

obj.prop === undefined of obj.prop === undefined :

  • undefined può essere sovrascritto nei vecchi browser

Plus di typeof obj.prop == 'undefined' :

  • È davvero universale! Funziona con i browser nuovi e vecchi.

Minuses of typeof obj.prop == 'undefined' :

  • 'undefned' ( errato ) qui è solo una costante di stringa, quindi il motore JavaScript non può aiutarti se hai sbagliato ad ortografarlo come ho fatto io.

Aggiornamento (per JavaScript lato server):

Node.js supporta la variabile globale undefined come global.undefined (può anche essere utilizzata senza il prefisso 'global'). Non conosco altre implementazioni di JavaScript lato server.


Crossposting la mia answer dalla domanda correlata Come verificare la presenza di "undefined" in JavaScript?

Specifico per questa domanda, vedi casi di test con someObject.<whatever> .

Alcuni scenari che illustrano i risultati delle varie risposte: http://jsfiddle.net/drzaus/UVjM4/

(Si noti che l'uso di var per i test fa la differenza quando si trova in un wrapper con scope)

Codice di riferimento:

(function(undefined) {
    var definedButNotInitialized;
    definedAndInitialized = 3;
    someObject = {
        firstProp: "1"
        , secondProp: false
        // , undefinedProp not defined
    }
    // var notDefined;

    var tests = [
        'definedButNotInitialized in window',
        'definedAndInitialized in window',
        'someObject.firstProp in window',
        'someObject.secondProp in window',
        'someObject.undefinedProp in window',
        'notDefined in window',

        '"definedButNotInitialized" in window',
        '"definedAndInitialized" in window',
        '"someObject.firstProp" in window',
        '"someObject.secondProp" in window',
        '"someObject.undefinedProp" in window',
        '"notDefined" in window',

        'typeof definedButNotInitialized == "undefined"',
        'typeof definedButNotInitialized === typeof undefined',
        'definedButNotInitialized === undefined',
        '! definedButNotInitialized',
        '!! definedButNotInitialized',

        'typeof definedAndInitialized == "undefined"',
        'typeof definedAndInitialized === typeof undefined',
        'definedAndInitialized === undefined',
        '! definedAndInitialized',
        '!! definedAndInitialized',

        'typeof someObject.firstProp == "undefined"',
        'typeof someObject.firstProp === typeof undefined',
        'someObject.firstProp === undefined',
        '! someObject.firstProp',
        '!! someObject.firstProp',

        'typeof someObject.secondProp == "undefined"',
        'typeof someObject.secondProp === typeof undefined',
        'someObject.secondProp === undefined',
        '! someObject.secondProp',
        '!! someObject.secondProp',

        'typeof someObject.undefinedProp == "undefined"',
        'typeof someObject.undefinedProp === typeof undefined',
        'someObject.undefinedProp === undefined',
        '! someObject.undefinedProp',
        '!! someObject.undefinedProp',

        'typeof notDefined == "undefined"',
        'typeof notDefined === typeof undefined',
        'notDefined === undefined',
        '! notDefined',
        '!! notDefined'
    ];

    var output = document.getElementById('results');
    var result = '';
    for(var t in tests) {
        if( !tests.hasOwnProperty(t) ) continue; // bleh

        try {
            result = eval(tests[t]);
        } catch(ex) {
            result = 'Exception--' + ex;
        }
        console.log(tests[t], result);
        output.innerHTML += "\n" + tests[t] + ": " + result;
    }
})();

E risultati:

definedButNotInitialized in window: true
definedAndInitialized in window: false
someObject.firstProp in window: false
someObject.secondProp in window: false
someObject.undefinedProp in window: true
notDefined in window: Exception--ReferenceError: notDefined is not defined
"definedButNotInitialized" in window: false
"definedAndInitialized" in window: true
"someObject.firstProp" in window: false
"someObject.secondProp" in window: false
"someObject.undefinedProp" in window: false
"notDefined" in window: false
typeof definedButNotInitialized == "undefined": true
typeof definedButNotInitialized === typeof undefined: true
definedButNotInitialized === undefined: true
! definedButNotInitialized: true
!! definedButNotInitialized: false
typeof definedAndInitialized == "undefined": false
typeof definedAndInitialized === typeof undefined: false
definedAndInitialized === undefined: false
! definedAndInitialized: false
!! definedAndInitialized: true
typeof someObject.firstProp == "undefined": false
typeof someObject.firstProp === typeof undefined: false
someObject.firstProp === undefined: false
! someObject.firstProp: false
!! someObject.firstProp: true
typeof someObject.secondProp == "undefined": false
typeof someObject.secondProp === typeof undefined: false
someObject.secondProp === undefined: false
! someObject.secondProp: true
!! someObject.secondProp: false
typeof someObject.undefinedProp == "undefined": true
typeof someObject.undefinedProp === typeof undefined: true
someObject.undefinedProp === undefined: true
! someObject.undefinedProp: true
!! someObject.undefinedProp: false
typeof notDefined == "undefined": true
typeof notDefined === typeof undefined: true
notDefined === undefined: Exception--ReferenceError: notDefined is not defined
! notDefined: Exception--ReferenceError: notDefined is not defined
!! notDefined: Exception--ReferenceError: notDefined is not defined

Il problema si riduce a tre casi:

  1. L'oggetto ha la proprietà e il suo valore non è undefined .
  2. L'oggetto ha la proprietà e il suo valore undefined è undefined .
  3. L'oggetto non ha la proprietà.

Questo ci dice qualcosa che considero importante:

C'è una differenza tra un membro indefinito e un membro definito con un valore non definito.

Ma sfortunatamente il typeof obj.foo non ci dice quale dei tre casi abbiamo. Tuttavia possiamo combinare questo con "foo" in obj per distinguere i casi.

                               |  typeof obj.x === 'undefined' | !("x" in obj)
1.                     { x:1 } |  false                        | false
2.    { x : (function(){})() } |  true                         | false
3.                          {} |  true                         | true

Vale la pena notare che questi test sono uguali anche per le voci null

                               |  typeof obj.x === 'undefined' | !("x" in obj)
                    { x:null } |  false                        | false

Direi che in alcuni casi ha più senso (ed è più chiaro) per verificare se la proprietà è lì, che controllare se è indefinito, e l'unico caso in cui questo controllo sarà diverso è il caso 2, il caso raro di una voce effettiva nell'oggetto con un valore non definito.

Ad esempio: ho appena effettuato il refactoring di un gruppo di codice che aveva un sacco di controlli se un oggetto avesse una determinata proprietà.

if( typeof blob.x != 'undefined' ) {  fn(blob.x); }

Che era più chiaro se scritto senza un assegno per indefinito.

if( "x" in blob ) { fn(blob.x); }

Ma come è stato detto questi non sono esattamente gli stessi (ma sono più che sufficienti per le mie esigenze).


Leggendo questo, sono stupito di non averlo visto. Ho trovato più algoritmi che avrebbero funzionato per questo.

Mai definito

Se il valore di un oggetto non è mai stato definito, questo impedirà di restituire true se è definito come null o undefined . Ciò è utile se si desidera che venga restituito true per i valori impostati come undefined

if(obj.prop === void 0) console.log("The value has never been defined");

Definito come non definito o mai definito

Se vuoi che diventi true per i valori definiti con il valore di undefined , o mai definito, puoi semplicemente usare === undefined

if(obj.prop === undefined) console.log("The value is defined as undefined, or never defined");

Definito come un valore falsy, indefinito, nullo o mai definito.

Comunemente, le persone mi hanno chiesto un algoritmo per capire se un valore è falso, undefined o null . I seguenti lavori.

if(obj.prop == false || obj.prop === null || obj.prop === undefined) {
    console.log("The value is falsy, null, or undefined");
}


Non sono sicuro da dove provenga l'origine dell'uso di === con typeof , e come convenzione lo vedo usato in molte librerie, ma l'operatore typeof restituisce una stringa letterale, e lo sappiamo in anticipo, quindi perché dovresti vuoi anche controllarlo anche tu?

typeof x;                      // some string literal "string", "object", "undefined"
if (typeof x === "string") {   // === is redundant because we already know typeof returns a string literal
if (typeof x == "string") {    // sufficient

Nonostante sia stato raccomandato con veemenza da molte altre risposte qui, typeof è una cattiva scelta . Non dovrebbe mai essere usato per verificare se le variabili hanno un valore undefined , perché agisce come un controllo combinato del valore undefined e dell'esistenza di una variabile. Nella stragrande maggioranza dei casi, sai quando esiste una variabile, e typeof introdurrà il potenziale per un errore silenzioso se scrivi un errore nel nome della variabile o nella stringa 'undefined' .

var snapshot = …;

if (typeof snaposhot === 'undefined') {
    //         ^
    // misspelled¹ – this will never run, but it won’t throw an error!
}
var foo = …;

if (typeof foo === 'undefned') {
    //                   ^
    // misspelled – this will never run, but it won’t throw an error!
}

Quindi, a meno che non si stia eseguendo il rilevamento delle caratteristiche², dove c'è incertezza sulla presenza di un determinato nome nel campo di applicazione (come il controllo del typeof module !== 'undefined' come passaggio nel codice specifico di un ambiente CommonJS), typeof è una scelta dannosa quando viene utilizzato su una variabile e l'opzione corretta è quella di confrontare direttamente il valore:

var foo = …;

if (foo === undefined) {
    ⋮
}

Alcuni equivoci comuni su questo includono:

  • che la lettura di una variabile "non inizializzata" ( var foo ) o parametro ( function bar(foo) { … } , chiamata as bar() ) avrà esito negativo. Questo semplicemente non è vero - le variabili senza inizializzazione esplicita e i parametri a cui non sono stati dati i valori diventano sempre undefined e sono sempre in ambito.

  • che undefined può essere sovrascritto. C'è molto di più in questo. undefined non è una parola chiave in JavaScript. Invece, è una proprietà sull'oggetto globale con il valore Non definito. Tuttavia, dal momento che ES5, questa proprietà è stata di sola lettura e non configurabile . Nessun browser moderno consentirà di modificare la proprietà undefined e, a partire dal 2017, ciò è avvenuto da molto tempo. La mancanza di una modalità rigorosa non influisce sul comportamento undefined - rende solo dichiarazioni come undefined = 5 non fare nulla invece di lanciare. Poiché non è una parola chiave, è possibile dichiarare variabili con il nome undefined e tali variabili potrebbero essere modificate, rendendo questo modello comune una volta:

    (function (undefined) {
        // …
    })()
    

    più pericoloso dell'uso del globale undefined . Se devi essere compatibile ES3, sostituisci undefined con void 0 - non ricorrere a typeof . ( void è sempre stato un operatore unario che valuta il valore Non definito per qualsiasi operando).

Con il modo in cui le variabili si disinteressano, è il momento di affrontare la vera domanda: le proprietà degli oggetti. Non c'è motivo di usare mai typeof per le proprietà dell'oggetto. L'eccezione precedente relativa al rilevamento delle caratteristiche non si applica qui: typeof ha solo un comportamento speciale sulle variabili e le espressioni che fanno riferimento alle proprietà dell'oggetto non sono variabili.

Questo:

if (typeof foo.bar === 'undefined') {
    ⋮
}

è sempre esattamente equivalente a questo³:

if (foo.bar === undefined) {
    ⋮
}

e tenendo conto dei consigli di cui sopra, per evitare di confondere i lettori sul motivo per cui stai usando typeof , perché ha più senso usare === per verificare l'uguaglianza, perché potrebbe essere refactored per controllare il valore di una variabile più tardi, e perché sembra semplicemente migliore, dovresti sempre usare === undefined ³ anche qui .

Qualcos'altro da tenere in considerazione quando si tratta di proprietà degli oggetti è se si vuole veramente controllare per undefined . Un dato nome di proprietà può essere assente su un oggetto (producendo il valore undefined quando letto), presente sull'oggetto stesso con il valore undefined , presente sul prototipo dell'oggetto con il valore undefined o presente su uno di quelli con un valore non undefined valore. 'key' in obj ti dirà se una chiave è ovunque sulla catena di prototipi di un oggetto, e Object.prototype.hasOwnProperty.call(obj, 'key') ti dirà se è direttamente sull'oggetto. Non andrò nei dettagli in questa risposta sui prototipi e sull'uso di oggetti come mappe a chiave stringa, però, perché è principalmente inteso a contrastare tutti i cattivi consigli in altre risposte, indipendentemente dalle possibili interpretazioni della domanda originale. Leggi su prototipi di oggetti su MDN per di più!

¹ scelta insolita del nome della variabile di esempio? questo è il vero codice morto dall'estensione NoScript per Firefox.
² non dare per scontato che non sapendo che cosa è in ambito è ok in generale, però. vulnerabilità bonus causata dall'abuso dello scope dinamico: Project Zero 1225
³ assumendo di nuovo un ambiente ES5 + e quello undefined fa riferimento alla proprietà undefined dell'oggetto globale. sostituto void 0 altrimenti.


Uso:

Per verificare se la proprietà non è definita:

if (typeof something === "undefined") {
    alert("undefined");
}

Per verificare se la proprietà non è indefinita:

if (typeof something !== "undefined") {
    alert("not undefined");
}

Uso:

if (typeof something === "undefined") {
    alert("something is undefined");
}

Se una variabile oggetto che ha alcune proprietà puoi usare la stessa cosa in questo modo:

if (typeof my_obj.someproperties === "undefined"){
    console.log('the property is not available...'); // print into console
}

Anche le stesse cose possono essere scritte più brevi:

if (!variable){
    //do it if variable is Undefined
}

o

if (variable){
    //do it if variable is Defined
}

C'è un modo bello ed elegante per assegnare una proprietà definita a una nuova variabile se è definita o assegnare un valore predefinito ad essa come una riserva se non è definita.

var a = obj.prop || defaultValue;

È adatto se hai una funzione, che riceve una proprietà di configurazione aggiuntiva:

var yourFunction = function(config){

   this.config = config || {};
   this.yourConfigValue = config.yourConfigValue || 1;
   console.log(this.yourConfigValue);

}

Ora in esecuzione

yourFunction({yourConfigValue:2});
//=> 2

yourFunction();
//=> 1

yourFunction({otherProperty:5});
//=> 1

La soluzione non è corretta. In JavaScript,

null == undefined

ritornerà vero, perché entrambi sono "castati" su un booleano e sono falsi. Il modo corretto sarebbe di controllare

if (something === undefined)

che è l'operatore dell'identità ...


Passando attraverso i commenti, per coloro che vogliono controllare entrambi è indefinito o il suo valore è nullo:

//Just in JavaScript
var s; // Undefined
if (typeof s == "undefined" || s === null){
    alert('either it is undefined or value is null')
}

Se stai usando la libreria jQuery, allora jQuery.isEmptyObject()sarà sufficiente per entrambi i casi,

var s; // Undefined
jQuery.isEmptyObject(s); // Will return true;

s = null; // Defined as null
jQuery.isEmptyObject(s); // Will return true;

//Usage
if (jQuery.isEmptyObject(s)) {
    alert('Either variable:s is undefined or its value is null');
} else {
     alert('variable:s has value ' + s);
}

s = 'something'; // Defined with some value
jQuery.isEmptyObject(s); // Will return false;

Confronta con void 0, per la precisione.

if (foo !== void 0)

Non è così verboso come if (typeof foo !== 'undefined')


Io uso if (this.variable)per verificare se è definito. Semplice if (variable), consigliato sopra , non funziona per me. Si scopre che funziona solo quando la variabile è un campo di qualche oggetto, obj.someFieldper verificare se è definita nel dizionario. Ma possiamo usare thiso windowcome oggetto dizionario dal momento che qualsiasi variabile è un campo nella finestra corrente, come ho capito. Quindi ecco un test

if (this.abc) alert("defined"); else alert("undefined");

abc = "abc";
if (this.abc) alert("defined"); else alert("undefined");

In primo luogo rileva che la variabile abcnon è definita e viene definita dopo l'inizializzazione.


Sono sorpreso di non aver ancora visto questo suggerimento, ma ottiene ancora più specificità rispetto al test typeof. Utilizzare Object.getOwnPropertyDescriptor()se è necessario sapere se una proprietà dell'oggetto è stata inizializzata con undefinedo se non è mai stata inizializzata:

// to test someObject.someProperty
var descriptor = Object.getOwnPropertyDescriptor(someObject, 'someProperty');

if (typeof descriptor === 'undefined') {
  // was never initialized
} else if (typeof descriptor.value === 'undefined') {
  if (descriptor.get || descriptor.set) {
    // is an accessor property, defined via getter and setter
  } else {
    // is initialized with `undefined`
  }
} else {
  // is initialized with some other value
}

Tutte le risposte sono incomplete. Questo è il modo giusto per sapere che esiste una proprietà "definita come non definita":

var hasUndefinedProperty = function hasUndefinedProperty(obj, prop){
  return ((prop in obj) && (typeof obj[prop] == 'undefined')) ;
} ;

Esempio:

var a = { b : 1, e : null } ;
a.c = a.d ;

hasUndefinedProperty(a, 'b') ; // false : b is defined as 1
hasUndefinedProperty(a, 'c') ; // true : c is defined as undefined
hasUndefinedProperty(a, 'd') ; // false : d is undefined
hasUndefinedProperty(a, 'e') ; // false : e is defined as null

// And now...
delete a.c ;
hasUndefinedProperty(a, 'c') ; // false : c is undefined

Peccato che questa sia stata la risposta giusta seppellita in risposte sbagliate> _ <

Quindi, per tutti quelli che passano, ti darò gratuitamente gli infiniti !!

var undefined ; undefined ; // undefined
({}).a ;                    // undefined
[].a ;                      // undefined
''.a ;                      // undefined
(function(){}()) ;          // undefined
void(0) ;                   // undefined
eval() ;                    // undefined
1..a ;                      // undefined
/a/.a ;                     // undefined
(true).a ;                  // undefined

"propertyName" in obj //-> true | false

function isUnset(inp) {
  return (typeof inp === 'undefined')
}

Restituisce false se la variabile è impostata e true se non è definita.

Quindi utilizzare:

if (isUnset(var)) {
  // initialize variable here
}






undefined