У javascript, як ми можемо визначити, чи є об'єкт хешем чи масивом?


77

Результатом мого виклику JSON може бути масив або хеш. Як розрізнити ці два?

Відповіді:


125

Сучасні браузери підтримують Array.isArray(obj)метод.

Документацію та поліфіл див. У MDN .

= оригінальна відповідь від 2008 =

Ви можете використовувати властивість constuctor вашого виводу:

if(output.constructor == Array){
}
else if(output.constructor == Object){
}

2
Це може призвести до конфліктів між різними сторінками, оскільки вони обидва мають різні екземпляри функцій Arrayі Objectконструктора, які не можуть порівнюватися як рівні. Я не зовсім впевнений, як навести приклад, який це демонструє, але я десь його читав.
ripper234

1
@ ripper234 Проблема проявиться у мульти windowсередовищі.
alex

3
+1 для вимірювання Array.isArray. Перевірте це посилання для підтримки боржників: kangax.github.io/compat-table/es5/#Array.isArray
SKuijers

1
Будь-хто, хто використовує underscore.js, може виявити корисним isArray та isObject .
акотіан

1
@akotian _.isObject повертає true для масиву та хешу, на жаль. Вам знадобиться додаткова умовна логіка, щоб виправити рішення з підкресленням.
Con Antonakos

31

Є об’єктом:

function isObject ( obj ) {
   return obj && (typeof obj  === "object");
}

Є масив:

function isArray ( obj ) { 
  return isObject(obj) && (obj instanceof Array);
}

Оскільки масиви - це об’єкти, які ви хочете перевірити, чи є змінна спочатку масивом, а потім, якщо це об’єкт:

if (isArray(myObject)) {
   // do stuff for arrays
}
else if (isObject(myObject)) {
   // do stuff for objects
}

1
Хороша відповідь. Ви можете додати, що кожен js-об'єкт можна розглядати як хеш.
Ронтолог

isObject (new Date ())) має значення true, але дата не є об’єктом / хешем у сенсі цього питання. Звичайно, ми просто застосовуємо його до JSON, але назва методу насправді бентежить.
schirrmacher

isObjectповертає істину як для об'єктів, так і для масивів, тому є надлишковим
hacklikecrack


5

Я створив функцію для визначення, чи це словник.

exports.is_dictionary = function (obj) {
    if(!obj) return false;
    if(Array.isArray(obj)) return false;
    if(obj.constructor != Object) return false;
    return true;
};

// return true
test.equal(nsa_utils.is_dictionary({}), true);
test.equal(nsa_utils.is_dictionary({abc:123, def:456}), true);

// returns false
test.equal(nsa_utils.is_dictionary([]), false);
test.equal(nsa_utils.is_dictionary([123, 456]), false);
test.equal(nsa_utils.is_dictionary(null), false);
test.equal(nsa_utils.is_dictionary(NaN), false);
test.equal(nsa_utils.is_dictionary('hello'), false);
test.equal(nsa_utils.is_dictionary(0), false);
test.equal(nsa_utils.is_dictionary(123), false);

Дякую за це. Це спрацювало для вищезазначених випадків. Мені ще доводиться стикатися з випадком, коли ваш метод не вдається.
Нав

1
if(Array.isArray(obj)) return false;<- Хіба це не зайве, враховуючи, що масив все одно не пройде наступну перевірку ( if(obj.constructor != Object))?

assert.equal(is_dictionary(new (class MyClass {})), true);не вдається - екземпляр MyClass, безумовно, є хешем / словником.
Анджелос Пікулас

Трохи вдосконалив:const assert = require('assert'); const is_dictionary = function (obj) { if(!obj) return false; if(Array.isArray(obj)) return false; if (({}).toString.apply(obj) !== '[object Object]') return false; return true; }; // returns true along your own with these values new (class MyClass {}) Object.create({}) Object.create(null) // returns false along with yours new String('foo') new Number(123) ()=> {} function() {} new Map
Анджелос Пікулас

1

Перевірте властивість "конструктор" на об'єкті. Це Array - це об’єкт масиву.

var a = {
 'b': {довжина: 0},
 'c': [1,2]
}

якщо (acconstructor == масив)
   для (var i = 0; i <aclength; i ++)
      попередження (ac [i]);
ще
   для (var s in ab);
      попередження (ab [s]);


0

Для розбору json може стати в нагоді :)

isArrayHashs = (attr) ->
  !!attr && attr.constructor == Array && isHash(attr[0])

isHash = (attr) ->
  !!attr && !$.isNumeric(attr) && attr.constructor == Object

attr [0] .constructor повинен бути:

  • Рядок
  • Числовий
  • Масив
  • Об'єкт
  • Не визначено

0

Більш практичний і точний термін, ніж об’єкт, хеш чи словник, може бути асоціативним масивом . Об'єкт може застосовуватися до багатьох небажаних випадків, наприклад typeof null === 'object'або [1,2,3] instanceof Object. Наступні дві функції працюють з ES3 і є природно ексклюзивними.

function is_array(z) {
    return Object.prototype.toString.call(z) === '[object Array]';
}

console.assert(true === is_array([]));
console.assert(true === is_array([1,2,3]));
console.assert(true === is_array(new Array));
console.assert(true === is_array(Array(1,2,3)));

console.assert(false === is_array({a:1, b:2}));
console.assert(false === is_array(42));
console.assert(false === is_array("etc"));
console.assert(false === is_array(null));
console.assert(false === is_array(undefined));
console.assert(false === is_array(true));
console.assert(false === is_array(function () {}));
function is_associative_array(z) {
    return Object.prototype.toString.call(z) === '[object Object]';
}

console.assert(true === is_associative_array({a:1, b:2}));
console.assert(true === is_associative_array(new function Legacy_Class(){}));
console.assert(true === is_associative_array(new class ES2015_Class{}));

console.assert(false === is_associative_array(window));
console.assert(false === is_associative_array(new Date()));
console.assert(false === is_associative_array([]));
console.assert(false === is_associative_array([1,2,3]));
console.assert(false === is_associative_array(Array(1,2,3)));
console.assert(false === is_associative_array(42));
console.assert(false === is_associative_array("etc"));
console.assert(false === is_associative_array(null));
console.assert(false === is_associative_array(undefined));
console.assert(false === is_associative_array(true));
console.assert(false === is_associative_array(function () {}));

Зверніть увагу, як це буде розглядати екземпляр класу як асоціативний масив. (Але не екземпляр вбудованого класу, такого як Date.)

Завдяки рішенню RobG у цьому напрямку для поліфіру Array.isArray (). Це торкається власного методу toString () класу Object, який стисло і ефективно повідомляє про тип.

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