Esiste una funzione standard per verificare la presenza di variabili nulle, indefinite o vuote in JavaScript?


2260

Esiste una funzione JavaScript universale che controlla che una variabile abbia un valore e garantisce che non lo sia undefinedo null? Ho questo codice, ma non sono sicuro che copra tutti i casi:

function isEmpty(val){
    return (val === undefined || val == null || val.length <= 0) ? true : false;
}


78
Protip, non farlo mai (truthy statement) ? true : false;. Fallo e basta (truthy statement);.
David Baucum,

5
@GeorgeJempty non è un duplicato, poiché l'altra risposta chiede in particolare le stringhe , mentre questa chiede informazioni sulle variabili .
Madbreaks

2
Qualsiasi risposta corretta a questa domanda si basa interamente sul modo in cui si definisce "vuoto".
Madbreaks

3
@Jay Non fa male nulla per quanto riguarda l'esecuzione del tuo codice. È troppo prolisso. Non diresti: "Hai fame è vero?" Devi solo "Hai fame" Quindi nel codice basta dire if (hungry) …invece di if (hungry === true) …. Come tutte le cose di programmazione in questo modo, è solo una questione di gusti. Più specifico dell'esempio fornito dall'OP, sta dicendo ancora più verbalmente: "Se è vero, allora vero, se non poi falso" Ma se è vero, allora è già vero. E, se è falso, è già falso. Questo è simile a dire "Se hai fame, allora lo sei, e in caso contrario non lo sei."
David Baucum,

Risposte:


4379

Puoi semplicemente verificare se la variabile ha un truthyvalore oppure no. Questo significa

if( value ) {
}

valuterà truese nonvalue è :

  • nullo
  • non definito
  • NaN
  • stringa vuota ("")
  • 0
  • falso

L'elenco sopra rappresenta tutti i possibili falsyvalori in ECMA- / Javascript. Lo trovi nelle specifiche nella ToBooleansezione.

Inoltre, se non si conosce l' esistenza di una variabile (ciò significa che se è stata dichiarata ) è necessario verificare con l' typeofoperatore. Per esempio

if( typeof foo !== 'undefined' ) {
    // foo could get resolved and it's defined
}

Se puoi essere sicuro che almeno una variabile sia dichiarata, dovresti verificare direttamente se ha unatruthy valore come mostrato sopra.

Ulteriori informazioni: http://typeofnan.blogspot.com/2011/01/typeof-is-fast.html


110
Che cosa succede se il valore è un falso booleano previsto. A volte vuoi dare un valore predefinito se non c'è nessun valore, che non funzionerà se è stato passato un falso booleano.
TruMan1

100
@ TruMan1: in tal caso (dove la tua logica impone la convalida) devi andare come if( value || value === false ). Lo stesso vale per tutti i valori falsi , dobbiamo convalidarli esplicitamente.
jAndy,

28
Tranne se value è un array. L'interpretazione di truthypotrebbe essere fuorviante. In tal caso dovremmo verificare la presenza value.length != 0di un array non vuoto.
utente

12
Voglio solo aggiungere che se si sente il ifcostrutto è sintatticamente troppo pesante, è possibile utilizzare l'operatore ternario, in questo modo: var result = undefined ? "truthy" : "falsy". Oppure, se si desidera solo per costringere a un valore booleano, utilizzare l' !!operatore, ad esempio !!1 // true, !!null // false.
KFL,

7
Si noti inoltre che ciò non controllerà le stringhe che contengono solo caratteri di spazi bianchi.
Christophe Roussy,

222

Il metodo dettagliato per verificare se il valore è indefinito o null è:

return value === undefined || value === null;

Puoi anche usare l' ==operatore ma questo si aspetta che tu conosca tutte le regole :

return value == null; // also returns true if value is undefined

33
Verifica del solo nullo undefinedpuò essere fatto in questo modo: if (value == null). Badate ==all'operatore che costringe. Se controlli in questo modo if (value === null || value === undefined), hai dimenticato / non sai come Javascript si coercita. webreflection.blogspot.nl/2010/10/…
Christiaan Westerbeek,

32
@ChristiaanWesterbeek: il tuo punto che arg == nullproduce gli stessi risultati di arg === undefined || arg === null. Tuttavia, considero quest'ultimo esempio più leggibile.
Salman A

10
arg == nullè abbastanza comune nella mia esperienza.
Bryan Downing,

8
return value === (void 0)è più sicuro dei test sui undefinedquali potrebbe purtroppo essere una portata legittima variabile.
x0n

4
@Sharky C'è una differenza tra una variabile non definita e una variabile non dichiarata: lucybain.com/blog/2014/null-undefined-undeclared
Christiaan Westerbeek,

80
function isEmpty(value){
  return (value == null || value.length === 0);
}

Questo tornerà vero per

undefined  // Because undefined == null

null

[]

""

e zero argomento funzioni da una funzione length è il numero di parametri dichiarati che accetta.

Per non consentire quest'ultima categoria, potresti voler controllare solo le stringhe vuote

function isEmpty(value){
  return (value == null || value === '');
}

7
undefined == nullmaundefined !== null
Ian Boyd il

2
@IanBoyd perché stai confrontando == con ===. questo significa che undefined == null (true) undefined! = null (false) undefined === null (false) undefined! == null (true) sarebbe meglio fornire un po 'più di informazioni per essere d'aiuto e spingere le persone nella giusta direzione. moz doc sulla differenza developer.mozilla.org/en-US/docs/Web/JavaScript/…
Corey Young

43

Questo è il controllo più sicuro e non l'ho visto pubblicato qui esattamente così:

if (typeof value !== 'undefined' && value) {
    //deal with value'
};

Tratterà i casi in cui il valore non è mai stato definito, e anche uno di questi:

  • nullo
  • undefined (il valore di undefined non è lo stesso di un parametro che non è mai stato definito)
  • 0
  • "" (stringa vuota)
  • falso
  • NaN

Modificato: cambiato in stretta uguaglianza (! ==) perché ormai è la norma;)


10
Non ho espresso il mio voto negativo, ma per quanto riguarda il rigoroso confronto sull'uguaglianza, la regola generale è che, a meno che tu non abbia bisogno di una conversione implicita del tipo, dovrebbe essere usato un confronto rigoroso.
J.Steve,

2
Grazie per il tuo commento Steve. Quella regola generale va bene. Mi aspetto solo che ppl capisca perché usano l'uno o l'altro. Ogni modo in cui sembri ppl sarà lieto di predicare "usa sempre sempre severi" - come se fosse la cosa più importante in Javascript. Ho visto troppi casi come if (val! == null) che ovviamente portano a un risultato indesiderato. Va bene dire che in caso di dubbio - usare rigoroso, ma è meglio non essere in dubbio.
guya

6
Penso che il punto qui sia che ci aspettiamo che l' typeofoperatore restituisca una stringa, quindi l'utilizzo del rigoroso controllo dell'uguaglianza è tecnicamente più accurato, più specifico e più veloce. Quindi davvero, non c'è motivo di usare il confronto libero, non il contrario. Inoltre val !== nullè perfettamente valido in molti casi - lo faccio sempre. Sono d'accordo con il tuo argomento di non conformità, ma penso che questo sia un cattivo esempio per farcela. Non sto cercando di trollarti.
Bryan Downing,

Grazie per il tuo commento Bryan, usi val! == null perché sai cosa stai facendo. Un principiante vorrà avere un fallback a quando val è falsa. Ma val non sarà mai nullo, non sarà definito. Se solo non avesse ascoltato quel consiglio di "usare sempre sempre severi" avrà meno bug. Ho visto che ciò accade nel codice di produzione. typeof restituisce sempre una stringa e la velocità diff sarà ridondante. Quindi, l'unico argomento per usare il rigoroso nel caso precedente è la coerenza. Ho detto "Non c'è bisogno di una rigorosa uguaglianza". Non significa che non puoi se vuoi o se rende il tuo codice più coerente.
Guya,

28

Potresti trovare utile la seguente funzione:

function typeOf(obj) {
  return {}.toString.call(obj).split(' ')[1].slice(0, -1).toLowerCase();
}

O in ES7 (commento se ulteriori miglioramenti)

function typeOf(obj) {
  const { toString } = Object.prototype;
  const stringified = obj::toString();
  const type = stringified.split(' ')[1].slice(0, -1);

  return type.toLowerCase();
}

risultati:

typeOf(); //undefined
typeOf(null); //null
typeOf(NaN); //number
typeOf(5); //number
typeOf({}); //object
typeOf([]); //array
typeOf(''); //string
typeOf(function () {}); //function
typeOf(/a/) //regexp
typeOf(new Date()) //date
typeOf(new WeakMap()) //weakmap
typeOf(new Map()) //map

"Si noti che l'operatore bind (: :) non fa parte di ES2016 (ES7) né alcuna versione successiva dello standard ECMAScript. Attualmente è una proposta di fase 0 (strawman) per essere introdotta nella lingua." - Simon Kjellberg. l'autore desidera aggiungere il suo sostegno a questa bellissima proposta di ricevere l'ascensione reale.


+1 è utile conoscere l'oggetto di tipo 'regexp' , 'array' e 'function'
Yash

@Vix, perché la versione ES7 è migliore?
GollyJer,

Non lo è, stava sperimentando modi più leggibili per esprimere la stessa funzionalità facendo uso di: compito di destrutturazione, operatore di rilegatura.
Vix,

2
Si noti che l'operatore bind ( ::) non fa parte di ES2016 (ES7) né di una versione successiva dello standard ECMAScript. Attualmente è una proposta di stage 0 (strawman) per essere introdotta nella lingua.
Simon Kjellberg,

25

La prima risposta con il miglior punteggio è sbagliata. Se il valore non è definito, verrà generata un'eccezione nei browser moderni. Devi usare:

if (typeof(value) !== "undefined" && value)

o

if (typeof value  !== "undefined" && value)

3
eee ... Penso che sia sbagliato come se (valore) fosse sufficiente (tranne oggetti / array vuoti). se il valore è 'indefinito' la confessione 'if' non passerà.
Oskar Szura,

3
Questo unisce variabili che non sono definite (che generano un errore di riferimento nella valutazione), che sono diverse dalle variabili con il undefinedvalore.
Qantas 94 Heavy

2
Ho avuto lo stesso errore qui. if (x), if (! x), if (!! x) genereranno tutti errori se x non è definito.
shaosh

if(value === 0) gameOver(); ;)
Madbreaks

Questa risposta è anche sbagliata perché restituisce false quando valueè zero, che non è ciò che op sta cercando.
Madbreaks

17

Questa verifica delle condizioni

if (!!foo) {
    //foo is defined
}

é tutto quello di cui hai bisogno.


Suppongo che questo sia solo uno snippet. Ma iffa già un controllo falso, che questo converte in un booleano. Cattura alcuni casi che un normale if(foo)non cattura?
Daan van Hulst,

1
Questo è perfetto per quando hai bisogno di qualcosa in linea, ad esempio ho bisogno di un attributo di reazione (chiamato attivo) che è vero quando una stringa non è vuota - un'istruzione if sarebbe eccessiva quindi posso semplicemente usareactive={!!foo}
Ben Kolya Mansley

16

! controlla le stringhe vuote (""), null, non definito, false e il numero 0 e NaN. Dire, se una stringa è vuota, var name = ""quindi console.log(!name)ritorna true.

function isEmpty(val){
  return !val;
}

questa funzione restituirà vero se val è vuoto, null, indefinito, falso, il numero 0 o NaN .

O

Secondo il tuo dominio problematico puoi semplicemente usare like !valo !!val.


Questo in realtà non dice se la variabile è vuota, poiché false e 0 possono essere valori validi e non costituire un valore vuoto. Il valore di avere una funzione isEmpty sarebbe assicurarsi che i valori che ti aspetti siano vuoti restituiscano vero. a mio avviso null, undefined, NaN e una stringa vuota sono i valori che hanno senso come vuoti.
Corey Young,

9
Perché usarlo isEmpty(val)se solo potessi farlo !val?
Allen Linatoc,

Spetta a voi. Puoi usarlo per aumentare la leggibilità. Altrimenti, se ritieni che il team in cui lavori siano programmatori più avanzati, puoi utilizzare solo !valo in !!valbase al tuo dominio problematico.
Arif,

15

Una soluzione che mi piace molto:

Definiamo che una variabile vuota è null, o undefined, o se ha lunghezza, è zero, o se è un oggetto, non ha chiavi:

function isEmpty (value) {
  return (
    // null or undefined
    (value == null) ||

    // has length and it's zero
    (value.hasOwnProperty('length') && value.length === 0) ||

    // is an Object and has no keys
    (value.constructor === Object && Object.keys(value).length === 0)
  )
}

Ritorna:

  • vero: undefined , null, "", [],{}
  • falso: true , false, 1, 0, -1, "foo", [1, 2, 3],{ foo: 1 }

14

Stai esagerando un po '. Per verificare se a una variabile non viene assegnato un valore, è necessario solo verificare undefined e null.

function isEmpty(value){
    return (typeof value === "undefined" || value === null);
}

Ciò presuppone 0, ""e gli oggetti (anche oggetto vuoto e matrice) sono "valori" validi.


10

Se preferisci javascript semplice prova questo:

  /**
   * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
   * length of `0` and objects with no own enumerable properties are considered
   * "empty".
   *
   * @static
   * @memberOf _
   * @category Objects
   * @param {Array|Object|string} value The value to inspect.
   * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
   * @example
   *
   * _.isEmpty([1, 2, 3]);
   * // => false
   *
   * _.isEmpty([]);
   * // => true
   *
   * _.isEmpty({});
   * // => true
   *
   * _.isEmpty('');
   * // => true
   */

function isEmpty(value) {
    if (!value) {
      return true;
    }
    if (isArray(value) || isString(value)) {
      return !value.length;
    }
    for (var key in value) {
      if (hasOwnProperty.call(value, key)) {
        return false;
      }
    }
    return true;
  }

Altrimenti, se stai già utilizzando il trattino basso o lodash, prova:

_.isEmpty(value)

3
Ho provato il tuo codice. Viene visualizzato un messaggio di errore nella console che dice: "Errore di riferimento non rilevato: isArray () non definito". Altrimenti, sarebbe fantastico se funzionasse.
crmprogdev,

11
Almeno nel caso di lodash, non _.isNilè la funzione che stai cercando _.isEmpty. Documentazione isNil , documentazione
isEmpty

Ciò fallirebbe se il valore è booleano e ha il valore vero.
Kalyanbk,

3
Il javascript normale non ha isArrayo isStringfunzioni sul window.
GFoley83

@ GFoley83 - Mi hai beccato! Ho i miei motivi per non usare Windows. In realtà tratterò l'argomento nel capitolo che parla della storia e della progressione dei linguaggi software. Informazioni più pertinenti saranno probabilmente la discussione / codice che dimostra la gestione degli errori monadici nel mio libro, Imparare la programmazione funzionale in corso. Saluti!
lx il

9

Ecco il mio - restituisce vero se il valore è null, indefinito, ecc. O vuoto (cioè contiene solo spazi vuoti):

function stringIsEmpty(value) {

    return value ? value.trim().length == 0 : true;

}

1
Ho fatto un test su diversi metodi qui. Con un controllo per indefinito, la tua funzione funziona alla grande. Quindi uso if (typeof value! == 'undefined' &&! IsEmpty (value)) OPPURE, se vuoi effettivamente controllare se è vuoto, puoi usare if (typeof value === 'undefined' || IsEmpty2 (value) ). Questo funzionerà per null; Non definito; 0; ""; ""; false
RationalRabbit

6
return val || 'Handle empty variable'

è un modo davvero piacevole e pulito per gestirlo in molti luoghi, può anche essere usato per assegnare variabili

const res = val || 'default value'

Un sacco di posti, ma non quando l'impostazione predefinita è truee stai cercando di fornire o restituire un valdi false.
Molomby

@Molomby è un caso limite molto specifico ma anche che è facilmente gestibileconst res = falsyValue ? true : falsyValue
cubefox

5

Se la variabile non è stata dichiarata, non sarà possibile verificare la presenza di un indefinito utilizzando una funzione perché si otterrà un errore.

if (foo) {}
function (bar) {}(foo)

Entrambi genereranno un errore se foo non è stato dichiarato.

Se si desidera verificare se è stata dichiarata una variabile, è possibile utilizzare

typeof foo != "undefined"

se si desidera verificare se foo è stato dichiarato e ha un valore che è possibile utilizzare

if (typeof foo != "undefined" && foo) {
    //code here
}

5

Per controllare il valore predefinito

function typeOfVar (obj) {
      return {}.toString.call(obj).split(' ')[1].slice(0, -1).toLowerCase();
}
function isVariableHaveDefaltVal(variable) {
    if ( typeof(variable) === 'string' ) {  // number, boolean, string, object 
        console.log(' Any data Between single/double Quotes is treated as String ');        
        return (variable.trim().length === 0) ? true : false;
    }else if ( typeof(variable) === 'boolean' ) {
      console.log('boolean value with default value \'false\'');
        return (variable === false) ? true : false;
    }else if ( typeof(variable) === 'undefined' ) {
        console.log('EX: var a; variable is created, but has the default value of undefined.'); 
        return true;
    }else if ( typeof(variable) === 'number' ) { 
        console.log('number : '+variable);
        return (variable === 0 ) ? true : false;
    }else if ( typeof(variable) === 'object' ) {
   //   -----Object-----
        if (typeOfVar(variable) === 'array' && variable.length === 0) {
            console.log('\t Object Array with length = ' + [].length); // Object.keys(variable)
            return true;
        }else if (typeOfVar(variable) === 'string' && variable.length === 0 ) {
            console.log('\t Object String with length = ' + variable.length);
            return true;
        }else if (typeOfVar(variable) === 'boolean' ) {
            console.log('\t Object Boolean = ' + variable);
            return (variable === false) ? true : false;
        }else if (typeOfVar(variable) === 'number' ) {
            console.log('\t Object Number = ' + variable);
            return (variable === 0 ) ? true : false;
        }else if (typeOfVar(variable) === 'regexp' && variable.source.trim().length === 0 ) {
       console.log('\t Object Regular Expression : ');
        return true;
        }else if (variable === null) {
       console.log('\t Object null value');
        return true;
        }
    }
    return false;
}
var str = "A Basket For Every Occasion";
str = str.replace(/\s/g, "-");
//The "g" flag in the regex will cause all spaces to get replaced.

controlla Risultato:

isVariableHaveDefaltVal(' '); // string          
isVariableHaveDefaltVal(false); // boolean       
var a;           
isVariableHaveDefaltVal(a);               
isVariableHaveDefaltVal(0); // number             
isVariableHaveDefaltVal(parseInt('')); // NAN isNAN(' '); - true         
isVariableHaveDefaltVal(null);              
isVariableHaveDefaltVal([]);               
isVariableHaveDefaltVal(/ /);              
isVariableHaveDefaltVal(new Object(''));               
isVariableHaveDefaltVal(new Object(false));            
isVariableHaveDefaltVal(new Object(0)); 
typeOfVar( function() {} );

Ho usato la funzione @Vix () per verificare l'oggetto di quale tipo.

usando instansof «

var prototypes_or_Literals = function (obj) {
    switch (typeof(obj)) {
        // object prototypes
        case 'object':
            if (obj instanceof Array)
                return '[object Array]';
            else if (obj instanceof Date)
                return '[object Date]';
            else if (obj instanceof RegExp)
                return '[object regexp]';
            else if (obj instanceof String)
                return '[object String]';
            else if (obj instanceof Number)
                return '[object Number]';

            else
                return 'object';
        // object literals
        default:
            return typeof(obj);
    }   
};
output test «
prototypes_or_Literals( '' ) // "string"
prototypes_or_Literals( new String('') ) // "[object String]"
Object.prototype.toString.call("foo bar") //"[object String]"        

Controlli degli operatori di confronto == [Dati]. === [Dati, tipo di oggetto] I numeri JS vengono sempre memorizzati come numeri in virgola mobile a precisione doppia, secondo lo standard internazionale IEEE 754. // Number Type [int, float literals ] var int = 77; var float = 77.7; console.log( int.toFixed(10) + '\t' + float.toFixed(10) ); // Object Type var number = new Number( 77 ); if( int != float ) console.log('Data Not Equal'); if( int == number && int !== number ) console.log('Data is Equal & Types vary');
Yash,

5
function isEmpty(obj) {
    if (typeof obj == 'number') return false;
    else if (typeof obj == 'string') return obj.length == 0;
    else if (Array.isArray(obj)) return obj.length == 0;
    else if (typeof obj == 'object') return obj == null || Object.keys(obj).length == 0;
    else if (typeof obj == 'boolean') return false;
    else return !obj;
}

In ES6 con trim per gestire stringhe di spazi bianchi:

const isEmpty = value => {
    if (typeof value === 'number') return false
    else if (typeof value === 'string') return value.trim().length === 0
    else if (Array.isArray(value)) return value.length === 0
    else if (typeof value === 'object') return value == null || Object.keys(value).length === 0
    else if (typeof value === 'boolean') return false
    else return !value
}

1
grande funzione, grazie! gestisce ogni tipo di valore - i numeri sono lasciati fuori in tutte le altre soluzioni!
Fabian von Ellerts,

1
@FabianvonEllerts Non tentare di modificare il codice aggiuntivo nella risposta di qualcun altro. Pubblica come tua risposta, come commento sotto la risposta, o richiedi in un commento di aggiornare la risposta da soli.
TylerH,

5

Potrebbe essere utile.

Tutti i valori nella matrice rappresentano ciò che vuoi essere (null, indefinito o altro) e cerchi ciò che vuoi in esso.

var variablesWhatILookFor = [null, undefined, ''];
variablesWhatILookFor.indexOf(document.DocumentNumberLabel) > -1

2
potresti spiegare per favore. cosa sta succedendo lì
JoshKisb il

L'array contiene alcune variabili che hai considerato vuote.
ddagsan,

@JoshKisb tutti i valori nella matrice rappresentano ciò che vuoi essere (null, indefinito o altro) e cerchi ciò che vuoi in esso.
ddagsan,

1
@ddagsan Sebbene JoshKisb possa apprezzare la tua risposta, dovresti inserire la tua spiegazione nella tua risposta piuttosto che nei commenti
Nick

4

Se stai usando TypeScripte non vuoi tenere conto di "valori che sono false" questa è la soluzione che fa per te:

Primo: import { isNullOrUndefined } from 'util';

Poi: isNullOrUndefined(this.yourVariableName)

Nota: come indicato di seguito, questo è ora obsoleto, utilizzare value === undefined || value === nullinvece. rif .


2
Ho pensato che fosse bello, quindi inizialmente non ho votato, ma è una cosa di Node.js che è stata deprecata. Il file delle definizioni dei tipi dice:/** @deprecated since v4.0.0 - use "value === null || value === undefined" instead. */
atomictom,

@atomictom Ho pensato che fosse una typescriptcosa. Potete per favore fornire il link della sua documentazione?
BlackBeard,

Qui: nodejs.org/api/util.html#util_util_isnullorundefined_object . Inoltre: "Ho pensato che fosse bello, quindi inizialmente ho votato " che dovrebbe leggere :)
atomictom

Perché deprecare una cosa semplice utile come questa? geeeeees.
ticktock

3

Vacuità

Non consiglio di provare a definire o utilizzare una funzione che calcola se un valore in tutto il mondo è vuoto. Cosa significa veramente essere "vuoti"? Se ho let human = { name: 'bob', stomach: 'empty' }, dovrebbe isEmpty(human)tornare true? Se ho let reg = new RegExp('');, dovrebbe isEmpty(reg)tornare true? Che dire isEmpty([ null, null, null, null ])- questo elenco contiene solo il vuoto, quindi l'elenco stesso è vuoto? Voglio presentare qui alcune note su "vacuità" (una parola intenzionalmente oscura, per evitare associazioni preesistenti) in javascript - e voglio sostenere che "vacuità" nei valori di javascript non dovrebbe mai essere trattata genericamente.


Truthiness / Falsiness

Per decidere come determinare la "vacuità" dei valori, dobbiamo soddisfare il senso innato e intrinseco di javascript sul fatto che i valori siano "veritieri" o "falsi". Naturalmente, nulle undefinedsono entrambi "falsi". Meno naturalmente, il numero 0(e nessun altro numero tranne NaN) è anche "falsa". Almeno naturalmente: ''è falso, ma []e {}(e new Set(), e new Map()) sono sinceri, anche se sembrano tutti ugualmente vacui!


Null vs Undefined

C'è anche qualche discussione riguardante il nullvs undefined: abbiamo davvero bisogno di entrambi per esprimere vacuità nei nostri programmi? Personalmente evito di far apparire nel mio codice le lettere u, n, d, e, f, i, n, e, d in questo ordine. Uso sempre nullper indicare "vacuità". Ancora una volta, tuttavia, dobbiamo soddisfare il senso intrinseco di JavaScript di come nulle undefineddifferire:

  • Cercare di accedere a una proprietà inesistente dà undefined
  • Se si omette un parametro quando si chiama una funzione, il parametro riceve undefined:

let f = a => a;
console.log(f('hi'));
console.log(f());

  • I parametri con valori predefiniti ricevono il valore predefinito solo se indicato undefined, non null:

let f = (v='hello') => v;
console.log(f(null));
console.log(f(undefined));


Vacuosità non generica

Credo che la vacuità non debba mai essere trattata in modo generico. Dovremmo invece sempre avere il rigore di ottenere maggiori informazioni sui nostri dati prima di determinare se sono vacui - lo faccio principalmente controllando il tipo di dati con cui ho a che fare:

let isType = (value, Cls) => {
  try {
    return Object.getPrototypeOf(value).constructor === Cls;
  } catch(err) {
    return false;
  }
};

Si noti che questa funzione ignora il polimorfismo: si aspetta valueche sia un'istanza diretta Clse non un'istanza di una sottoclasse di Cls. Evito instanceofper due motivi principali:

  • ([] instanceof Object) === true ("Una matrice è un oggetto")
  • ('' instanceof String) === false ("Una stringa non è una stringa")

Si noti che Object.getPrototypeOfviene utilizzato per evitare un caso come let v = { constructor: String };La isTypefunzione restituisce ancora correttamente per isType(v, String)(false) eisType(v, Object) (true).

Nel complesso, consiglio di utilizzare questa isTypefunzione insieme a questi suggerimenti:

  • Ridurre al minimo la quantità di valori di elaborazione del codice di tipo sconosciuto. Ad esempio, per let v = JSON.parse(someRawValue);, la nostra vvariabile è ora di tipo sconosciuto. Il prima possibile, dovremmo limitare le nostre possibilità. Il modo migliore per farlo può essere quello di richiedere un tipo particolare: ad esempio if (!isType(v, Array)) throw new Error('Expected Array');- questo è un modo davvero rapido ed espressivo per rimuovere la natura generica di v, e assicurarsi che sia sempre un Array. A volte, tuttavia, dobbiamo consentire vdi essere di più tipi. In questi casi, dovremmo creare blocchi di codice dove vnon è più generico, il più presto possibile:

if (isType(v, String)) {
  /* v isn't generic in this block - It's a String! */
} else if (isType(v, Number)) {
  /* v isn't generic in this block - It's a Number! */
} else if (isType(v, Array)) {
  /* v isn't generic in this block - it's an Array! */
} else {
  throw new Error('Expected String, Number, or Array');
}

  • Utilizzare sempre "whitelist" per la convalida. Se richiedi che un valore sia, ad esempio, una stringa, un numero o una matrice, controlla le 3 possibilità "bianche" e genera un errore se nessuna delle 3 è soddisfatta. Dovremmo essere in grado di vedere che il controllo per la possibilità di "nero" non è molto utile: Dire che scriviamo if (v === null) throw new Error('Null value rejected');- questo è grande per garantire che nulli valori non fanno fino in fondo, ma se un valore lo fa fare attraverso, sappiamo ancora poco niente al riguardo. Un valore vche supera questo controllo null è ancora MOLTO generico - è tutt'altro chenull ! Le blacklist difficilmente dissipano la genericità.
  • A meno che non sia un valore null, non considerare mai "un valore vacuo". Invece, considera "una X che è vacua". In sostanza, non considerare mai di fare qualcosa del genere if (isEmpty(val)) { /* ... */ }- non importa come isEmptysia implementata quella funzione (non voglio saperlo ...), non è significativo! Ed è troppo generico! La vacuità dovrebbe essere calcolata solo con la conoscenza del valtipo. I controlli di vacuità dovrebbero apparire così:

    • "Una stringa, senza caratteri": if (isType(val, String) && val.length === 0) ...
    • "Un oggetto, con 0 oggetti di scena": if (isType(val, Object) && Object.entries(val).length === 0) ...
    • "Un numero, uguale o inferiore a zero": if (isType(val, Number) && val <= 0) ...
    • "Una matrice, senza elementi": if (isType(val, Array) && val.length === 0) ...

    • L'unica eccezione è quando nullviene utilizzato per indicare determinate funzionalità. In questo caso è significativo dire: "Un valore vacuo":if (val === null) ...


Vedo che hai riflettuto su questo:>
Rui Marques

3

Prova con logica diversa . Puoi usare il codice seguente per controllare tutte e quattro le condizioni (4) per la convalida come non null, non vuoto, non definito e non zero utilizzare questo codice (! (! (Variabile))) in javascript e jquery.

function myFunction() {
    var data;  //The Values can be like as null, blank, undefined, zero you can test

    if(!(!(data)))
    {
        alert("data "+data);
    } 
    else 
    {
        alert("data is "+data);
    }
}

3

Dai un'occhiata al nuovo operatore di coalescenza Nullish ECMAScript

Puoi pensare a questa funzione - l' ??operatore - come un modo per "ripiegare" su un valore predefinito quando hai a che fare con nullo undefined.

let x = foo ?? bar();

Ancora una volta, il codice sopra è equivalente al seguente.

let x = (foo !== null && foo !== undefined) ? foo : bar();

2
function isEmpty(val){
    return !val;
}

ma questa soluzione è troppo ingegnerizzata, se non si desidera modificare la funzione in un secondo momento per le esigenze del modello aziendale, è più pulito utilizzarla direttamente nel codice:

if(!val)...

2
var myNewValue = myObject && myObject.child && myObject.child.myValue;

Questo non genererà mai un errore. Se myObject , child o myValue è null, myNewValue sarà null. Non verranno generati errori


2

Per tutti coloro che vengono qui per avere una domanda simile, il seguente funziona alla grande e ce l'ho nella mia biblioteca negli ultimi anni:

(function(g3, $, window, document, undefined){
   g3.utils = g3.utils || {};
/********************************Function type()********************************
* Returns a lowercase string representation of an object's constructor.
* @module {g3.utils}
* @function {g3.utils.type}
* @public
* @param {Type} 'obj' is any type native, host or custom.
* @return {String} Returns a lowercase string representing the object's 
* constructor which is different from word 'object' if they are not custom.
* @reference http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/
* http://stackoverflow.com/questions/3215046/differentiating-between-arrays-and-hashes-in-javascript
* http://javascript.info/tutorial/type-detection
*******************************************************************************/
g3.utils.type = function (obj){
   if(obj === null)
      return 'null';
   else if(typeof obj === 'undefined')
      return 'undefined';
   return Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1].toLowerCase();
};
}(window.g3 = window.g3 || {}, jQuery, window, document));

2

Se vuoi evitare di diventare vero se il valore è uno dei seguenti, secondo la risposta di jAndy :

  • nullo
  • non definito
  • NaN
  • stringa vuota ("")
  • 0
  • falso

Una possibile soluzione che potrebbe evitare di ottenere valori veritieri è la seguente:

function isUsable(valueToCheck) {
    if (valueToCheck === 0     || // Avoid returning false if the value is 0.
        valueToCheck === ''    || // Avoid returning false if the value is an empty string.
        valueToCheck === false || // Avoid returning false if the value is false.
        valueToCheck)             // Returns true if it isn't null, undefined, or NaN.
    {
        return true;
    } else {
        return false;
    }
}

Sarebbe usato come segue:

if (isUsable(x)) {
    // It is usable!
}
// Make sure to avoid placing the logical NOT operator before the parameter (isUsable(!x)) and instead, use it before the function, to check the returned value.
if (!isUsable(x)) {
    // It is NOT usable!
}

Oltre a questi scenari, potresti voler restituire false se l' oggetto o la matrice sono vuoti:

  • Oggetto: {} (utilizzando ECMA 7+ )
  • Matrice: [] (utilizzando ECMA 5+ )

Ci andresti in questo modo:

function isEmptyObject(valueToCheck) {
    if(typeof valueToCheck === 'object' && !Object.keys(valueToCheck).length){
        // Object is empty!
        return true;
    } else {
        // Object is not empty!
        return false;
    }
}

function isEmptyArray(valueToCheck) {
    if(Array.isArray(valueToCheck) && !valueToCheck.length) {
        // Array is empty!
        return true;
    } else {
        // Array is not empty!
        return false;
    }
}

Se si desidera verificare tutte le stringhe di spazi bianchi (""), è possibile effettuare le seguenti operazioni:

function isAllWhitespace(){
    if (valueToCheck.match(/^ *$/) !== null) {
        // Is all whitespaces!
        return true;
    } else {
        // Is not all whitespaces!
        return false;
    }
}

Nota: hasOwnPropertyrestituisce true per stringhe vuote, 0, false, NaN, null e non definito, se la variabile è stata dichiarata come una qualsiasi di esse, quindi potrebbe non essere la migliore da utilizzare. La funzione può essere modificata per usarla per mostrare che è stata dichiarata, ma non è utilizzabile.


2

Codice su GitHub

const isEmpty = value => (
  (!value && value !== 0 && value !== false)
  || (Array.isArray(value) && value.length === 0)
  || (isObject(value) && Object.keys(value).length === 0)
  || (typeof value.size === 'number' && value.size === 0)

  // `WeekMap.length` is supposed to exist!?
  || (typeof value.length === 'number'
      && typeof value !== 'function' && value.length === 0)
);

// Source: https://levelup.gitconnected.com/javascript-check-if-a-variable-is-an-object-and-nothing-else-not-an-array-a-set-etc-a3987ea08fd7
const isObject = value =>
  Object.prototype.toString.call(value) === '[object Object]';

Test da povero 😁

const test = () => {
  const run = (label, values, expected) => {
    const length = values.length;
    console.group(`${label} (${length} tests)`);
    values.map((v, i) => {
      console.assert(isEmpty(v) === expected, `${i}: ${v}`);
    });
    console.groupEnd();
  };

  const empty = [
    null, undefined, NaN, '', {}, [],
    new Set(), new Set([]), new Map(), new Map([]),
  ];
  const notEmpty = [
    ' ', 'a', 0, 1, -1, false, true, {a: 1}, [0],
    new Set([0]), new Map([['a', 1]]),
    new WeakMap().set({}, 1),
    new Date(), /a/, new RegExp(), () => {},
  ];
  const shouldBeEmpty = [
    {undefined: undefined}, new Map([[]]),
  ];

  run('EMPTY', empty, true);
  run('NOT EMPTY', notEmpty, false);
  run('SHOULD BE EMPTY', shouldBeEmpty, true);
};

Risultati del test:

EMPTY (10 tests)
NOT EMPTY (16 tests)
SHOULD BE EMPTY (2 tests)
  Assertion failed: 0: [object Object]
  Assertion failed: 1: [object Map]

ottima funzione, tutte le altre risposte qui hanno avuto più problemi che sembrano affrontare i tuoi, vorrei solo averlo trovato prima di aver scritto il mio: p ho pensato che ti sarebbe piaciuto dare un'occhiata al mio lavoro stackoverflow.com/ questions / 5515310 /… entrambe le nostre funzioni sembrano avere esattamente lo stesso output ma ho ridotto un po 'il codice. Per favore fatemi sapere se ho perso qualcosa.
Sean Bannister,

👍 Hai provato i miei "test per i poveri"? Penso di aver finito per aggiungere altri test nella funzione per casi speciali come Map, WeakMap e forse anche Date, RegExp. Sei sicuro del tuo value.constructor === Object? Controllare questo .
Pascal Polleunus il

Sì, ho eseguito i tuoi test, grazie per quelli, entrambe le nostre funzioni restituiscono gli stessi risultati con entrambi i nostri test. Continuo a chiedermi se mi manca qualcosa al di fuori di questi casi di test. Credo che value.constructor === Objectvada bene, in javascript le istruzioni OR hanno un ordine di esecuzione in modo che l'istruzione OR venga eseguita solo se la precedente non ha restituito VERO e abbiamo già verificato Null. In effetti, l'unico scopo di quest'ultima istruzione OR è quello di rilevare {}e assicurarsi che non restituisca VERO per cose che non dovrebbero.
Sean Bannister,

1

Questo verificherà se la variabile di annidamento indeterminato non è definita

function Undef(str) 
{
  var ary = str.split('.');
  var w = window;
  for (i in ary) {
    try      { if (typeof(w = w[ary[i]]) === "undefined") return true; }
    catch(e) { return true; }
  }
  return false;
}

if (!Undef("google.translate.TranslateElement")) {

Quanto sopra controlla se esiste la funzione di traduzione di Google TranslateElement. Ciò equivale a:

if (!(typeof google === "undefined" 
 || typeof google.translate === "undefined" 
 || typeof google.translate.TranslateElement === "undefined")) {

1

L'operatore di concatenamento opzionale fornisce un modo per semplificare l'accesso ai valori tramite oggetti connessi quando è possibile che un riferimento o una funzione possano essere indefiniti o nulli.

let customer = {
  name: "Carl",
  details: {
    age: 82,
    location: "Paradise Falls" // detailed address is unknown
  }
};
let customerCity = customer.details?.address?.city;

L'operatore di coalescenza nullish può essere utilizzato dopo il concatenamento facoltativo per creare un valore predefinito quando non ne viene trovato nessuno:

let customer = {
  name: "Carl",
  details: { age: 82 }
};
const customerCity = customer?.city ?? "Unknown city";
console.log(customerCity); // Unknown city

1
function notEmpty(value){
  return (typeof value !== 'undefined' && value.trim().length);
}

controllerà anche gli spazi bianchi ('') insieme a quanto segue:

  • null, non definito, NaN, vuoto, stringa (""), 0, falso

0

Penso che usando il? l'operatore è leggermente più pulito.

var ? function_if_exists() : function_if_doesnt_exist();
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.