JavaScript еквівалентний () еквівалент


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: sset.
Мартін Андерссон

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 ви можете використовувати набір або порожній і безпечно на будь-якій глибині.
Енріке

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()що працює, але я особисто уникаю

Я думаю, що я багато цього висвітлював. У своїй відповіді я зазначаю деякі моменти, яких я не зачіпаю, тому що вони - хоча є актуальними - не є частиною питання. Якщо потрібно, я можу оновити свою відповідь посиланнями на деякі більш технічні аспекти, що базуються на попиті.

Я витратив waaay багато часу на це так сподіваюсь це допомагає людям.

Дякую за прочитане!


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


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
також додайте опис.
Shree Krishna

Як згадувалося в декількох попередніх відповідях, це призведе до створення 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, подивіться на це питання про stackoverflow .

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

Для мене це була справді проблема, коли я отримував доступ до більш глибокої властивості об'єкта, тому я створив функцію, яка повертає значення властивості, якщо існує в іншому випадку, вона поверне помилкову. Ви можете використовувати його, щоб заощадити свій час,

//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 також перевіряйте, чи не змінюється це NULL

Наприклад

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

Отже, ми можемо включити це в javascript, тоді це виглядає приблизно так:

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

0

jaset 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';
}

інше рішення, якщо ви можете змінити дозвіл на 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.