JavaScript isset () эквивалент - PullRequest
510 голосов
/ 17 февраля 2010

В PHP вы можете сделать if(isset($array['foo'])) { ... }.В JavaScript вы часто используете if(array.foo) { ... }, чтобы сделать то же самое, но это не совсем то же самое утверждение.Условие также оценивается как ложное, если array.foo действительно существует, но имеет значение false или 0 (и, возможно, другие значения).

Что является идеальным эквивалентом PHP isset в JavaScript?

В более широком смысле было бы удобно общее полное руководство по обработке в JavaScript переменных, которые не существуют, переменных без значения и т. Д.

Ответы [ 19 ]

867 голосов
/ 17 февраля 2010

Я обычно использую оператор typeof:

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

Он вернет "undefined", либо если свойство не существует, либо его значение равно undefined.

(См. Также: Разница между undefined и не определена. )

Существуют и другие способы выяснить, существует ли свойство объекта, например, метод hasOwnProperty:

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

И оператор in:

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

Разница между двумя последними в том, что метод hasOwnProperty проверит, существует ли свойство физически на объекте (свойство не наследуется).

Оператор in проверит все свойства, доступные в цепочке прототипов, например ::1010 *

var obj = { foo: 'bar'};

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

Как видите, hasOwnProperty возвращает false, а оператор in возвращает true при проверке метода toString, этот метод определен в цепочке прототипов, поскольку obj наследует форму Object.prototype.

23 голосов
/ 16 сентября 2017

Вековая ветка, но вот новый способ запустить эквивалент isset().

Ответ

См. Объяснение ниже. Примечание. Я использую синтаксис StandardJS

Пример использования

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

Функция ответа

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

Объяснение

PHP

Обратите внимание, что в PHP вы можете ссылаться на любую переменную на любой глубине - даже пытаясь доступ к не массиву как к массиву вернет простое true или 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

В JavaScript у нас нет этой свободы, мы всегда получим ошибку, если сделаем то же самое, потому что JS немедленно пытается получить доступ к значению deeper прежде чем мы сможем обернуть его в нашей isset() функции, так что ...

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

Больше неудачных альтернатив:

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

И некоторые рабочие альтернативы, которые могут стать избыточными быстро:

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

Заключение

Все остальные ответы - хотя большинство из них жизнеспособны ...

  1. Предположим, вы проверяете, не является ли переменная неопределенной, подходит для некоторых случаев использования, но все равно может выдать ошибку
  2. Предположим, вы пытаетесь получить доступ только к свойству верхнего уровня, что опять же штраф за некоторые варианты использования
  3. Заставить вас использовать менее чем идеальный подход относительно PHP isset()
    например isset(some, 'nested.deeper.value')
  4. Используйте eval(), который работает, но я лично избегаю

Мне кажется, я многое об этом рассказал. В моем ответе есть несколько моментов, которые я не касайтесь, потому что они - хотя и актуальны - не являются частью вопрос. При необходимости я могу обновить свой ответ ссылками на некоторые из больше технических аспектов, основанных на спросе.

Я потратил много времени на это, так что, надеюсь, это поможет людям.

Спасибо за чтение!

23 голосов
/ 20 ноября 2012

Ссылка на ИСТОЧНИК

    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 в основном удален в пользу locutus Вот новая ссылка http://locutus.io/php/var/isset

17 голосов
/ 17 февраля 2010
if (!('foo' in obj)) {
  // not set.
}
8 голосов
/ 21 июня 2014

Это простое решение работает, но не для глубокой проверки объекта.

function isset(str) {
    return window[str] !== undefined;
}
8 голосов
/ 21 августа 2013
//
//  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;

 } 
//
//
5 голосов
/ 19 февраля 2016

Если вы используете underscorejs Я всегда использую

if (!_.isUndefined(data) && !_.isNull(data)) {
     //your stuff
}
5 голосов
/ 07 августа 2015

Я всегда использую эту универсальную функцию для предотвращения ошибок примитивных переменных, а также массивов и объектов.

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
4 голосов
/ 18 мая 2015

Это решение сработало для меня.

function isset(object){
    return (typeof object !=='undefined');
}
4 голосов
/ 08 марта 2016
function isset(variable) {
    try {
        return typeof eval(variable) !== 'undefined';
    } catch (err) {
        return false;
    }
}
...