Як перевірити, чи має об’єкт якісь властивості в JavaScript?


167

Якщо припустити, я заявляю

var ad = {}; 

Як я можу перевірити, чи буде цей об’єкт містити визначені користувачем властивості?

Відповіді:


86

Ви можете переключити властивості об'єкта наступним чином:

for(var prop in ad) {
    if (ad.hasOwnProperty(prop)) {
        // handle prop as required
    }
}

Важливо використовувати hasOwnProperty()метод, щоб визначити, чи має об'єкт вказану властивість як безпосередню властивість, а не успадковується від прототипу ланцюга об'єкта.

Редагувати

З коментарів: Ви можете поставити цей код у функцію та змусити його повернути помилковим, як тільки він досягне тієї частини, де є коментар

Тест на продуктивність

Test Of Object.Keys vs For..In При тестуванні будь-яких властивостей


2
Привіт, Даніеле, насправді я шукаю пристрій, щоб перевірити, чи об’єкт містить визначені користувачем властивості чи ні. Не перевіряти, чи існує певна властивість.
— Рікі

7
@ Ricky: Ви можете поставити цей код у функцію і змусити його повернути помилкове, як тільки він досягне тієї частини, де є коментар.
— Даніель Вассалло

8
Думаю, що використання цих днів Object.keysбуло б найпростішим: var a = [1,2,3];a.something=4;console.log(Object.keys(a))оскільки він вже є частиною ECMA 5, ви можете сміливо його прошивати: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
— HMR

2
Зауважте, що "в наші дні" за допомогою ES5 нативні об'єкти можуть мати безлічі власних властивостей, наприклад Object.defineProperty(obj, 'foo', {enumerable:false, value:'foo'}).
— RobG

2
Це рішення - це спосіб перевірити наявність ключів , але правдива, ефективна та найправильніша відповідь наведена нижче за допомогою Object.keys (x) .length. Вам не потрібно робити власну функцію, вона вже існує!
— 22

193

Ви можете використовувати вбудований Object.keysметод, щоб отримати список клавіш на об'єкті і протестувати його довжину.

var x = {};
// some code where value of x changes and than you want to check whether it is null or some object with values

if(Object.keys(x).length > 0){
 // Your code here if x has some properties  
}

14
Це тут правильна відповідь. Прийнята вище відповідь є обхідною проблемою і коштує дорожче, ніж просто перевірка кількості клавіш; це має більше сенсу .
— 22

6
Object.keys ("містінг"); також дає ключі, які, на мою думку, небажані. На мою думку ця відповідь неповна.
— Майк де Клерк

2
@MikedeKlerk, будь ласка, прочитайте його уважно, це не Object.keys ("mystring"); це Object.keys (objectVariableName), який поверне масив усіх ключів в об'єкті. наприклад: {'x': 'abc', 'y': 'def'} це буде ['x', 'y']
— Dhaval Chaudhary

3
@DhavalChaudhary Дякую за вашу відповідь на мій коментар. Коли я пробую цей код var str = "MyString"; Object.keys(str);, консоль видає 8 клавіш, від 0 до 7, для кожного символу. Або я досі не розумію відповіді.
— Майк де Клерк

6
@MikedeKlerk, але це єдине рішення для об'єктів, а не для рядків.
— Дхаваль Чадхарі

111

А як зробити просту функцію?

function isEmptyObject(obj) {
  for(var prop in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
      return false;
    }
  }
  return true;
}

isEmptyObject({}); // true
isEmptyObject({foo:'bar'});  // false

hasOwnPropertyМетод виклику безпосередньо на Object.prototypeтільки додати трохи більше безпеки , уявіть собі наступне , використовуючи звичайний obj.hasOwnProperty(...)виклик:

isEmptyObject({hasOwnProperty:'boom'});  // false

Примітка: (на майбутнє) Вищеописаний метод спирається на for...inтвердження, і це твердження ітералізує лише над перелічуваними властивостями, у найпоширенішому в даний час стандарті ECMAScript (3-е видання) програміст не має жодного способу створити незліченні властивості .

Однак це змінилося зараз із ECMAScript 5th Edition , і ми можемо створити властивості, що не перелічуються, не підлягають запису або не підлягають видаленню, тому вищевказаний метод може вийти з ладу , наприклад:

var obj = {};
Object.defineProperty(obj, 'test', { value: 'testVal', 
  enumerable: false,
  writable: true,
  configurable: true
});
isEmptyObject(obj); // true, wrong!!
obj.hasOwnProperty('test'); // true, the property exist!!

Рішенням цієї проблеми ECMAScript 5 буде:

function isEmptyObject(obj) {
  return Object.getOwnPropertyNames(obj).length === 0;
}

У Object.getOwnPropertyNamesметод повертає Arrayмістить імена всіх тих своїх якостей об'єкта, що перераховується чи ні , цей метод реалізується в даний час виробниками браузерів, це вже на Chrome 5 Beta і останній WebKit нічні збірки.

Object.defineProperty також доступний у цих браузерах та найновіших версіях Firefox 3.7 Alpha.


1
Яка перевага для Object.prototype.hasOwnProperty.call (obj, prop) над obj.hasOwnProperty (prop)?
— Кейсі Чу

3
@Casey, відредагований, якщо об’єкт перекриває hasOwnPropertyвластивість, функція може вийти з ладу ... Я знаю, я трохи параноїдальний ... але іноді ви не знаєте, в якому середовищі буде використовуватися ваш код, але ви знаєте, яким методом ви хочете скористатися ...
— CMS

2
+1 за відповідь на це питання ... та інші питання майбутнього! :)
— Даніель Вассалло

1
Зауважте, що в IE також є помилка, якщо якщо у вас є властивість з ім'ям, яке відповідає властивості Object.prototype, що не перелічується , воно не перераховується for...in. Так isEmptyObject({toString:1})не вдасться. Це одна із сумних причин ви не можете цілком використовувати Objectяк відображення загального призначення.
— bobince

1
@ MichaelMartin-Smucker - клавіші повертають лише безліч власних властивостей, тому тут не підходять.
— RobG

58

За допомогою jQuery ви можете використовувати:

$.isEmptyObject(obj); // Returns: Boolean

Станом на jQuery 1.4 цей метод перевіряє як властивості самого об’єкта, так і властивості, успадковані від прототипів (у тому, що він не використовує hasOwnProperty).

За допомогою ECMAScript 5-го видання в сучасних браузерах (IE9 +, FF4 +, Chrome5 +, Opera12 +, Safari5 +) ви можете використовувати вбудований метод Object.keys :

var obj = { blah: 1 };
var isEmpty = !Object.keys(obj).length;

Або звичайний старий JavaScript:

var isEmpty = function(obj) {
               for(var p in obj){
                  return false;
               }
               return true;
            };

33

Більшість останніх браузерів (і node.js) підтримують Object.keys (), який повертає масив з усіма ключами у вашому об'єктному літералі, щоб ви могли зробити наступне:

var ad = {}; 
Object.keys(ad).length;//this will be 0 in this case

Підтримка браузера: Firefox 4, Chrome 5, Internet Explorer 9, Opera 12, Safari 5

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys


13

Якщо ви використовуєте underscore.js, ви можете використовувати функцію _.isEmpty :

var obj = {};
var emptyObject = _.isEmpty(obj);

1
Просто для тих, хто проходить повз, це не метод, присвячений предметам. _.isEmpty([]) // true Обов'язково перевірте перший: stackoverflow.com/a/22482737/1922747
— Djv

11

Якщо ви готові використовувати лодаш , ви можете скористатися someметодом.

_.some(obj) // returns true or false

Дивіться цей невеликий приклад jsbin


var x = [1,2] // true
— djv

@damionjn Я додав ваш код у приклад. Я бачу вашу точку з тим, що масив повертає неправильну відповідь, але ОП спочатку оголосив змінну як об'єкт, тому я вважаю, що це добре, щоб вважати це. Вище є відповідь, в якій використовується метод підкреслення isEmpty (метод методу lodash). Ця відповідь має саме те саме питання. Якщо ви дасте isEmpty порожній масив, ви також отримаєте неправильний результат.
— sfs

Досить справедливо, але ми повинні надавати відповіді з усіма охопленими базами, щоб бути впевненими в передовій практиці. Ви маєте рацію, я пройшов правильну його відповідь без жодної критики. Просто для тих, хто проходить повз, це не метод, присвячений предметам. _.some([1, 2]) // true Обов'язково перевірте перший: stackoverflow.com/a/13356338/1922747
— Djv

5
for (var hasProperties in ad) break;
if (hasProperties)
    ... // ad has properties

Якщо вам потрібно бути безпечним і перевірити наявність прототипів Object (вони додаються певними бібліотеками, а за замовчуванням їх немає):

var hasProperties = false;
for (var x in ad) {
    if (ad.hasOwnProperty(x)) {
        hasProperties = true;
        break;
    }
}
if (hasProperties)
    ... // ad has properties

1
у вашому рішенні відсутня фільтрація небажаних властивостей прототипу, це означає, що це може бути недоброзичливо при використанні бібліотеки на зразок Prototype.js або недосвідчений користувач додав до об'єкта додаткові властивості прототипу. Ознайомтеся з рішенням Daniels на цій сторінці.
— Джоша

Вам не потрібно використовувати бібліотеку або бути недосвідченим для розширення прототипу об'єкта. Деякі досвідчені програмісти роблять це постійно.
— Альссенде

2
for(var memberName in ad)
{
  //Member Name: memberName
  //Member Value: ad[memberName]
}

Член означає власність члена, змінну члена, як би ви хочете назвати його> _>

Вищевказаний код поверне ВСЕ, включаючи toString ... Якщо ви хочете лише перевірити, чи поширювався прототип об'єкта:

var dummyObj = {};  
for(var memberName in ad)
{
  if(typeof(dummyObj[memberName]) == typeof(ad[memberName])) continue; //note A
  //Member Name: memberName
  //Member Value: ad[memberName]

}

Примітка A: Ми перевіряємо, чи має член об'єкта манекена той же тип, що і член нашого об'єкта тестування. Якщо це розширення, тип члена манекена повинен бути "невизначеним"


Привіт, чи можу я просто знати, чи об’єкт містить властивості чи ні? Спасибі
— Рікі

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

ознайомтеся з рішенням Daniels на цій сторінці - його менш схильним до помилок!
— Джоша

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

@ Ricky: Якщо ви хочете перевірити, чи містить об'єкт властивості, ви можете просто використати приклад у моїй відповіді: stackoverflow.com/questions/2673121/… . Якщо код дійде до коментаря, ваш об’єкт не матиме прямих властивостей. Якщо ні, то було б.
— Даніель Вассалло

2
var hasAnyProps = false; for (var key in obj) { hasAnyProps = true; break; }
// as of this line hasAnyProps will show Boolean whether or not any iterable props exist

Простий, працює у кожному браузері, і хоча технічно це цикл для всіх клавіш на об'єкті, він НЕ перетворює їх через усі ... або 0, і цикл не працює, або є якийсь, і він порушується після першого один (тому що ми все перевіряємо, чи є ЛЮБІ ... то чому продовжувати?)


1

Дуже пізня відповідь, але саме так ви могли б впоратися з прототипами.

Array.prototype.Any = function(func) {
    return this.some(func || function(x) { return x });
}

Object.prototype.IsAny = function() {
    return Object.keys(this).Any();
}

0

Якщо ви впевнені, що об'єкт визначений користувачем, найпростішим способом визначити, чи UDO порожній, буде такий код:

isEmpty=
/*b.b Troy III p.a.e*/
function(x,p){for(p in x)return!1;return!0};

Незважаючи на те, що цей метод (за своєю природою) дедуктивний, - це найшвидший і найшвидший.

a={};
isEmpty(a) >> true

a.b=1
isEmpty(a) >> false 

ps:! не використовуйте його на визначених браузером об'єктах.


... повернути 0; повернути 1}; було б те саме?
— commonpike

1
@pike ні, повертайся! 1; return! 0 - це те саме, що return false; return true
— Christophe

0

Пізня відповідь, але деякі рамки обробляють об'єкти як перелічені. Тому bob.js може це зробити так:

var objToTest = {};
var propertyCount = bob.collections.extend(objToTest).count();

0

Ви можете використовувати наступне:

Подвійний чубок !! пошук власності

var a = !![]; // true
var a = !!null; // false

hasOwnProperty Це я використовував:

var myObject = {
  name: 'John',
  address: null
};
if (myObject.hasOwnProperty('address')) { // true
  // do something if it exists.
}

Однак JavaScript вирішив не захищати ім'я методу, щоб його можна було підробити.

var myObject = {
  hasOwnProperty: 'I will populate it myself!'
};

підтримка в myObject

var myObject = {
  name: 'John',
  address: null,
  developer: false
};
'developer' in myObject; // true, remember it's looking for exists, not value.

тип

if (typeof myObject.name !== 'undefined') {
  // do something
}

Однак він не перевіряється на null.

Я думаю, що це найкращий спосіб.

в оператора

var myObject = {
  name: 'John',
  address: null
};

if('name' in myObject) {
  console.log("Name exists in myObject");
}else{
  console.log("Name does not exist in myObject");
}

результат:

Ім'я існує у myObject

Ось посилання, що детальніше описується на операторі in: Визначення, чи існує властивість об'єкта


0

Функція ES6

/**
 * Returns true if an object is empty.
 * @param  {*} obj the object to test
 * @return {boolean} returns true if object is empty, otherwise returns false
 */
const pureObjectIsEmpty = obj => obj && obj.constructor === Object && Object.keys(obj).length === 0

Приклади:


let obj = "this is an object with String constructor"
console.log(pureObjectIsEmpty(obj)) // empty? true

obj = {}
console.log(pureObjectIsEmpty(obj)) // empty? true

obj = []
console.log(pureObjectIsEmpty(obj)) // empty? true

obj = [{prop:"value"}]
console.log(pureObjectIsEmpty(obj)) // empty? true

obj = {prop:"value"}
console.log(pureObjectIsEmpty(obj)) // empty? false

-1

Як щодо цього?

var obj = {},
var isEmpty = !obj;
var hasContent = !!obj

Ця відповідь не відповідає на запитання. ОП запитує, чи містить об'єкт визначені користувачем властивості - ваша відповідь перевіряє, чи сам об'єкт перетворить у булеве помилкове значення.
— Jasmonate

... і я також пізніше зрозумів, що Джеймс вже включив цей варіант у свою відповідь. Вибачте, хлопці.
— Пітер Тот
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.