PDA

View Full Version : 'falsey' values that are not undefined



jscheuer1
04-26-2018, 09:06 PM
Yes, I think about these things sometimes. What are the 'falsey' values that are not undefined (useful in iterating over an object when .hasOwnProperty() is either unavailable or inadvisable, or iterating over an array when you want to know if something, anything, even a 'falsey' value is defined for a given index).

Anyways, so far I have the empty string, 0, null, and false:


['', 0, null, false]

Anyone have any additional ideas?

keyboard
04-27-2018, 02:14 AM
["", '', ``, 0, -0, 0.0, 0x0, null, false, undefined, NaN, void 0]

james438
04-27-2018, 02:16 AM
Is the following table what you are looking into?

https://dorey.github.io/JavaScript-Equality-Table/

A while back I looked into something similar with php regarding various types of empty values. See the following php documentation: PHP type comparison tables (http://www.php.net/manual/en/types.comparisons.php)

Please let me know if I am misunderstanding.

jscheuer1
04-27-2018, 03:41 AM
["", '', ``, 0, -0, 0.0, 0x0, null, false, undefined, NaN, void 0]

To begin, the first three all appear to be === to the empty string. Have I missed something there? (from the console):


"" === ''
true
`` === ''
true

And I said, "that are not undefined" so that lops off one. Unquoted 0.0, and -0, as far as I know*, evaluate to 0, so two more bite the dust. NaN and void 0 I'm not sure of. Just checked in the console, and:


NaN == false

returns false, so is not 'falsey'.

and:


void 0

returns undefined, so is technically not what I'm looking for. But is worthy of further consideration.

The void keyword by itself is odd. From what I can tell, nothing can be set to it, so it also shouldn't enter into this. However, odd as it is, void merits further study.

Thanks for the input, and if you would like to refute anything I've said, or simply comment further upon it, please do.


*from the console:


0.0 === 0
true
-0 === 0
true

jscheuer1
04-27-2018, 03:45 AM
Is the following table what you are looking into?

Yes, but it is in error. Or at least as I read it. It appears to me to say null === undefined, but it doesn't.

Then again it might just mean that null == undefined, which I knew, but that's not what I'm after.

keyboard
04-27-2018, 05:10 AM
To begin, the first three all appear to be === to the empty string. Have I missed something there? (from the console):
Yeah they are all an empty string, just included them all for my own sake of complete coverage.


And I said, "that are not undefined" so that lops off one.
Yeah. Again I just included undefined for coverage sake.


Unquoted 0.0, and -0, as far as I know*, evaluate to 0, so two more bite the dust.
Yup. They all evaluate to 0 just because of the way JS stores numbers. Same with 0x0.
Starting to see a pattern of me just including stuff because I think its cool haha.


NaN == false
returns false, so is not 'falsey'.
NaN == true also evaluates to false.
Also
if(NaN) {
console.log(true);
} else {
console.log(false);
}
returns false. So I believe it is falsey.


void 0
returns undefined, so is technically not what I'm looking for. But is worthy of further consideration.
Yeah it just evaluates an expression and returns undefined.



Most of the stuff on here I just included because it was interesting.
To be honest I still have no idea what you were trying to do in the first place haha (the bit about how it would be useful when iterating without hasOwnProperty).

jscheuer1
04-27-2018, 07:30 AM
NaN is creepy and I may have to include it. Using undefined kind of defeats the purpose because [][0] is undefined, and so is [undefined][0]. So there's no way around it without something like hasOwnProperty(), which I don't believe was intended for such use and I don't think works on arrays anyway. MMMmmm. It does work on arrays:


[undefined].hasOwnProperty(0)

is true. Unfortunately:


[].hasOwnProperty(0)

is a syntax error. But you can do:


a = []
[]
a[1] = 'bob'
"bob"
a.hasOwnProperty(0)
false
a[0] = undefined
undefined
a.hasOwnProperty(0)
true

So, combined with length, you could work something out. But what I'm working with should be OK as long as someone doesn't use undefined and is trying to mean false when the default is true:


var runningflags = {};
function lotto(cfg){
cfg = cfg || {};
var defaults = {
totalnumbers: 10, // how many numbers to generate
lowerbound: 1, // lower bound for generated numbers
upperbound: 70, // upper bound for generated numbers
interval: 20, // how quickly calculations repeat until finalized (milliseconds)
caltime: 1000, // how long until calculations finalized (milliseconds)
id: 'lottery1', // id of target element that shows result
noadjacent: true, // should there be at least 2 between selected numbers
padsingle: false, // should single digits be padded with preceding 0
sort: true, // should result be sorted
dupes: false // allow duplicate numbers
};
this.setprops(defaults, cfg); . . .

and:


lotto.prototype = {
setprops: runningflags.hasOwnProperty? function(d, c){for(var p in d){this[p] = c.hasOwnProperty(p)? c[p] : d[p];}
} : function(d, c){for(var p in d){this[p] = c[p] || [0, '', null, false].indexOf(c[p]) > -1? c[p] : d[p];}}, . . .

This will allow lowerboud to be set in the cfg to 0 and things like noadjacent and sort in the cfg to be set to false, even when .hasOwnProperty() is unavailable. Now I know that often, if not aways, when .hasOwnProperty() is unavailable that [].indexOf() is also unavailable. But that's easy to fix:


if(![].indexOf){ // for IE 8 and less
Array.prototype.indexOf = function(v, i){
var l = this.length;
if(typeof i === 'number'){if(i < 0){i = l + i;}} else {i = 0;}
--i;
while(++i < l){if(v === this[i]){return i;}}
return -1;
}
} (taken loosely from the MDN Polyfill for Array.indexOf)

Maybe they have a poly for hasOwnProperty() - nope, just checked.

jscheuer1
04-27-2018, 07:40 AM
I think I've figured this out and it should also work for arrays, but would be a little more cumbersome. Anyways, for objects:


function setprops(d, c){
var p, tmp = {};
for(p in c){tmp[p] = true;}
for(p in d){this[p] = tmp[p]? c[p] : d[p];}
}

Even simpler:


function(d, c){for(var p in d){this[p] = p in c? c[p] : d[p];}}

jscheuer1
04-27-2018, 02:50 PM
The more I looked into what hasOwnProperty means and why it might be useful, things became more complicated again, both for when it's available and when it's not. So for now I'm using this:


setprops: runningflags.hasOwnProperty? function(d, c){for(var p in d){if(d.hasOwnProperty(p)){this[p] = c.hasOwnProperty(p)? c[p] : d[p];}}
} : function(d, c){for(var p in d){if((!d.prototype || !p in d.prototype) && !p in Object.prototype){this[p] = p in c? c[p] : d[p];}}},

jscheuer1
04-27-2018, 06:37 PM
You can't polyfill hasOwnProperty because all or at least some of the browsers that don't support it also don't support assigning things to the Object.prototype. Here's the next best thing (more or less, still figuring, use a more distinct variable name for the function or encapsulate it in the area where it's needed):


var op;
if(Object.prototype.hasOwnProperty){op = function(obj, p){return Object.prototype.hasOwnProperty.apply(obj, [p]);};}
else {op = function(obj, p){return p in obj && (!obj.prototype || !p in obj.prototype) && !p in Object.prototype;};}

jscheuer1
04-28-2018, 03:13 AM
Not so important though I see, after further research, you have to go back to before IE 6 at least (probably before IE 5 or IE 5.5), before you find a browser that doesn't support hasOwnProperty, at least as it applies to true objects.