Question JavaScript isset () équivalent


En PHP, vous pouvez faire if(isset($array['foo'])) { ... }. En JavaScript, vous utilisez souvent if(array.foo) { ... } faire la même chose, mais ce n'est pas exactement la même déclaration. La condition sera également évaluée à false si array.foo existe mais est false ou 0 (et probablement d'autres valeurs aussi).

Quel est l'équivalent parfait de PHP isset en JavaScript?

Dans un sens plus large, un guide général et complet sur la gestion par JavaScript des variables qui n'existent pas, des variables sans valeur, etc. serait pratique.


446
2018-02-17 14:54


origine


Réponses:


J'utilise généralement le typeof opérateur:

if (typeof obj.foo !== 'undefined') {
  // your code here
}

Il reviendra "undefined" soit si la propriété n'existe pas ou sa valeur est undefined.

(Voir également: Différence entre undefined et n'étant pas défini.)

Il existe d'autres façons de déterminer si une propriété existe sur un objet, comme la hasOwnProperty méthode:

if (obj.hasOwnProperty('foo')) {
  // your code here
}

Et le in opérateur:

if ('foo' in obj) {
  // your code here
}

La différence entre les deux derniers est que le hasOwnProperty méthode va vérifier si la propriété existe physiquement sur l'objet (la propriété n'est pas héritée).

le in l'opérateur vérifiera toutes les propriétés accessibles dans la chaîne prototype, par exemple:

var obj = { foo: 'bar'};

obj.hasOwnProperty('foo'); // true
obj.hasOwnProperty('toString'); // false
'toString' in obj; // true

Comme vous pouvez le voir, hasOwnProperty résultats false et le in l'opérateur retourne true lors de la vérification de toString méthode, cette méthode est définie dans la chaîne du prototype, car obj hérite de la forme Object.prototype.


762
2018-02-17 14:57



Référence à SOURCE

function isset ()
{
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: FremyCompany
    // +   improved by: Onno Marsman
    // +   improved by: Rafał Kukawski
    // *     example 1: isset( undefined, true);
    // *     returns 1: false
    // *     example 2: isset( 'Kevin van Zonneveld' );
    // *     returns 2: true

  var a = arguments,
    l = a.length,
    i = 0,
    undef;

  if (l === 0)
  {
    throw new Error('Empty isset');
  }

  while (i !== l)
  {
    if (a[i] === undef || a[i] === null)
    {
      return false;
    }
    i++;
  }
  return true;
}

21
2017-11-20 01:48



if (!('foo' in obj)) {
  // not set.
}

16
2018-02-17 14:59



Age vieux thread, mais voici une nouvelle façon d'exécuter un équivalent isset().

Répondre

Voir ci-dessous pour l'explication. Remarque: j'utilise la syntaxe StandardJS

Exemple d'utilisation

// IMPORTANT pass a function to our isset() that returns the value we're
// trying to test(ES6 arrow function)
isset(() => some) // false

// Defining objects
let some = { nested: { value: 'hello' } }

// More tests that never throw an error
isset(() => some) // true
isset(() => some.nested) // true
isset(() => some.nested.value) // true
isset(() => some.nested.deeper.value) // false

// Less compact but still viable except when trying to use `this` context
isset(function () { return some.nested.deeper.value }) // false

Fonction de réponse

/**
 * Checks to see if a value is set.
 *
 * @param {Function} accessor Function that returns our value
 */
function isset (accessor) {
  try {
    // Note we're seeing if the returned value of our function is not
    // undefined
    return typeof accessor() !== 'undefined'
  } catch (e) {
    // And we're able to catch the Error it would normally throw for
    // referencing a property of undefined
    return false
  }
}

Explication

PHP

Notez qu'en PHP vous pouvez référencer n'importe quelle variable à n'importe quelle profondeur - même en essayant de accéder à un non-tableau comme un tableau retournera un simple true ou false:

// Referencing an undeclared variable
isset($some); // false

$some = 'hello';

// Declared but has no depth(not an array)
isset($some); // true
isset($some['nested']); // false

$some = ['nested' => 'hello'];

// Declared as an array but not with the depth we're testing for
isset($some['nested']); // true
isset($some['nested']['deeper']); // false

JS

En JavaScript, nous n'avons pas cette liberté, nous aurons toujours une erreur si nous le faisons la même chose parce que JS tente immédiatement d'accéder à la valeur de deeper  avant que nous puissions l'envelopper dans notre isset() Fonctionne donc ...

// Common pitfall answer(ES6 arrow function)
const isset = (ref) => typeof ref !== 'undefined'

// Same as above
function isset (ref) { return typeof ref !== 'undefined' }

// Referencing an undeclared variable will throw an error, so no luck here
isset(some) // Error: some is not defined

// Defining a simple object with no properties - so we aren't defining
// the property `nested`
let some = {}

// Simple checking if we have a declared variable
isset(some) // true

// Now trying to see if we have a top level property, still valid
isset(some.nested) // false

// But here is where things fall apart: trying to access a deep property
// of a complex object; it will throw an error
isset(some.nested.deeper) // Error: Cannot read property 'deeper' of undefined
//         ^^^^^^ undefined

Plus d'alternatives défaillantes:

// Any way we attempt to access the `deeper` property of `nested` will
// throw an error
some.nested.deeper.hasOwnProperty('value') // Error
//   ^^^^^^ undefined

Object.hasOwnProperty('value', some.nested.deeper) // Error
//                                  ^^^^^^ undefined

// Same goes for typeof
typeof some.nested.deeper !== 'undefined' // Error
//          ^^^^^^ undefined

Et des alternatives de travail qui peuvent rapidement devenir redondantes:

// Wrap everything in try...catch
try { isset(some.nested.deeper) } catch (e) {}
try { typeof some.nested.deeper !== 'undefined' } catch (e) {}

// Or by chaining all of the isset which can get long
isset(some) && isset(some.nested) && isset(some.nested.deeper) // false
//                        ^^^^^^ returns false so the next isset() is never run

Conclusion

Toutes les autres réponses - bien que la plupart soient viables ...

  1. Supposons que vous vérifiez seulement si la variable n'est pas indéfinie   est correct pour certains cas d'utilisation, mais peut toujours lancer une erreur
  2. Supposons que vous essayez seulement d'accéder à une propriété de premier niveau, ce qui est encore   bien pour certains cas d'utilisation
  3. Vous obliger à utiliser une approche moins qu'idéale par rapport à celle de PHP isset()
      par exemple. isset(some, 'nested.deeper.value')
  4. Utilisation eval() qui fonctionne mais j'évite personnellement

Je pense que j'en ai couvert beaucoup. Il y a quelques points que je fais dans ma réponse que je ne touchent pas car ils - bien que pertinents - ne font pas partie de la question. Au besoin, cependant, je peux mettre à jour ma réponse avec des liens vers certains des aspects plus techniques basés sur la demande.

J'ai passé beaucoup de temps là-dessus, alors j'espère que cela aidera les gens.

Merci pour la lecture!


7
2017-09-16 18:08



//
//  tring to reference non-existing variable throws ReferenceError 
//  before test function is even executed
//
//  example, if you do:
//    
//     if ( isset( someVar ) ) 
//        doStuff( someVar );
//   
//  you get a ReferenceError ( if there is no someVar... ) 
//  and isset fn doesn't get executed.
//
//  if you pass variable name as string, ex. isset( 'novar' );, 
//  this might work:
//
function isset ( strVariableName ) { 

    try { 
        eval( strVariableName );
    } catch( err ) { 
        if ( err instanceof ReferenceError ) 
           return false;
    }

    return true;

 } 
//
//

6
2017-08-21 13:23



Cette solution simple fonctionne, mais pas pour la vérification d'objets en profondeur.

function isset(str) {
    return window[str] !== undefined;
}

6
2018-06-21 16:33



J'utilise toujours cette fonction générique pour éviter les erreurs sur les variables primitives ainsi que sur les tableaux et les objets.

isset = function(obj) {
  var i, max_i;
  if(obj === undefined) return false;
  for (i = 1, max_i = arguments.length; i < max_i; i++) {
    if (obj[arguments[i]] === undefined) {
        return false;
    }
    obj = obj[arguments[i]];
  }
  return true;
};

console.log(isset(obj));                   // returns false
var obj = 'huhu';
console.log(isset(obj));                   // returns true
obj = {hallo:{hoi:'hoi'}};
console.log(isset(obj, 'niet'));           // returns false
console.log(isset(obj, 'hallo'));          // returns true
console.log(isset(obj, 'hallo', 'hallo')); // returns false
console.log(isset(obj, 'hallo', 'hoi'));   // returns true

3
2017-08-07 14:04



Si vous utilisez raccourcis J'utilise toujours

if (!_.isUndefined(data) && !_.isNull(data)) {
     //your stuff
}

3
2018-02-19 11:23