JavaScript isset () эквивалент


553

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

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

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


1
Я написал функцию, которая будет проверять наличие свойства объектов независимо от глубины запроса: stackoverflow.com/a/12681101/1268003 Используя мой код в сочетании с некоторыми знаниями, которыми @CMS поделился в этой теме, вы можете легко написать глобальную функция, которая работает очень похоже на PHP: s isset.
Мартин Андерссон

3
Если вы используете Underscore.js, попробуйте_.isUndefined(arr.foo)
Виталий Федоренко

Дополнительное сцепление - это, вероятно, то, что большинство людей будет искать stackoverflow.com/a/60845999/2100372
zoran404

Ответы:


938

Я обычно использую 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Оператор проверит все свойства досягаемых в цепи прототипов, например:

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
Почему использовать, typeofа не if( obj.foo !== undefined )?
Мэтт Болл

7
Ах. Однажды я напишу кусок действительно кросс-браузерного Javascript. До тех пор ...
Мэтт Болл

37
проблема в том, что вы получаете ошибку при попытке проверить более глубокие свойства, например: obj.thisdoesntexist.foo! == undefined. В PHP вы можете использовать isset или пустой и безопасно на любой глубине.
Энрике

6
IE8 не имеет hasOwnPropery
max4ever

12
Точно, PHP позволяет isset($abc->def->ghi->jkl)без вызова исключения и остановки скрипта, в отличие от typeofоператора JavaScript . Вы должны использовать что-то вроде try{ abc.def.ghi.jkl; isset=true } catch(e){ isset=false }
Стивен Прибилинский

43

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

ESNext (Этап 4 декабря 2019 г.)

Два новых синтаксиса позволяют нам значительно упростить использование 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()который работает, но я лично избегаю

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

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

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


25

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

    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


6
Это вызовет исключение при вызове isset(abc.def.ghi)в случае, если значение abc.defне определено. Однако, объединяя это решение с тем, которое принимает имя переменной в виде строки, оно будет идентично версии PHP.
Стивен Прибилинский


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

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

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

5

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

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

4

Это довольно пуленепробиваемое решение для тестирования, если переменная существует:

var setOrNot = typeof variable !== typeof undefined ? true : false;

К сожалению, вы не можете просто заключить его в функцию.

Вы можете подумать о том, чтобы сделать что-то вроде этого:

function isset(variable) {
    return typeof variable !== typeof undefined ? true : false;
}

Однако это приведет к ошибке ссылки, если переменная variableне была определена, потому что вы не можете передать несуществующую переменную в функцию:

Uncaught ReferenceError: foo не определен

С другой стороны, это позволяет вам проверить, не определены ли параметры функции:

var a = '5';

var test = function(x, y) {
    console.log(isset(x));
    console.log(isset(y));
};

test(a);

// OUTPUT :
// ------------
// TRUE
// FALSE

Даже если никакое значение для yне передается функции test, наша issetфункция прекрасно работает в этом контексте, потому что yв функции она известна testкак undefinedзначение.


Незначительная гнида: `? true: false` излишне. Результат !==уже логический.
ToolmakerSteve

4
(typeof SOMETHING) !== 'undefined'

Это слишком долго писать, когда используется. Но мы не можем упаковать typeofключевое слово в функцию, потому что перед вызовом функции возникнет ошибка, например:

function isdef($var) {
    return (typeof $var) !== 'undefined';
}

isdef(SOMETHING); ///// thrown error: SOMETHING is not defined

Вот я и нашел способ:

function isdef($type) {
    return $type !== 'undefined';
}

isdef(typeof SOMETHING);

Он может работать как с отдельными переменными (переменные, которые вообще не существуют), так и со свойствами объекта (несуществующие свойства). И всего на 7 символов больше, чем в PHP isset.


Это работает для меня, использовал его, чтобы проверить, существует ли определенный ответ JSON.
Юлий

3

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

function isset(object){
    return (typeof object !=='undefined');
}

5
Вызов isset(var)с varнеустановленным:ReferenceError: var is not defined
Gui Imamura

3
function isset(variable) {
    try {
        return typeof eval(variable) !== 'undefined';
    } catch (err) {
        return false;
    }
}

4
добавить описание тоже.
Шри Кришна

Как уже упоминалось в нескольких предыдущих ответах, это вызовет ReferenceError, если вызывается с переменной, которая никогда не была объявлена. Например isset(someVar), где someVarникогда не было объявлено. Однако, учитывая то, что вы делаете eval, вы, вероятно, намереваетесь передать строку . Показать использование. Ваше предполагаемое использование isset('someVar')? Если это так, то это похоже на предыдущий ответ - что нового в вашем ответе?
ToolmakerSteve

3
window.isset = function(v_var) {
    if(typeof(v_var) == 'number'){ if(isNaN(v_var)){ return false; }}
    if(typeof(v_var) == 'undefined' || v_var === null){ return false;   } else { return true; }
};

плюс тесты:

https://gist.github.com/daylik/24acc318b6abdcdd63b46607513ae073


Как уже упоминалось в нескольких предыдущих ответах, это вызовет ReferenceError, если вызывается с переменной, которая никогда не была объявлена.
ToolmakerSteve

3

Чтобы проверить, существует ли HTML-блок или нет, я использую этот код:

if (typeof($('selector').html()) != 'undefined') {
    // $('selector') is existing
    // your code here
}

2

Укажите путь к объекту в виде строки, затем вы можете разбить эту строку на путь и разрешать hasOwnPropertyна каждом шаге, перезаписывая сам объект при каждой итерации.

Если вы программируете в среде ES6, взгляните на этот стековый поток Ques .

var a;

a = {
    b: {
        c: 'e'
    }
};

function isset (obj, path) {
    var stone;

    path = path || '';

    if (path.indexOf('[') !== -1) {
        throw new Error('Unsupported object path notation.');
    }

    
    path = path.split('.');
    
    do {
        if (obj === undefined) {
            return false;
        }

        stone = path.shift();
        
        if (!obj.hasOwnProperty(stone)) {
            return false;
        }
        
        obj = obj[stone];
        
    } while (path.length);

    return true;
}

console.log(
    isset(a, 'b') == true,
    isset(a, 'b.c') == true,
    isset(a, 'b.c.d') == false,
    isset(a, 'b.c.d.e') == false,
    isset(a, 'b.c.d.e.f') == false
);


2

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

    function _isset (variable) {
        if(typeof(variable) == "undefined" || variable == null)
            return false;
        else
            if(typeof(variable) == "object" && !variable.length) 
                return false;
            else
                return true;
    };

Как уже упоминалось в нескольких предыдущих ответах, это вызовет ReferenceError, если вызывается с переменной, которая никогда не была объявлена.
ToolmakerSteve

1

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

//Object on which we want to test
var foo = {
    bar: {
        bik: {
            baz: 'Hello world'
        }
    }
};


/*
USE: To get value from the object using it properties supplied (Deeper),
    if found it will return the property value if not found then will return false

You can use this function in two ways
WAY - 1:
Passing an object as parameter 1 and array of the properties as parameter 2
EG: getValueFromObject(foo, ['bar', 'bik', 'baz']);
WAY - 2: (This will work only if, your object available in window object)
Passing an STRING as parameter 1(Just similarly how we retrieve value form object using it's properties - difference is only the quote)
EG: getValueFromObject('foo.bar.bik.baz');
*/
function getValueFromObject(object, properties) {
    if(typeof(object) == 'string') {            //Here we extract our object and it's properties from the string
        properties = object.split('.');
        object = window[properties[0]];
        if(typeof(object) == 'undefined') {
            return false;
        }
        properties.shift();
    }
    var property = properties[0];
    properties.shift();
    if(object != null && typeof(object[property]) != 'undefined') {
        if(typeof(object[property]) == 'object') {
            if(properties.length != 0) {
                return getValueFromObject(object[property], properties);    //Recursive call to the function
            } else {
                return object[property];
            }
        } else {
            return object[property];
        }
    } else {
        return false;
    }
}
console.log(getValueFromObject('fooo.bar.bik.baz'));        //false
console.log(getValueFromObject('foo.bar.bik.baz'));         //Hello world
console.log(getValueFromObject('foo'));                     //false
console.log(getValueFromObject('foo.bar.bik'));             //returns an object { baz: 'Hello World' }
console.log(getValueFromObject(foo, ['bar', 'bik']));       //returns an object { baz: 'Hello World' }
console.log(getValueFromObject(foo, ['bar', 'bik', 'baz']));//Hello world

1

Если вы хотите проверить, существует ли элемент, просто используйте следующий код:

if (object) {
  //if isset, return true
} else {
  //else return false
}

Это образец:

function switchDiv() {
    if (document.querySelector("#divId")) {
        document.querySelector("#divId").remove();
    } else {
        var newDiv = document.createElement("div");
        newDiv.id = "divId";
        document.querySelector("body").appendChild(newDiv);
    }
}

document.querySelector("#btn").addEventListener("click", switchDiv);
#divId {
    background: red;
    height: 100px;
    width: 100px;
    position: relative;
    
}
<body>
  <button id="btn">Let's Diiiv!</button>
</body>



0

Руководство PHP говорит:

isset - определяет, установлена ​​ли переменная и не равна ли NULL

И интерфейс примерно так:

bool isset ( mixed $var [, mixed $... ] )

Параметр $var- это переменная для проверки. он может иметь любое количество параметров.

isset () возвращает, TRUEесли var существует и имеет значение, отличное от NULL.FALSEв противном случае.

Пример:

$foo = 'bar';
var_dump(isset($foo));        -> true

$baz = null;
var_dump(isset($baz));        -> false

var_dump(isset($undefined));  -> false

Учитывая это, по-видимому, невозможно написать точный эквивалент isset()функции php . Например, когда мы звоним так:

if (isset(some_var)) {

}

function issset() {
    // function definition
}

Javascript триггер Uncaught ReferenceError: some_var is not defined at (file_name):line_number. Важной и замечательной особенностью этого поведения является то, что при попытке передать несуществующие переменные нормальным функциям возникает ошибка.

Но в PHP на isset()самом деле не обычные функции, а языковые конструкции. Это означает, что они являются частью самого языка PHP, не воспроизводят по обычным правилам функций и, следовательно, могут избежать появления ошибки для несуществующих переменных. Это важно при попытке выяснить, существует ли переменная или нет. Но в javscript он в первую очередь вызывает ошибку, скажем, вызов функции с несуществующими переменными.

Я хочу сказать, что мы не можем написать это как эквивалентную функцию javscript, но мы можем сделать что-то вроде этого

if (typeof some_var !== 'undefined') {
   // your code here
}

Если вы хотите точно такой же эффект, PHP также проверьте varable не NULL

Например

$baz = null;
var_dump(isset($baz));        -> false

Итак, мы можем включить это в JavaScript, тогда это будет выглядеть так:

if (typeof some_var !== 'undefined' && some_var !== null) {
   // your code here
}

0

javascript isset

let test = {
  a: {
    b: [0, 1]
  }
};

console.log(test.isset('a.b'))   // true
console.log(test.isset('a.b.1')) // true
console.log(test.isset('a.b.5')) // false
console.log(test.isset('a.c'))   // false
console.log('abv'.isset('0'))    // true

0

Будьте осторожны в ES6 , все предыдущие решения не работают, если вы хотите проверить объявление переменной let и объявить ее, если это не так

пример

let myTest = 'text';

if(typeof myTest === "undefined") {
    var myTest = 'new text'; // can't be a let because let declare in a scope
}

вы увидите ошибку

Uncaught SyntaxError: Идентификатор 'myTest' уже объявлен

Решением было изменить его на переменную

var myTest = 'text'; // I replace let by a var

if(typeof myTest === "undefined") {
    var myTest = 'new text';
}

другое решение, если вы можете изменить let на var, вам нужно удалить ваш var

let myTest = 'text';

if(typeof myTest === "undefined") {
    myTest = 'new text'; // I remove the var declaration
}

-1
    isset('user.permissions.saveProject', args);

    function isset(string, context) {
        try {
            var arr = string.split('.');
            var checkObj = context || window;

            for (var i in arr) {
                if (checkObj[arr[i]] === undefined) return false;
                checkObj = checkObj[arr[i]];
            }

            return true;
        } catch (e) {
            return false;
        }
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.