Reference to loverajoel/jstips#62
The tip is not about checking whether a property is defined (o.key = 'value' ) but only whether the key has been set on the object, via key in o
or o.hasOwnProperty('key')
The null-or-undefined check is done with loose-equals and null:
// test helpers
function test(actual) { console.log(!!actual); }
function undef() { /* returns undefined */ }
var o = {};
// existence checks
test(typeof o.key === 'undefined'); // true
test(o.key == null); // true
test('key' in o); // <= false - the key of 'key' is not declared
test(o.hasOwnProperty('key')); // false
// exists but undefined
o.key = undef();
test(typeof o.key === 'undefined'); // still true
test(o.key == null); // still true
test('key' in o); // true, since o.key has now been declared even if it has no value
test(o.hasOwnProperty('key')); // true...
// no longer exists
delete o.key; // remove key from o
test(typeof o.key === 'undefined'); // still true
test(o.key == null); // still true
test('key' in o); // false again, since 'key' is no longer a property name in o
test(o.hasOwnProperty('key')); // false...
// exists but defined as null...
o.key = null;
test(typeof o.key === 'undefined'); // <= false
test(typeof o.key === 'object'); // <= true
test(o.key == null); // still true
test('key' in o); // true again, since o.key has now been declared even if it has no value
test(o.hasOwnProperty('key')); // true..
Maybe you should explain that here it returns true, because Boolean(o.key) is false and Boolean(null) is false and since you are not comparing their identities they are equal. You may also add
o.key === false // false
as an example