vector
vector

Reputation: 83

object has keys but evaluates to null

the problem is, there is no "standard function" you can write to detect if some thing "is set". for example, if it truly is a null object, then, you don't want to work with it; but, if it has keys, then you DO want to work with it - however, if you try to see if it has keys when it does not, even though "typeof" returns "object", using "Object.keys()" throws an error, saying it is not an object. so, we seem to have a catch 22 here (o_O)... is there a better way to see if an object is truly null, or if it has keys, without throwing an error?

i've been using a basic function to see if a object is even SET before then seeing if it has a valid VALUE, but, i'm running into scenarios where this fails. in the indexeddb scenario, and the "this.items" scenario, both evaluate to "null", even though their "type" is an "object", and their "objects" HAVE keys; but if i evaluate the keys when there are none, it will throw another error, because the object TRULY is null at this point (no keys / properties). using "object" functions, such as "Object.keys" or "hasOwnProperty" etc throws an "this is not an object" error.

essentially, what i NEED to do, is to be able to properly determine: "HAS this object been set to ANY THING AT ALL, or is it a truly EMPTY object?". in this case, this means that "does it have ANY properties, even if their respective values are 'null'???" - i just need to know that they DO have properties, without using a "try catch" block, and without using object functions (because they fail if the object truly is null).

Upvotes: 0

Views: 5212

Answers (4)

vector
vector

Reputation: 83

after loosing the problem, and the ability to duplicate it, i found the problem again, and, since i was not sleep deprived, i solved it, and, i can show you how to replicate it:

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));

but, for all intents and purposes, this MUST pass as an "object", and NOT an array, because the various library functions DEPEND on proper identification. i know, according to "ecma", that IS actually "correct", but, we could not properly detect against it, FOR SURE, without calling an "object" function (eh: "Object.keys") to see if it yields a fatal error, meaning that it is TRULY an "array", and not an "array converted into an object with 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));

so, the ANSWER is: MAKE SURE TO USE THE CORRECT CONSTRUCTOR, WHERE EVER POSSIBLE, because, at some point, it DOES MATTER! jsfiddle: http://jsfiddle.net/vector_thorn/RqhBm/1/

oh, and, this is also the REASON that the object "$o.property" was being evaluated as "invalid", due to being detected as empty or null or false. it will == false, but not === false, and this is because an "empty array" is useless to me, so, since it's being detected as an array, the functions are evaluating "$o.property.length", which is 0, instead of "Object.keys($o.property).length", which is 1 - it has a VALID and USABLE value.

Upvotes: 1

Kyaw Tun
Kyaw Tun

Reputation: 13131

If you received a cursor object, IndexedDB API ensure that the key exists in the object store. The record may still be 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');
  }
}

The problem you mention can only be happened when you use get method, which cannot distinguish between non-existing key and undefined record value. It is clearly stated in the spec (see Note).

Upvotes: 0

ruakh
ruakh

Reputation: 183211

To determine if a variable/field/whatever is an actual object (as opposed to null, undefined, or a primitive), you can write a function like:

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
}

Note that this doesn't detect whether the object does have keys, only whether it could have keys. To detect if it does have keys, you can add an additional check:

function hasActualKeys(x) {
    return isActualObject(x) && Object.keys(x).length > 0;
}

Upvotes: 0

Ismael Ghalimi
Ismael Ghalimi

Reputation: 3565

How about using something like typeof foo === 'undefined'

Upvotes: 0

Related Questions