объект имеет ключи, но оценивается как null

проблема в том, что нет «стандартной функции», которую вы могли бы написать, чтобы определить, «установлено ли что-то». например, если это действительно нулевой объект, вы не хотите с ним работать; но если у него есть ключи, то вы ДЕЙСТВИТЕЛЬНО хотите с ним работать - однако, если вы попытаетесь увидеть, есть ли у него ключи, когда их нет, даже если "typeof" возвращает "object", используя "Object.keys()" выдает ошибку, говоря, что это не объект. Итак, у нас, похоже, есть ловушка 22 (o_O) ... есть ли лучший способ увидеть, действительно ли объект является нулевым или у него есть ключи, не выдавая ошибку?

я использовал базовую функцию, чтобы увидеть, установлен ли объект даже до того, как посмотреть, имеет ли он действительное ЗНАЧЕНИЕ, но я сталкиваюсь со сценариями, в которых это не удается. в сценарии indexeddb и сценарии «this.items» оба оцениваются как «null», даже если их «тип» является «объектом», а их «объекты» ИМЕЮТ ключи; но если я оценю ключи, когда их нет, это вызовет еще одну ошибку, потому что объект ДЕЙСТВИТЕЛЬНО является нулевым в этот момент (без ключей/свойств). использование «объектных» функций, таких как «Object.keys» или «hasOwnProperty» и т. д., вызывает ошибку «это не объект».

по сути, то, что мне НУЖНО сделать, - это иметь возможность правильно определить: «БЫЛ ли этот объект установлен на ЛЮБУЮ ВЕЩЬ ВООБЩЕ, или это действительно ПУСТОЙ объект?». в данном случае это означает, что «есть ли у него КАКИЕ-ЛИБО свойства, даже если их соответствующие значения равны нулю???» - мне просто нужно знать, что у них ДЕЙСТВИТЕЛЬНО есть свойства, без использования блока «try catch» и без использования объектных функций (потому что они терпят неудачу, если объект действительно равен нулю).


person Community    schedule 28.01.2013    source источник
comment
Верно, что typeof(null) === 'object', но неверно, что [] === null. Можете ли вы объяснить, почему вы думаете иначе?   -  person ruakh    schedule 28.01.2013
comment
Можете пояснить, почему obj === null недостаточно?   -  person apsillers    schedule 28.01.2013
comment
Как вы вызываете метод add? Если this.item === null, то у вас может быть другое значение для this, чем вы ожидаете, что возможно. this устанавливается при вызове функции; не тогда, когда это определено.   -  person Jonathan Lonowski    schedule 28.01.2013
comment
@ all : см. обновленный вопрос - извините, что так долго (-_-); @apsillers: потому что, если obj === null, НО Object.keys(obj).length › 0, то мне НУЖНО знать об этом. с ДРУГОГО направления, если typeof(obj) === 'object', но Object.keys(obj) === undefined', тогда мне НУЖНО его игнорировать   -  person vector    schedule 29.01.2013
comment
#1) Как obj === null && Object.keys(obj).length > 0 всегда может быть правдой? Вы сделали опечатку? Должен ли быть !== вместо этого? #2) При каких обстоятельствах Object.keys(obj) возвращает undefined? Вы имеете в виду, если Object.keys(obj).length < 0?   -  person apsillers    schedule 29.01.2013
comment
@apsillers: хороший вопрос! это не опечатка, обещаю ;).   -  person vector    schedule 29.01.2013


Ответы (4)


после потери проблемы и возможности ее дублировать, я снова нашел проблему, и, поскольку я не был лишен сна, я решил ее и могу показать вам, как ее воспроизвести:

var $o = {};
// THIS is the CAUSE of the problem
$o.property = [];
$key = '1234asdf';
$value = 'this is a value for 1234asdf';
$o.property[$key] = $value;
alert(Array.isArray($o.property));

но, во всех смыслах и целях, это ДОЛЖНО проходить как «объект», а НЕ как массив, потому что различные библиотечные функции ЗАВИСЯТ от правильной идентификации. я знаю, согласно "ecma", это на самом деле "правильно", но мы не могли должным образом обнаружить это, НАВЕРНЯК, без вызова функции "объекта" (например: "Object.keys"), чтобы увидеть, дает ли он результат фатальная ошибка, означающая, что это ДЕЙСТВИТЕЛЬНО "массив", а не "массив, преобразованный в объект с ключами".

var $o = {};
// THIS is the SOLUTION to the problem
$o.property = {};
$key = '1234asdf';
$value = 'this is a value for 1234asdf';
$o.property[$key] = $value;
alert(Array.isArray($o.property));

Итак, ОТВЕТ: ОБЯЗАТЕЛЬНО ИСПОЛЬЗУЙТЕ ПРАВИЛЬНЫЙ КОНСТРУКТОР, ГДЕ ВОЗМОЖНО, потому что в какой-то момент это ВАЖНО! jsfiddle: http://jsfiddle.net/vector_thorn/RqhBm/1/

о, и это также ПРИЧИНА того, что объект «$ o.property» оценивался как «недействительный» из-за того, что он был обнаружен как пустой, нулевой или ложный. это будет == false, но не === false, и это потому, что «пустой массив» для меня бесполезен, поэтому, поскольку он определяется как массив, функции оценивают «$ o.property.length», который равен 0 вместо "Object.keys($o.property).length", который равен 1 - он имеет ДЕЙСТВИТЕЛЬНОЕ и ИСПОЛЬЗУЕМОЕ значение.

person vector    schedule 08.02.2013

Как насчет использования чего-то вроде typeof foo === 'undefined'

person Ismael Ghalimi    schedule 28.01.2013

Чтобы определить, является ли переменная/поле/что-либо фактическим объектом (в отличие от null, undefined или примитива), вы можете написать такую ​​функцию:

function isActualObject(x) {
    return x && // not null, undefined, false, 0, or ''
           typeof x !== 'number' && // not a numeric primitive
           typeof x !== 'boolean' && // not true
           typeof x !== 'string'; // not a string primitive
}

Обратите внимание, что это не определяет, имеет ли объект ключи, а только то, может ли иметь ключи. Чтобы определить, есть ли у него есть ключи, вы можете добавить дополнительную проверку:

function hasActualKeys(x) {
    return isActualObject(x) && Object.keys(x).length > 0;
}
person ruakh    schedule 28.01.2013
comment
Проще просто сделать return x !== null && typeof x === 'object' - person gsnedders; 29.01.2013
comment
да, я уже пробовал такие штуки. ознакомьтесь с подробно обновленным вопросом, чтобы увидеть всю проблему более ясно. но, спасибо за мысль и усилия ;) - person vector; 29.01.2013
comment
@gsnedders: Конечно, это проще, но это также неправильно, поскольку typeof не дает 'object' для всех объектов. (Спецификация требует, чтобы он возвращал 'function' для вызываемых объектов, и позволяет ему возвращать другие строки для других объектов, предоставляемых средой. Единственная гарантия состоит в том, что он не будет возвращать 'undefined', 'number', 'boolean' или 'string' для любого объекта.) - person ruakh; 29.01.2013
comment
@vector: Можете ли вы опубликовать Fiddle? Вы говорите, что alert($e.target.result) предупреждает [object IDBCursorWithValue], а alert($e.target.result.value) дает TypeError: $e.target.result is null, но на самом деле это не должно быть возможным. - person ruakh; 29.01.2013
comment
@ruakh Но функция - это реальный объект, поэтому я запутался. :) - person gsnedders; 29.01.2013
comment
@gsnedders: Извините, я не понимаю вашей точки зрения. Да, функция — это реальный объект; именно поэтому typeof x === 'object' не является достаточным тестом. - person ruakh; 29.01.2013
comment
@ruakh Вы сказали, чтобы определить, является ли переменная / поле / что-либо фактическим объектом ... Функция - это фактический объект на обычном языке. - person gsnedders; 29.01.2013
comment
@gsnedders: Да, вот почему мой код правильный (он возвращает true, если x является функцией), а ваш код нет (в этом случае возвращается false). Я не уверен, что вас смущает. . . - person ruakh; 29.01.2013

Если вы получили объект курсора, IndexedDB API гарантирует, что ключ существует в хранилище объектов. Запись все еще может быть undefined.

req = objectStore.openCursor();
req.onsuccess = function(e) {
  var cursor = e.event.target; 
  if (cursor) {
    var record = cursor.value; // record may still be undefined
    cursor.continue();
  } else {
    console.log('no more record');
  }
}

Упомянутая вами проблема может возникнуть только при использовании метода get, который не может отличить несуществующий ключ от значения записи undefined. Это четко указано в спецификации (см. примечание)< /а>.

person Kyaw Tun    schedule 29.01.2013