web-dev-qa-db-fra.com

Quelle est la raison d'utiliser null au lieu de non défini en JavaScript?

J'écris du JavaScript depuis assez longtemps maintenant, et je n'ai jamais eu de raison d'utiliser null. Il semble que undefined soit toujours préférable et sert le même objectif par programme. Quelles sont les raisons pratiques d'utiliser null au lieu de undefined?

91
Jimmy Cuadra

Null et undefined sont essentiellement deux valeurs différentes qui signifient la même chose. La seule différence réside dans les conventions de la façon dont vous les utilisez dans votre système. Comme certains l'ont mentionné, certaines personnes utilisent null pour signifier "aucun objet" où vous pouvez parfois obtenir un objet tandis qu'undefined signifie qu'aucun objet n'était attendu (ou qu'il y a eu une erreur). Mon problème avec cela est complètement arbitraire et totalement inutile.

Cela dit, il y a une différence majeure - les variables qui ne sont pas initialisées (y compris les paramètres de fonction où aucun argument n'a été passé, entre autres) sont toujours non défini.

C'est pourquoi dans mon code, je jamais utilise null sauf si quelque chose que je ne contrôle pas retourne null (correspondance regex par exemple). La beauté de cela est qu'elle simplifie beaucoup les choses. Je n'ai jamais à vérifier si x === indéfini || x === null. Et si vous avez l'habitude d'utiliser == ou simplement des trucs comme if (x) .... Arrête ça. !x sera évalué à true pour une chaîne vide, 0, null, NaN - c'est-à-dire des choses que vous ne voulez probablement pas. Si vous voulez écrire du javascript qui n'est pas terrible, utilisez toujours triple égal === et n'utilisez jamais null (utilisez plutôt undefined). Cela vous facilitera la vie.

40
B T

Je n'ai pas vraiment de réponse, mais selon Nicholas C. Zakas , page 30 de son livre " JavaScript professionnel pour les développeurs Web " :

Lors de la définition d'une variable destinée à contenir ultérieurement un objet, il est conseillé d'initialiser la variable sur null par opposition à toute autre chose. De cette façon, vous pouvez vérifier explicitement la valeur null pour déterminer si la variable a été remplie avec une référence d'objet ultérieurement

76
bbg

Vous pourriez adopter la convention suggérée ici, mais il n'y a vraiment aucune bonne raison de le faire. Il n'est pas utilisé de manière suffisamment cohérente pour être significatif.

Afin de rendre la convention utile, vous devez d'abord savoir que la fonction appelée suit la convention. Ensuite, vous devez tester explicitement la valeur retournée et décider quoi faire. Si vous obtenez non défini, vous pouvez supposer qu'une sorte d'erreur s'est produite que la fonction appelée connaissait. Mais si une erreur s'est produite et que la fonction en était informée, et qu'il est utile de l'envoyer dans un environnement plus large, pourquoi ne pas utiliser un objet d'erreur? c'est-à-dire jeter une erreur?

Donc, au bout du compte, la convention est pratiquement inutile dans autre chose que de très petits programmes dans des environnements simples.

10
RobG

indéfini est où aucune notion de la chose n'existe; il n'a pas de type, et il n'a jamais été référencé auparavant dans cette portée; null est l'endroit où la chose est connue pour exister, mais elle n'a aucune valeur.

10
Alex Shapovalov

Chacun a sa propre façon de coder et sa propre sémantique interne, mais au fil des ans, j'ai trouvé que c'était le conseil le plus intuitif que je donne aux personnes qui posent cette question: en cas de doute, faites ce que JavaScript fait =.

Disons que vous travaillez avec des propriétés d'objet comme des options pour un plugin jQuery ... demandez-vous quelle valeur JavaScript donne à une propriété qui n'a pas encore été définie - la réponse est undefined. Donc, dans ce contexte, j'initialiserais ce type de choses avec 'undefined' pour être cohérent avec JavaScript (pour les variables, vous pouvez faire var myVar; au lieu de var myVar = undefined;).

Supposons maintenant que vous effectuez une manipulation DOM ... quelle valeur JavaScript attribue-t-il aux éléments inexistants? La réponse est null. Il s'agit de la valeur que j'initialiserais si vous créez une variable d'espace réservé qui contiendra plus tard une référence à un élément, un fragment de document ou similaire qui se rapporte au DOM.

Si vous travaillez avec JSON, un cas spécial doit être fait: pour les valeurs de propriété non définies, vous devez soit les définir sur "" ou null car une valeur de undefined n'est pas considérée comme un format JSON approprié.

Cela dit, comme une affiche précédente l'a exprimé, si vous constatez que vous initialisez des choses avec null ou undefined plus d'une fois dans une lune bleue, alors peut-être devriez-vous reconsidérer comment vous allez sur le codage de votre application.

9
thdoan

À la fin de la journée, étant donné que null et undefined contraignent à la même valeur (Boolean(undefined) === false && Boolean(null) === false), vous pouvez techniquement utiliser l'une ou l'autre pour faire le travail. Cependant, il y a une bonne façon, l'OMI.

  1. Laissez l'utilisation de undefined au compilateur JavaScript.

    undefined est utilisé pour décrire les variables qui ne pointent pas vers une référence. C'est quelque chose que le compilateur JS prendra soin de vous. Au moment de la compilation, le moteur JS définira la valeur de toutes les variables hissées sur undefined. À mesure que le moteur parcourt le code et que les valeurs deviennent disponibles, le moteur attribue des valeurs respectives aux variables respectives. Pour les variables pour lesquelles il n'a pas trouvé de valeurs, les variables continueront de conserver une référence à la primitive undefined.

  2. N'utilisez null si vous souhaitez explicitement désigner la valeur d'une variable comme n'ayant "aucune valeur".

    Comme l'indique @ com2gz: null est utilisé pour définir quelque chose de vide par programme. undefined signifie que la référence n'existe pas. Une valeur null a une référence définie à "rien". Si vous appelez une propriété non existante d'un objet, vous obtiendrez undefined. Si je veux rendre cette propriété intentionnellement vide, elle doit être null pour que vous sachiez qu'elle est exprès.

TLDR; N'utilisez pas la primitive undefined. C'est une valeur que le compilateur JS définira automatiquement pour vous lorsque vous déclarez des variables sans affectation ou si vous essayez d'accéder aux propriétés des objets pour lesquels il n'y a pas de référence. D'un autre côté, utilisez null si et seulement si vous voulez intentionnellement qu'une variable n'ait "aucune valeur".

Je n'ai jamais défini explicitement quoi que ce soit sur undefined (et je ne l'ai pas rencontré dans les nombreuses bases de code avec lesquelles j'ai interagi). De plus, j'utilise rarement null. Les seules fois où j'utilise null, c'est quand je veux désigner la valeur d'un argument d'une fonction comme n'ayant aucune valeur, c'est-à-dire:

function printArguments(a,b) {
  console.log(a,b);
}

printArguments(null, " hello") // logs: null hello
6
Govind Rai

Une propriété utile dans null que non défini ne qualifie pas:

> null + 3
3
> undefined + 3
NaN

J'utilise null lorsque je veux "désactiver" une valeur numérique ou en initialiser une. Ma dernière utilisation a été la manipulation de la transformation css:

const transforms = { perspective : null, rotateX : null };
// if already set, increase, if not, set to x
runTimeFunction((x) => { trasforms.perspective += x; });
// still useful, as setting perspective to 0 is different than turning it off
runTimeFunction2((x) => { transforms.perspective = null; });

// toCss will check for 'null' values and not set then at all
runTimeFunction3(() => { el.style.transform = toCss(transforms); });

Je ne sais pas si je devrais utiliser cette propriété pensée ...

2
Faccion

Quelques-uns ont dit qu'il était correct d'initialiser des objets à null. Je voulais juste souligner que les valeurs par défaut des arguments de déstructuration ne fonctionnent pas avec null. Par exemple:

const test = ({ name } = {}) => {
  console.log(name)
}

test() // logs undefined
test(null) // throws error

Cela nécessite d'effectuer null vérifications avant pour appeler la fonction, ce qui peut se produire souvent.

2
Matt Way

Voici une raison: var undefined = 1 Est du javascript légal, mais var null = 1 Est une erreur de syntaxe. La différence est que null est un mot-clé de langue, tandis que undefined ne l'est pas, pour une raison quelconque.

Si votre code repose sur des comparaisons avec undefined comme si c'était un mot-clé (if (foo == undefined) - une erreur très simple à faire) qui ne fonctionne que parce que personne n'a défini une variable avec ce nom. Tout ce code est vulnérable à la définition accidentelle ou malveillante d'une variable globale portant ce nom. Bien sûr, nous savons tous que la définition accidentelle d'une variable globale est totalement impossible en javascript ...

2
Joel Mueller

Les nœuds et éléments DOM ne sont pas indéfinis, mais peuvent être nuls.

  • Le nextSibling du dernier enfant d'un élément est null.

  • Le previousSibling du premier enfant est nul.

  • Une référence document.getElementById est null si l'élément n'existe pas dans le document.

Mais dans aucun de ces cas, la valeur ndefined; il n'y a tout simplement pas de nœud là-bas.

2
kennebec

Je travaille sur cette question exacte en ce moment, et je regarde la philosophie suivante:

  1. Toute fonction destinée à renvoyer un résultat doit retourner null si elle ne parvient pas à trouver un résultat
  2. Toute fonction qui n'est PAS destinée à renvoyer un résultat renvoie implicitement undefined.

Pour moi, cette question est importante car quiconque appelle une fonction qui renvoie un résultat ne devrait pas se demander s'il faut tester non défini par rapport à null.

Cette réponse n'essaie pas d'aborder:

  1. Valeurs de propriété null vs undefined
  2. Les variables dans vos fonctions étant nulles ou non définies

À mon avis, les variables sont votre propre entreprise et ne font pas partie de votre API, et les propriétés de tout système OO sont définies et doivent donc être définies avec une valeur différente de ce qu'elles seraient si elles n'étaient pas définies) (null pour défini, indéfini est ce que vous obtenez lorsque vous accédez à quelque chose qui n'est pas dans votre objet).

1
Michael

Je veux juste ajouter qu'avec l'utilisation de certaines bibliothèques javascript, null et undefined peuvent avoir des conséquences inattendues.

Par exemple, la fonction get de lodash, qui accepte une valeur par défaut comme 3e argument:

const user = {
  address: {
    block: null,
    unit: undefined,
  }
}
console.log(_.get(user, 'address.block', 'Default Value')) // prints null
console.log(_.get(user, 'address.unit', 'Default Value')) // prints 'Default Value'
console.log(_.get(user, 'address.postalCode', 'Default Value')) // prints 'Default Value'

Un autre exemple: si vous utilisez defaultProps dans React, si une propriété est passée null, les accessoires par défaut ne sont pas utilisés car null est interprété comme une valeur définie. par exemple.

class MyComponent extends React.Component {
   static defaultProps = {
      callback: () => {console.log('COMPONENT MOUNTED')},
   }
   componentDidMount() {
      this.props.callback();
   }
}
//in some other component
<MyComponent />   // Console WILL print "COMPONENT MOUNTED"
<MyComponent callback={null}/>   // Console will NOT print "COMPONENT MOUNTED"
<MyComponent callback={undefined}/>   // Console WILL print "COMPONENT MOUNTED"
1
lilbitofchee

Je suis complètement en désaccord sur le fait que l'utilisation nulle ou non définie n'est pas nécessaire. undefined est une chose qui maintient en vie le processus de chaînage du prototype. Ainsi, le compilateur uniquement avec null ne peut pas vérifier si cette propriété est juste égale à null, ou si elle n'est pas définie dans le prototype de point de terminaison. Dans d'autres langages typés dynamiques (par exemple Python), il lève une exception si vous voulez accéder à une propriété non définie, mais pour les langages basés sur des prototypes, le compilateur doit également vérifier les prototypes parents et voici l'endroit où les besoins non définis ont le plus besoin.

Toute la signification de l'utilisation de null est simplement une variable ou une propriété de liaison avec un objet qui est singleton et a une signification de vide, et l'utilisation de null a également des objectifs de performance. Ce code 2 a un temps d'exécution différent.

var p1 = function(){this.value = 1};
var big_array = new Array(100000000).fill(1).map((x, index)=>{
    p = new p1();
    if(index > 50000000){
       p.x = "some_string";
    }

    return p;
});
big_array.reduce((sum, p)=> sum + p.value, 0)

var p2 = function(){this.value = 1, p.x = null};
var big_array = new Array(100000000).fill(1).map((x, index)=>{
    p = new p2();
    if(index > 50000000){
       p.x = "some_string";
    }

    return p; 
});
big_array.reduce((sum, p)=> sum + p.value, 0)
1
VahagnNikoghosian