Equivalente a isset() de JavaScript

Resuelto Bart van Heukelom asked hace 14 años • 28 respuestas

En PHP puedes hacerlo if(isset($array['foo'])) { ... }. En JavaScript sueles if(array.foo) { ... }hacer lo mismo, pero esta no es exactamente la misma declaración. La condición también se evaluará como falsa si array.fooexiste pero es falseo 0(y probablemente también otros valores).

¿ Cuál es el equivalente perfecto de PHP isseten JavaScript?

En un sentido más amplio, sería conveniente una guía general y completa sobre el manejo de JavaScript de variables que no existen, variables sin valor, etc.


Actualización : hace 11 años y 11 meses publiqué esta pregunta y, vaya, todavía hay mucha actividad. Ahora, estoy bastante seguro de que cuando escribí esto, solo quería saber cómo verificar la presencia de una propiedad en una matriz asociativa (también conocida como diccionario) y, como tal, las respuestas correctas (para mí) involucran hasOwnPropertyal inoperador . No estaba interesado en verificar variables locales o globales.

Pero aunque lo recuerdo bien, esa intención no está del todo clara en la pregunta tal como está escrita, ¡o incluso la contradice directamente! Nunca mencioné la matriz asociativa, y PHP issettambién hace esas otras cosas. Que esto sea una lección para todos nosotros sobre lo importante que es expresar adecuadamente sus requisitos en una pregunta, y también cómo las variables globales, las variables locales, las propiedades de los objetos, las claves del diccionario y lo que sea no son Huey, Dewey, y Louie.

Mientras tanto (je), muchas personas también han proporcionado respuestas en ese sentido, así que para aquellos de ustedes que encontraron esta pregunta a través de Google, bueno, me alegro de que mi vaguedad haya ayudado de alguna manera, supongo. De todos modos, sólo quería aclarar eso.

Bart van Heukelom avatar Feb 17 '10 21:02 Bart van Heukelom
Aceptado

Generalmente uso el typeofoperador:

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

Retornará "undefined"si la propiedad no existe o si su valor es undefined.

(Ver también: Diferencia entre undefinedy no estar definido ) .

Hay otras formas de averiguar si existe una propiedad en un objeto, como el hasOwnPropertymétodo:

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

Y el inoperador:

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

La diferencia entre los dos últimos es que el hasOwnPropertymétodo comprobará si la propiedad existe físicamente en el objeto (la propiedad no se hereda).

El inoperador verificará todas las propiedades alcanzables en la cadena del prototipo, por ejemplo:

var obj = { foo: 'bar'};

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

Como puede ver, hasOwnPropertyregresa falsey el inoperador regresa trueal verificar el toStringmétodo, este método está definido en la cadena del prototipo, porque objhereda la forma Object.prototype.

Christian C. Salvadó avatar Feb 17 '2010 14:02 Christian C. Salvadó

Hilo antiguo, pero hay nuevas formas de ejecutar un equivalente isset().

ESNext (Etapa 4 de diciembre de 2019)

Dos nuevas sintaxis nos permiten simplificar enormemente el uso de isset()la funcionalidad:

  • Encadenamiento opcional( ?.)
  • Operador coalescente nulo( ??)

Lea los documentos y tenga en cuenta la compatibilidad del navegador.

Respuesta

Consulte a continuación para obtener una explicación. Tenga en cuenta que uso la sintaxis StandardJS

Uso de ejemplo

// 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

Función de respuesta

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

Paquete MNP

Esta función de respuesta está disponible como isset-phppaquete en NPM. El paquete contiene algunas mejoras, como la verificación de tipos y la compatibilidad con múltiples argumentos.

npm install --save isset-php

La documentación completa está disponible en el README .

const isset = require('isset-php')
let val = ''

// This will evaluate to true so the text will be printed.
if (isset(() => val)) {
  console.log('This val is set so I will print.')
}

Explicación

PHP

Tenga en cuenta que en PHP puede hacer referencia a cualquier variable en cualquier profundidad; incluso intentar acceder a una matriz que no sea una matriz devolverá un simple trueo 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

javascript

En JavaScript, no tenemos esa libertad; Siempre obtendremos un error si hacemos lo mismo porque el motor intenta inmediatamente acceder al valor de deeperantes de que podamos incluirlo en nuestra isset()función, así que...

// 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

Más alternativas fallidas:

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

// Similar to the above but safe from objects overriding `hasOwnProperty`
Object.prototype.hasOwnProperty.call(some.nested.deeper, 'value') // Error
//                                        ^^^^^^ undefined

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

Y algunas alternativas de trabajo que pueden volverse redundantes rápidamente:

// Wrap everything in try...catch
try {
  if (isset(some.nested.deeper)) {
    // ...
  }
} catch (e) {}

try {
  if (some.nested.deeper !== undefined && some.nested.deeper !== null) {
    // ...
  }
} 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

Conclusión

Todas las demás respuestas, aunque la mayoría son viables...

  1. Suponga que solo está verificando si la variable no está definida, lo cual está bien para algunos casos de uso, pero aún puede generar un error.
  2. Suponga que solo está intentando acceder a una propiedad de nivel superior, lo que nuevamente está bien para algunos casos de uso.
  3. Obligarlo a utilizar un enfoque menos que ideal en relación con PHP, isset()
    por ejemploisset(some, 'nested.deeper.value')
  4. Use eval()el que funciona pero yo personalmente lo evito

Creo que cubrí mucho de eso. Hay algunos puntos que planteo en mi respuesta que no menciono porque, aunque son relevantes, no son parte de la pregunta (por ejemplo, cortocircuito ). Sin embargo, si es necesario, puedo actualizar mi respuesta con enlaces a algunos de los aspectos más técnicos según la demanda.

Pasé mucho tiempo en esto, así que espero que ayude a la gente.

¡Gracias por leer!

Enom avatar Sep 16 '2017 18:09 Enom

Referencia a la FUENTE

    module.exports = function isset () {
  //  discuss at: http://locutus.io/php/isset/
  // original by: Kevin van Zonneveld (http://kvz.io)
  // improved by: FremyCompany
  // improved by: Onno Marsman (https://twitter.com/onnomarsman)
  // improved by: Rafał Kukawski (http://blog.kukawski.pl)
  //   example 1: isset( undefined, true)
  //   returns 1: false
  //   example 2: isset( 'Kevin van Zonneveld' )
  //   returns 2: true

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

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

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

  return true
}

phpjs.org está mayoritariamente retirado a favor de locutus. Aquí está el nuevo enlace http://locutus.io/php/var/isset.

Ijas Ameenudeen avatar Nov 20 '2012 01:11 Ijas Ameenudeen