Як перевірити, чи має об’єкт якісь властивості в 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.