Existe-t-il une fonction standard pour vérifier les variables nulles, non définies ou vides en JavaScript?

2262

Existe-t-il une fonction JavaScript universelle qui vérifie qu'une variable a une valeur et s'assure qu'elle ne l'est pas undefinedou null? J'ai ce code, mais je ne sais pas s'il couvre tous les cas:

function isEmpty(val){
    return (val === undefined || val == null || val.length <= 0) ? true : false;
}
Alex
la source
5
doublon possible de Comment vérifier une chaîne vide en JavaScript?
Dour High Arch
78
Protip, ne fais jamais (truthy statement) ? true : false;. Faites-le (truthy statement);.
David Baucum
5
@GeorgeJempty n'est pas un dup, puisque l'autre réponse porte sur les chaînes en particulier, alors que celle-ci pose sur les variables .
Madbreaks
2
Toute réponse correcte à cette question dépend entièrement de la façon dont vous définissez "vide".
Madbreaks
3
@Jay Cela ne fait rien de mal jusqu'à l'exécution de votre code. C'est juste trop verbeux. Vous ne diriez pas: "Avez-vous faim, c'est vrai?" Vous venez de "Avez-vous faim" Donc, dans le code, dites simplement if (hungry) …au lieu de if (hungry === true) …. Comme toutes les choses de codage de cette manière, c'est juste une question de goût. Plus spécifique à l'exemple fourni par l'OP, il dit encore plus verbalement: "Si c'est vrai, alors vrai, sinon faux" Mais si c'est vrai, alors c'est déjà vrai. Et si c'est faux, c'est déjà faux. Cela revient à dire: "Si vous avez faim, vous en avez et sinon, vous ne l’avez pas."
David Baucum

Réponses:

4381

Vous pouvez simplement vérifier si la variable a une truthyvaleur ou non. Cela signifie

if( value ) {
}

évaluera truesi ce valuen'est pas le cas :

  • nul
  • indéfini
  • NaN
  • chaîne vide ("")
  • 0
  • faux

La liste ci-dessus représente toutes les falsyvaleurs possibles en ECMA- / Javascript. Trouvez-le dans la spécification auToBoolean section.

De plus, si vous ne savez pas si une variable existe (c'est-à-dire si elle a été déclarée ), vous devriez vérifier auprès de l' typeofopérateur. Par exemple

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

Si vous pouvez être sûr qu'une variable est déclarée au moins, vous devez vérifier directement si elle a untruthy valeur comme indiqué ci-dessus.

Pour en savoir plus: http://typeofnan.blogspot.com/2011/01/typeof-is-fast.html

jAndy
la source
110
Et si la valeur est un faux booléen qui était prévu. Parfois, vous voulez donner une valeur par défaut s'il n'y a pas de valeur, ce qui ne fonctionnera pas si un faux booléen a été transmis.
TruMan1
100
@ TruMan1: dans un tel cas (où votre logique dicte la validation) vous devez aller comme if( value || value === false ). Il en va de même pour toutes les valeurs de falsification , nous devons les valider explicitement.
jAndy
28
Sauf si la valeur est un tableau. L'interprétation de truthypourrait être trompeuse. Dans ce cas, nous devrions value.length != 0rechercher un tableau non vide.
utilisateur
12
Je veux juste ajouter que si vous vous sentez la ifconstruction est syntaxiquement trop lourd, vous pouvez utiliser l'opérateur ternaire, comme suit: var result = undefined ? "truthy" : "falsy". Ou si vous voulez juste forcer à une valeur booléenne, utilisez l' !!opérateur, par exemple !!1 // true, !!null // false.
KFL
7
Notez également que cela ne vérifiera pas les chaînes qui ne contiennent que des espaces blancs.
Christophe Roussy
222

La méthode détaillée pour vérifier si la valeur n'est pas définie ou nulle est:

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

Vous pouvez également utiliser l' ==opérateur, mais celui-ci attend de connaître toutes les règles :

return value == null; // also returns true if value is undefined
Salman A
la source
33
Vérification seulement nullou undefinedpeut être fait comme ceci: if (value == null). Attention à l' ==opérateur qui contraint. Si vous cochez comme ceci if (value === null || value === undefined), vous avez oublié / ne sais pas comment Javascript coercit. webreflection.blogspot.nl/2010/10/…
Christiaan Westerbeek
32
@ChristiaanWesterbeek: votre point qui arg == nullproduit les mêmes résultats que arg === undefined || arg === null. Cependant, je considère ce dernier exemple plus lisible.
Salman A
10
arg == nullest assez commun dans mon expérience.
Bryan Downing du
8
return value === (void 0)est plus sûr que de tester par rapport à undefinedce qui pourrait bien être une variable légitime dans la portée, malheureusement.
x0n
4
@Sharky Il y a une différence entre une variable non définie et une variable non déclarée: lucybain.com/blog/2014/null-undefined-undeclared
Christiaan Westerbeek
80
function isEmpty(value){
  return (value == null || value.length === 0);
}

Cela reviendra vrai pour

undefined  // Because undefined == null

null

[]

""

et zéro fonction d'argument car une fonction lengthest le nombre de paramètres déclarés qu'elle prend.

Pour interdire cette dernière catégorie, vous voudrez peut-être simplement vérifier les chaînes vides

function isEmpty(value){
  return (value == null || value === '');
}
Mike Samuel
la source
7
undefined == nullmaisundefined !== null
Ian Boyd
2
@IanBoyd c'est parce que vous comparez == à ===. cela signifie qu'undefined == null (true) undefined! = null (false) undefined === null (false) undefined! == null (true) serait préférable de donner un peu plus d'informations afin d'être utile et de pousser les gens dans la bonne direction. doc moz sur la différence developer.mozilla.org/en-US/docs/Web/JavaScript/…
Corey Young
43

C'est le chèque le plus sûr et je ne l'ai pas vu affiché exactement comme ça:

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

Il couvrira les cas où la valeur n'a jamais été définie, et également l'un d'eux:

  • nul
  • undefined (la valeur de undefined n'est pas la même chose qu'un paramètre qui n'a jamais été défini)
  • 0
  • "" (chaîne vide)
  • faux
  • NaN

Modifié: changé en stricte égalité (! ==) car c'est la norme maintenant;)

guya
la source
10
Je n'ai pas déçu, mais en ce qui concerne la comparaison stricte d'égalité, la règle générale est que, sauf si vous avez besoin d' une conversion de type implicite, une comparaison stricte doit être utilisée.
J.Steve
2
Merci pour votre commentaire Steve. Cette règle générale est très bien. Je m'attends juste à ce que ppl comprenne pourquoi ils utilisent l'un ou l'autre. Chaque fois que vous regardez, ppl se fera un plaisir de vous prêcher sur "toujours toujours strict" - comme c'est la chose la plus importante en Javascript. J'ai vu trop de cas comme if (val! == null) qui conduisent évidemment à un résultat indésirable. C'est bien de dire qu'en cas de doute - utilisez strict, mais il vaut mieux ne pas en douter.
guya
6
Je pense que le point ici est que nous nous attendons à ce que l' typeofopérateur retourne une chaîne, donc l'utilisation du contrôle d'égalité stricte est techniquement plus précise, plus spécifique et plus rapide. Donc, vraiment, il n'y a aucune raison d'utiliser la comparaison lâche, pas l'inverse. Est également val !== nullparfaitement valable dans de nombreux cas - je le fais tout le temps. Je suis d'accord avec votre argument de non-conformité, mais je pense que c'est un mauvais exemple pour le faire. Je n'essaye pas de te troller.
Bryan Downing du
Merci pour votre commentaire Bryan, vous utilisez val! == null parce que vous savez ce que vous faites. Un débutant voudra avoir un repli sur quand val est faux. Mais, val ne sera jamais nul, il sera indéfini. Si seulement il n'écoutait pas ce conseil de «toujours toujours utiliser strictement» il aura moins de bugs. J'ai vu cela se produire dans le code de production. typeof renvoie toujours une chaîne et le différentiel de vitesse sera redondant. Ainsi, le seul argument pour utiliser strict dans le cas ci-dessus est la cohérence. J'ai dit «Pas besoin d'une égalité stricte». Cela ne signifie pas que vous ne pouvez pas si vous le souhaitez ou si cela rend votre code plus cohérent.
guya
28

Vous pouvez trouver la fonction suivante utile:

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

Ou dans ES7 (commentez si d'autres améliorations)

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

  return type.toLowerCase();
}

Résultats:

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

"Notez que l'opérateur de liaison (: :) ne fait pas partie de ES2016 (ES7) ni d'aucune édition ultérieure de la norme ECMAScript. C'est actuellement une proposition de l'étape 0 (homme de paille) à introduire dans la langue." - Simon Kjellberg. l'auteur souhaite ajouter son soutien à cette belle proposition de recevoir l'ascension royale.

Vix
la source
+1 il est utile de connaître l'objet de type 'regexp' , 'array' et 'function'
Yash
@Vix, pourquoi la version ES7 est-elle meilleure?
GollyJer
Ce n'est pas le cas, expérimentait des façons plus lisibles d'exprimer la même fonctionnalité en utilisant: assignation de déstructuration, opérateur de liaison.
Vix
2
Notez que l'opérateur de liaison ( ::) ne fait pas partie de ES2016 (ES7) ni d'aucune édition ultérieure de la norme ECMAScript. C'est actuellement une proposition de l'étape 0 (homme de paille) pour être introduit dans la langue.
Simon Kjellberg
25

La première réponse avec la meilleure note est fausse. Si la valeur n'est pas définie, elle lèvera une exception dans les navigateurs modernes. Vous devez utiliser:

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

ou

if (typeof value  !== "undefined" && value)
krupar
la source
3
eee ... Je pense que c'est faux comme si (valeur) était suffisant (sauf les objets / tableaux vides). si la valeur n'est pas définie, la confition «if» ne passera pas.
Oskar Szura du
3
Cela confond les variables qui ne sont pas définies (qui lancent une ReferenceError lors de l'évaluation), qui sont différentes des variables avec la undefinedvaleur.
Qantas 94 Heavy
2
J'ai la même erreur ici. if (x), if (! x), if (!! x) générera tous des erreurs si x n'est pas défini.
shaosh
if(value === 0) gameOver(); ;)
Madbreaks
Cette réponse est également fausse car elle retourne false quand valueest zéro, ce qui n'est pas ce que op recherche.
Madbreaks
17

Cette vérification de l'état

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

est tout ce dont vous avez besoin.

JerryP
la source
Je suppose que ce n'est qu'un extrait de code. Mais effectue ifdéjà un contrôle de falsification, que cela convertit simplement en un booléen. Attrape-t-il des cas qu'une normale if(foo)n'attrape pas?
Daan van Hulst
1
C'est parfait lorsque vous avez besoin de quelque chose en ligne, par exemple, j'ai besoin d'un attribut react (appelé actif) qui est vrai quand une chaîne n'est pas vide - une instruction if serait exagérée pour que je puisse simplement l'utiliseractive={!!foo}
Ben Kolya Mansley
16

! vérifier les chaînes vides (""), null, undefined, false et le nombre 0 et NaN. Disons que si une chaîne est vide, var name = ""elle console.log(!name)revient true.

function isEmpty(val){
  return !val;
}

cette fonction retournera true si val est vide, null, non défini, false, le nombre 0 ou NaN .

OU

Selon votre domaine de problème, vous pouvez simplement utiliser comme !valou !!val.

Arif
la source
Cela ne dit pas vraiment si la variable est vide, car false et 0 peuvent être des valeurs valides et ne constituent pas une valeur vide. La valeur d'avoir une fonction isEmpty serait de s'assurer que les valeurs que vous attendez qui sont vides retournent true. à mon avis, null, undefined, NaN et une chaîne vide sont les valeurs qui ont du sens comme vides.
Corey Young
9
Pourquoi utiliser isEmpty(val)si vous pouviez simplement faire !val?
Allen Linatoc
C'est comme tu veux. Vous pouvez l'utiliser pour augmenter la lisibilité. Sinon, si vous pensez que l'équipe que vous travaillez est un codeur plus avancé, vous pouvez utiliser juste !valou !!valselon votre domaine de problème.
Arif
15

Une solution que j'aime beaucoup:

Définissons qu'une variable vide est null, ou undefined, ou si elle a une longueur, elle est nulle, ou si c'est un objet, elle n'a pas de clés:

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)
  )
}

Retour:

  • vrai: undefined , null, "", [],{}
  • faux: true , false, 1, 0, -1, "foo", [1, 2, 3],{ foo: 1 }
Alexandre Magro
la source
14

Vous en faites un peu trop. Pour vérifier si une variable ne reçoit pas de valeur, il vous suffit de vérifier par rapport à undefined et null.

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

Cela suppose 0, ""et des objets (même objet et tableau vide) sont valides « valeurs ».

tcooc
la source
10

Si vous préférez le javascript simple, essayez ceci:

  /**
   * 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;
  }

Sinon, si vous utilisez déjà un trait de soulignement ou un lodash, essayez:

_.isEmpty(value)
l3x
la source
3
J'ai essayé votre code. Je reçois un message d'erreur dans la console qui dit: "Erreur de référence non capturée: isArray () n'est pas défini". Sinon, ce serait génial si cela fonctionnait.
crmprogdev
11
Dans le cas du lodash au moins, _.isNilc'est la fonction que vous recherchez, non _.isEmpty. documentation isNil , documentation isEmpty
Snixtor
Cela échouerait si la valeur est booléenne et a la valeur true.
kalyanbk
3
Le Javascript simple n'a pas isArrayou ne isStringfonctionne pas sur le window.
GFoley83
@ GFoley83 - Tu m'as rattrapé! J'ai mes raisons de ne pas utiliser Windows. En fait, je couvre le sujet dans le chapitre qui parle de l'histoire et de la progression des langages logiciels. Des informations plus pertinentes seront probablement la discussion / le code démontrant la gestion des erreurs monadiques dans mon livre, Learn Functional Programming in Go. À votre santé!
l3x
9

Voici le mien - renvoie vrai si la valeur est nulle, non définie, etc. ou vide (c'est-à-dire ne contient que des espaces vides):

function stringIsEmpty(value) {

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

}
DavidWainwright
la source
1
J'ai fait un test sur plusieurs méthodes ici. Avec une vérification pour indéfini, votre fonction fonctionne très bien. J'utilise donc if (typeof value! == 'undefined' &&! IsEmpty (value)) OU, si vous voulez réellement vérifier vide, vous pouvez utiliser if (typeof value === 'undefined' || IsEmpty2 (value) ). Cela fonctionnera pour null; Indéfini; 0; ""; ""; false
RationalRabbit
6
return val || 'Handle empty variable'

est un moyen très agréable et propre de le gérer dans de nombreux endroits, peut également être utilisé pour attribuer des variables

const res = val || 'default value'
cubefox
la source
Beaucoup d'endroits mais pas quand la valeur par défaut est trueet vous essayez de fournir ou de renvoyer un valde false.
Molomby
@Molomby qui est un cas de bord très spécifique, mais même qui est facilement manipuléconst res = falsyValue ? true : falsyValue
cubefox
5

Si la variable n'a pas été déclarée, vous ne pourrez pas tester l'indéfini en utilisant une fonction car vous obtiendrez une erreur.

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

Les deux généreront une erreur si foo n'a pas été déclaré.

Si vous voulez tester si une variable a été déclarée, vous pouvez utiliser

typeof foo != "undefined"

si vous voulez tester si foo a été déclaré et qu'il a une valeur que vous pouvez utiliser

if (typeof foo != "undefined" && foo) {
    //code here
}
herostwist
la source
5

Pour vérifier la valeur par défaut

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.

vérifier Résultat:

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() {} );

J'ai utilisé la fonction @Vix () pour vérifier l'objet de quel type.

en utilisant 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]"        
Yash
la source
Les opérateurs de comparaison vérifient == [Données]. === [Données, type d'objet] Les nombres JS sont toujours stockés sous forme de nombres à virgule flottante double précision, conformément à la norme internationale 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;
}

En ES6 avec garniture pour gérer les chaînes d'espaces:

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
}
jales cardoso
la source
1
grande fonction, merci! gère tous les types de valeur - les chiffres sont omis dans toutes les autres solutions!
Fabian von Ellerts
1
@FabianvonEllerts Veuillez ne pas essayer de modifier du code supplémentaire dans la réponse de quelqu'un d'autre. Publiez-le comme votre propre réponse, comme un commentaire sous la réponse, ou demandez dans un commentaire qu'ils mettent à jour la réponse eux-mêmes.
TylerH
5

Cela peut être utile.

Toutes les valeurs du tableau représentent ce que vous voulez être (nul, non défini ou autre) et vous recherchez ce que vous voulez dedans.

var variablesWhatILookFor = [null, undefined, ''];
variablesWhatILookFor.indexOf(document.DocumentNumberLabel) > -1
ddagsan
la source
2
pourriez-vous expliquer s'il vous plaît. ce qui se passe là
JoshKisb
Le tableau contient une variable que vous supposiez vide.
ddagsan
@JoshKisb toutes les valeurs du tableau représentent ce que vous voulez être (nul, non défini ou autre) et vous recherchez ce que vous voulez dedans.
ddagsan
1
@ddagsan Bien que JoshKisb puisse apprécier votre réponse, vous devriez mettre votre explication dans votre réponse plutôt que dans les commentaires
Nick
4

Si vous utilisez TypeScriptet que vous ne voulez pas prendre en compte les "valeurs qui sont false", voici la solution pour vous:

Première: import { isNullOrUndefined } from 'util';

Alors: isNullOrUndefined(this.yourVariableName)

Remarque: comme mentionné ci - dessous, il est désormais obsolète, utilisez-le à la value === undefined || value === nullplace.réf .

Blackeard
la source
2
Je pensais que c'était cool donc j'ai initialement voté, mais c'est une chose Node.js qui est déconseillée. Le fichier de définitions de type dit:/** @deprecated since v4.0.0 - use "value === null || value === undefined" instead. */
atomictom
@atomictom Je pensais que c'était une typescriptchose. Pouvez-vous fournir le lien de sa documentation?
BlackBeard
Ici: nodejs.org/api/util.html#util_util_isnullorundefined_object . Aussi: "Je pensais que c'était cool donc j'ai initialement voté " qui devrait lire :)
atomictom
Pourquoi le déprécier une chose simple et utile comme ça? geeeeees.
ticktock
3

Vacuité

Je ne recommande pas d'essayer de définir ou d'utiliser une fonction qui calcule si une valeur dans le monde entier est vide. Que signifie vraiment être "vide"? Si je l'ai let human = { name: 'bob', stomach: 'empty' }, devrait isEmpty(human)revenir true? Si je l'ai let reg = new RegExp('');, devrait isEmpty(reg)revenirtrue ? Qu'en est-il isEmpty([ null, null, null, null ])- cette liste ne contient que du vide, donc la liste elle-même est-elle vide? Je veux présenter ici quelques notes sur la "vacuité" (un mot intentionnellement obscur, pour éviter les associations préexistantes) en javascript - et je veux faire valoir que la "vacuité" dans les valeurs javascript ne doit jamais être traitée de manière générique.


Vérité / fausseté

Pour décider comment déterminer la «vacuité» des valeurs, nous devons tenir compte du sens intrinsèque intégré de javascript de savoir si les valeurs sont «véridiques» ou «fausses». Naturellement, nullet undefinedsont tous les deux "falsifiés". Moins naturellement, le nombre 0(et aucun autre nombre sauf NaN) est également "falsifié". Le moins naturellement: ''est faux, mais []et {}(et new Set(), et new Map()) sont vrais - bien qu'ils semblent tous également vides!


Null vs Undefined

Il y a aussi une discussion concernant nullvs undefined- avons-nous vraiment besoin des deux pour exprimer la vacuité dans nos programmes? Personnellement, j'évite que les lettres u, n, d, e, f, i, n, e, d apparaissent dans mon code dans cet ordre. J'utilise toujours nullpour signifier la «vacuité». Encore une fois, cependant, nous devons tenir compte du sens inhérent de javascript de la manière nullet de la undefineddifférence:

  • Essayer d'accéder à une propriété inexistante donne undefined
  • L'omission d'un paramètre lors de l'appel d'une fonction entraîne la réception de ce paramètre undefined:

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

  • Les paramètres avec des valeurs par défaut reçoivent la valeur par défaut uniquement lorsqu'ils sont donnés undefined, pas null:

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


Vacuité non générique

Je pense que la vacuité ne doit jamais être traitée de manière générique. Au lieu de cela, nous devrions toujours avoir la rigueur pour obtenir plus d'informations sur nos données avant de déterminer si elles sont vides - je le fais principalement en vérifiant le type de données que je traite:

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

Notez que cette fonction ignore le polymorphisme - elle s'attend valueà être une instance directe de Cls, et non une instance d'une sous-classe de Cls. J'évite instanceofpour deux raisons principales:

  • ([] instanceof Object) === true ("Un tableau est un objet")
  • ('' instanceof String) === false ("Une chaîne n'est pas une chaîne")

Notez que cela Object.getPrototypeOfest utilisé pour éviter un cas comme let v = { constructor: String };La isTypefonction renvoie toujours correctement pour isType(v, String)(false), etisType(v, Object) (true).

Dans l'ensemble, je recommande d'utiliser cette isTypefonction avec ces conseils:

  • Réduisez la quantité de valeurs de traitement de code de type inconnu. Par exemple, pour let v = JSON.parse(someRawValue);, notre vvariable est maintenant de type inconnu. Le plus tôt possible, nous devons limiter nos possibilités. La meilleure façon de le faire peut être d'exiger un type particulier: par exemple if (!isType(v, Array)) throw new Error('Expected Array');- c'est un moyen très rapide et expressif de supprimer la nature générique de v, et de s'assurer que c'est toujours un Array. Parfois, cependant, nous devons permettre vd'être de plusieurs types. Dans ces cas, nous devons créer des blocs de code qui vne sont plus génériques, le plus tôt possible:

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');
}

  • Utilisez toujours des "listes blanches" pour la validation. Si vous voulez qu'une valeur soit, par exemple, une chaîne, un nombre ou un tableau, vérifiez ces 3 possibilités "blanches" et lancez une erreur si aucun des 3 n'est satisfait. Nous devrions être en mesure de voir que la vérification des possibilités "noires" n'est pas très utile: disons que nous écrivons if (v === null) throw new Error('Null value rejected');- c'est très bien pour s'assurer que les nullvaleurs ne passent pas, mais si une valeur le fait , nous savons encore à peine quoi que ce soit à ce sujet. Une valeur vqui passe ce null-check est encore TRÈS générique - c'est tout saufnull ! Les listes noires dissipent à peine le caractère générique.
  • À moins qu'une valeur ne soit null, ne considérez jamais «une valeur vide de sens». Considérez plutôt "un X qui est vide". Essentiellement, n'envisagez jamais de faire quelque chose comme if (isEmpty(val)) { /* ... */ }- peu importe comment cette isEmptyfonction est implémentée (je ne veux pas savoir ...), ce n'est pas significatif! Et c'est bien trop générique! La vacuité ne doit être calculée qu'en connaissant valle type de. Les contrôles de vacuité devraient ressembler à ceci:

    • "Une chaîne, sans caractères": if (isType(val, String) && val.length === 0) ...
    • "Un objet, avec 0 accessoires": if (isType(val, Object) && Object.entries(val).length === 0) ...
    • "Un nombre égal ou inférieur à zéro": if (isType(val, Number) && val <= 0) ...
    • "An Array, with no items": if (isType(val, Array) && val.length === 0) ...

    • La seule exception est quand nullest utilisé pour signifier certaines fonctionnalités. Dans ce cas, il est significatif de dire: "Une valeur vide":if (val === null) ...

Gershom
la source
Je peux voir que vous y avez réfléchi:>
Rui Marques
3

Essayez avec une logique différente . Vous pouvez utiliser le code ci-dessous pour vérifier les quatre (4) conditions de validation comme non nul, non vide, non indéfini et non nul uniquement utiliser ce code (! (! (Variable))) en javascript et 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);
    }
}
Ravikant
la source
3

Jetez un œil au nouveau ECMAScript Découvrez opérateur de coalescence Nullish

Vous pouvez considérer cette fonctionnalité - l' ??opérateur - comme un moyen de «retomber» à une valeur par défaut lorsque vous traitez avecnull ou undefined.

let x = foo ?? bar();

Encore une fois, le code ci-dessus est équivalent au suivant.

let x = (foo !== null && foo !== undefined) ? foo : bar();
Daniel Eduardo Delgado Diaz
la source
2
function isEmpty(val){
    return !val;
}

mais cette solution est sur-conçue, si vous ne souhaitez pas modifier la fonction plus tard pour les besoins du modèle commercial, il est plus propre de l'utiliser directement dans le code:

if(!val)...
Luca C.
la source
2
var myNewValue = myObject && myObject.child && myObject.child.myValue;

Cela ne générera jamais d'erreur. Si myObject , child ou myValue est null, myNewValue sera null. Aucune erreur ne sera levée

Keith Blanchard
la source
2

Pour tous ceux qui viennent ici pour avoir une question similaire, ce qui suit fonctionne très bien et je l'ai dans ma bibliothèque les dernières années:

(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));
centurien
la source
2

Si vous voulez éviter de devenir vrai si la valeur est l'une des suivantes, selon la réponse de jAndy :

  • nul
  • indéfini
  • NaN
  • chaîne vide ("")
  • 0
  • faux

Une solution possible qui pourrait éviter d'obtenir des valeurs véridiques est la suivante:

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;
    }
}

Il serait utilisé comme suit:

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!
}

En plus de ces scénarios, vous pouvez vouloir retourner false si l' objet ou le tableau est vide:

Vous vous y prendriez de cette façon:

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;
    }
}

Si vous souhaitez vérifier toutes les chaînes d'espaces (""), vous pouvez procéder comme suit:

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

Remarque: hasOwnPropertyrenvoie true pour les chaînes vides, 0, false, NaN, null et undefined, si la variable a été déclarée comme l'une d'entre elles, donc ce n'est peut-être pas la meilleure à utiliser. La fonction peut être modifiée pour l'utiliser pour montrer qu'elle a été déclarée, mais n'est pas utilisable.

yaharga
la source
2

Code sur 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]';

Les tests du pauvre 😁

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);
};

Résultats de test:

EMPTY (10 tests)
NOT EMPTY (16 tests)
SHOULD BE EMPTY (2 tests)
  Assertion failed: 0: [object Object]
  Assertion failed: 1: [object Map]
Pascal Polleunus
la source
grande fonction, toutes les autres réponses ici avaient plusieurs problèmes que le vôtre semble résoudre, je souhaite juste l'avoir trouvé avant d'avoir écrit le mien: p pensais que vous aimeriez jeter un oeil à mon travail stackoverflow.com/ questions / 5515310 /… nos deux fonctions semblent avoir exactement la même sortie mais j'ai réduit un peu le code. Veuillez me faire savoir si j'ai raté quelque chose.
Sean Bannister
👍 Avez-vous essayé mes "tests du pauvre"? Je pense que j'ai fini par ajouter plus de tests dans la fonction pour des cas spéciaux comme Map, WeakMap et peut-être aussi Date, RegExp. Êtes-vous sûr de votre value.constructor === Object? Vérifiez ça .
Pascal Polleunus
Oui, j'ai fait vos tests, merci pour ceux-ci, nos deux fonctions retournent les mêmes résultats avec nos deux tests. Je me demande si je manque quelque chose en dehors de ces cas de test. Je crois que value.constructor === Objectça va, en javascript, les instructions IF OR ont un ordre d'exécution, de sorte que l'instruction OR ne s'exécutera que si la précédente n'a pas retourné TRUE et que nous avons déjà vérifié Null. En fait, le seul but de cette dernière instruction OR est de détecter {}et de s'assurer qu'elle ne renvoie pas VRAI pour les choses qu'elle ne devrait pas.
Sean Bannister
1

Ceci vérifiera si la variable d'imbrication indéterminée n'est pas définie

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")) {

Ce qui précède vérifie si la fonction de traduction de Google TranslateElement existe. Cela équivaut à:

if (!(typeof google === "undefined" 
 || typeof google.translate === "undefined" 
 || typeof google.translate.TranslateElement === "undefined")) {
rickdog
la source
1

L'opérateur de chaînage facultatif permet de simplifier l'accès aux valeurs via des objets connectés lorsqu'il est possible qu'une référence ou une fonction soit indéfinie ou nulle.

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

L'opérateur coalescent nul peut être utilisé après un chaînage optionnel afin de construire une valeur par défaut quand aucune n'a été trouvée:

let customer = {
  name: "Carl",
  details: { age: 82 }
};
const customerCity = customer?.city ?? "Unknown city";
console.log(customerCity); // Unknown city
Sunny Sultan
la source
1
function notEmpty(value){
  return (typeof value !== 'undefined' && value.trim().length);
}

il vérifiera également les espaces blancs ('') ainsi que les éléments suivants:

  • null, non défini, NaN, vide, chaîne (""), 0, faux
Hassan Ali Shahzad
la source
0

Je pense qu'en utilisant le? l'opérateur est légèrement plus propre.

var ? function_if_exists() : function_if_doesnt_exist();
Pedro Pereira
la source