I want to pass the values from my request body into a paramsDict object where I have defined constraint to test the parameters against. I don't require that all possible parameters are sent with every request and also, if a value is deleted on the client, it can be sent as an empty string.
So we pass the values to the dictionary like so
for ( p in paramsDict ) {
if ( container[p] ) {
paramsDict[p].value = container[p];
}
}
where container is set to req.body (in node.js express).
In the case where container[p] = "" the property paramsDict[p].value never gets set, i.e typeof paramsDict[p].value returns "undefined" (note: it does not exist on the object before I attempt to assign it here). This means adding an extra check which I would rather not have to:
if (typeof container[p] == "string" && container[p].length == 0){
paramsDict[p].value = "";
}
Investigating I see that paramsDict[p].value = "" and paramsDict[p].value = false both set the property to the empty string and false respectively (I include false because the empty string is falsey in JS).
typeof container[p] returns "string" when the value is the empty string so I am very surprised that is does not assign the empty string as the value.
Is this a decision that has been made for this implementation of JS or is it a bug?
Your check for the property [p] will return false even in the cases you care about (empty string or false). Instead of if (container[p]), you should use if (container.hasOwnProperty(p)).
You answered your own question: empty string is falsy, so this will evaluate to false when container[p] === '':
if ( container[p] ) {
So, assignment to paramsDict won't happen.
Related
What is the least amount of code needed to do the following:
If an object exists and it has a required property and the property is not an empty string then set a variable to the value of the property else set the variable to a default string.
Assuming that the object variable can only be undefined or a valid object, it can never be a function, null, string or anything else. Also if the object has the required property it is a string and never anything else.
A solution to this maybe:
// obj is the object we are testing, prop is the name of the property, def is the default string
var result = def;
if (obj && obj[prop] && obj[prop].length) {
result = obj[prop];
}
Whether this is completely correct I am unsure.
But is there a shorter way?
Thanks,
AJ
If you want to shorten it, you can write:
result = (obj && obj[prop]) || def;
An empty string is falsy, so you don't need to check the length explicitly.
result = <val> || <default>;
is a common idiom for setting a variable to a value, with a default if the value is null.
I am setting a mode in a script by passing a "truthy" boolean to a function. In the function a simple if statement checks if the param is true or false. I sometimes pass it as a string or a bool which has always worked, but for some reason it isn't for this:
setMode: function(Setting) {
if (Setting) {
console.log('Enabling mode');
} else {
console.log('Disabling mode');
}
}
For example when I pass it a string 'false' and log Setting to console, the console says false, yet the if statement thinks it's true.
I have to add this to the start of the function for it to work:
if (typeof Setting == 'string') {
Setting = (Setting == "true");
}
An example of it in use:
var inverted = $('INPUT[name="Mode"]').prop('checked');
app.setMode(inverted);
and another:
var mode = localStorage.getItem('Mode');
this.setMode(mode);
It's so bizarre since I've done this type of thing for years yet it's only starting now. Maybe because I'm using localStorage and .prop?
If you try to log 'false' it is obvious that console logs false(it is a string) and that the if statement sees true, because a not-empty string is a true boolean value.
If you want to check if the string is "true" or "false" you have to do it with normal operators. So you could add this line at the beginning of your function:
Setting = (typeof Setting === 'string') ? Setting === "true" : Setting;
To answer your question about string to boolean conversions:
ECMA SPEC:
The result [of this conversion] is false if the argument is the empty String (its length is zero);
otherwise the result is true.
So yes, if you pass the string "false" it will be converted to true, which means the only option you have is to manually check for the strings "true" or "false" and do the conversion by yourself.
However, the jQuery function .prop("checked") is supposed to return a boolean value (or undefined if the property is not defined). So I would say you should be able to actually do
if (elem.prop("checked"))
like here.
For example when I pass it a string 'false' and log it to console, the console says false, yet the if statement thinks it's true.
The console output is confusing, it is concealing the quotes and logging false both for the string "false" and the boolean false. Yet, these two are not equivalent, the string is not empty and indeed truthy.
Maybe because I'm using localStorage and .prop?
Yes. The .checked property returns a boolean and everything works well. In contrast, local storage only stores strings, and when you pass in a boolean you get back its stringification. You can undo that by using
var modeStr = localStorage.getItem('Mode');
var mode = JSON.parse(modeStr);
this.setMode(mode);
I have a simple if statement
if(variable == null)
does not enter the statement
if(variable == "")
does
Why does this happen??
What is the difference between "" and null in javascript
"" is the empty string. In other words, it's a string of length 0. null on the other hand is more like a generic placeholder object (or an object representing the absence of an object). There's also undefined which is different from both "" and null.
But the point is, "" != null so therefore:
var s = "";
s == null; // false
s == ""; // true
The ECMA–262 Abstract Equality Comparison Algorithm (§ 11.9.3) says that null == null (step 1.b) or null == undefined (steps 2 and 3) return true, everything else returns false.
There are types in JavaScript
typeof("") is "string" and typeof(null) is "object"
"" is a string object with a length of zero. null is the value the represents the absence of a value. A string object is never null, regardless of its length.
As SHiNKiROU mentioned, there are types in Javascript. And since the language is dynamically typed, variables can change type. Therefore, even though your variable may have been pointing to, say, an empty string at some point, it may be changed to point to, say, a number now. So, to check the concept of "nonexistence" or "nothingness" or "undefinededness" of a variable, Crockford recommends against doing stuff like if (variableName == null).
You can take advantage of javascript's dynamically-typed qualities. When you want to check for a variable's "falsiness" or "nothingness", instead of if(variableName == null) (or undefined or "") use if(!variableName)
Also, instead of if(variableName != undefined) (or null or "") use if(variableName)
[Bounty Edit]
I'm looking for a good explanation when you should set/use null or undefined and where you need to check for it. Basically what are common practices for these two and is really possible to treat them separately in generic maintainable codee?
When can I safely check for === null, safely check for === undefined and when do I need to check for both with == null
When should you use the keyword undefined and when should one use the keyword null
I have various checks in the format of
if (someObj == null) or if (someObj != null) which check for both null and undefined. I would like to change all these to either === undefined or === null but I'm not sure how to guarantee that it will only ever be one of the two but not both.
Where should you use checks for null and where should you use checks for undefined
A concrete example:
var List = []; // ordered list contains data at odd indexes.
var getObject = function(id) {
for (var i = 0; i < List.length; i++) {
if (List[i] == null) continue;
if (id === List[i].getId()) {
return List[i];
}
}
return null;
}
var deleteObject = function(id) {
var index = getIndex(id) // pretty obvouis function
// List[index] = null; // should I set it to null?
delete List[index]; // should I set it to undefined?
}
This is just one example of where I can use both null or undefined and I don't know which is correct.
Are there any cases where you must check for both null and undefined because you have no choice?
Functions implicitly return undefined. Undefined keys in arrays are undefined. Undefined attributes in objects are undefined.
function foo () {
};
var bar = [];
var baz = {};
//foo() === undefined && bar[100] === undefined && baz.something === undefined
document.getElementById returns null if no elements are found.
var el = document.getElementById("foo");
// el === null || el instanceof HTMLElement
You should never have to check for undefined or null (unless you're aggregating data from both a source that may return null, and a source which may return undefined).
I recommend you avoid null; use undefined.
Some DOM methods return null. All properties of an object that have not been set return undefined when you attempt to access them, including properties of an Array. A function with no return statement implicitly returns undefined.
I would suggest making sure you know exactly what values are possible for the variable or property you're testing and testing for these values explicitly and with confidence. For testing null, use foo === null. For testing for undefined, I would recommend using typeof foo == "undefined" in most situations, because undefined (unlike null) is not a reserved word and is instead a simple property of the global object that may be altered, and also for other reasons I wrote about recently here: variable === undefined vs. typeof variable === "undefined"
The difference between null and undefined is that null is itself a value and has to be assigned. It's not the default. A brand new variable with no value assigned to it is undefined.
var x;
// value undefined - NOT null.
x = null;
// value null - NOT undefined.
I think it's interesting to note that, when Windows was first written, it didn't do a lot of checks for invalid/NULL pointers. Afterall, no programmer would be dumb enough to pass NULL where a valid string was needed. And testing for NULL just makes the code larger and slower.
The result was that many UAEs were due to errors in client programs, but all the heat went to Microsoft. Since then, Microsoft has changed Windows to pretty much check every argument for NULL.
I think the lesson is that, unless you are really sure an argument will always be valid, it's probably worth verifying that it is. Of course, Windows is used by a lot of programmers while your function may only be used by you. So that certainly factors in regarding how likely an invalid argument is.
In languages like C and C++, you can use ASSERTs and I use them ALL the time when using these languages. These are statements that verify certain conditions that you never expect to happen. During debugging, you can test that, in fact, they never do. Then when you do a release build these statements are not included in the compiled code. In some ways, this seems like the best of both worlds to me.
If you call a function with no explicit return then it implicitly returns undefined. So if I have a function that needs to say that it did its task and there is nothing result, e.g. a XMLHTTPRequest that returned nothing when you normally expect that there would be something (like a database call), then I would explicitly return null.
Undefined is different from null when using !== but not when using the weaker != because JavaScript does some implicit casting in this case.
The main difference between null and undefined is that undefined can also mean something which has not been assigned to.
undefined false
(SomeObject.foo) false false
(SomeObject.foo != null) false true
(SomeObject.foo !== null) true true
(SomeObject.foo != false) true false
(SomeObject.foo !== false) true false
This is taken from this weblog
The problem is that you claim to see the difference, but you don't. Take your example. It should really be:
var List = []; // ordered list contains data at odd indexes.
var getObject = function(id) {
for (var i = 1; i < List.length; i+=2) {
if (id === List[i].getId()) {
return List[i];
}
}
// returns undefined by default
}
Your algorithm is flawed because you check even indexes (even though you know there's nothing there), and you also misuse null as a return value.
These kind of functions should really return undefined because it means: there's no such data
And there you are in the heart of the problem. If you don't fully understand null and undefined and may use them wrongly sometimes, how can you be so sure that others will use it correctly? You can't.
Then there are Host objects with their nasty behavior, if you ask me, you better off checking for both. It doesn't hurt, in fact, it saves you some headaches dealing with third party code, or the aformentioned non-native objects.
Except for these two cases, in your own code, you can do what #bobince said:
Keep undefined as a special value for signalling when other languages might throw an exception instead.
When to set/use them...
Note that a method without a return statement returns undefined, you shouldn't force this as an expected response, if you use it in a method that should always return a value, then it should represent an error state internally.
Use null for an intentional or non-match response.
As for how/when to check...
undefined, null, 0, an empty string, NaN and false will be FALSE via coercion. These are known as "falsy" values... everything else is true.
Your best bet is coercion then testing for valid exception values...
var something; //undefined
something = !!something; //something coerced into a boolean
//true if false, null, NaN or undefined
function isFalsish(value) {
return (!value && value !== "" && value !== 0);
}
//get number or default
function getNumber(val, defaultVal) {
defaultVal = isFalsish(defaultVal) ? 0 : defaultVal;
return (isFalsish(val) || isNaN(val)) ? defaultVal : +val;
}
Numeric testing is the real bugger, since true, false and null can be coerced into a number, and 0 coerces to false.
I would treat them as 2 completely different values, and check for the one you know might occur.
If you're checking to see if something has been given a value yet, check against undefined.
If you're checking to see if the value is 'nothing,' check against 'null'
A slightly contrived example:
Say you have a series of ajax requests, and you're morally opposed to using callbacks so you have a timeout running that checks for their completion.
Your check would look something like this:
if (result !== undefined){
//The ajax requests have completed
doOnCompleteStuff();
if (result !== null){
//There is actually data to process
doSomething(result);
}
}
tldr; They are two different values, undefined means no value has been given, null means a value has been given, but the value is 'nothing'.
This code fails with an exception indicating invalid JSON:
var example = '{ "AKEY": undefined }';
jQuery.parseJSON(example);
I was able to fix it by replacing all undefineds with empty strings. Are undefineds not part of JSON?
If you can wrap your head around this, the token undefined is actually undefined.
Allow me to elaborate: even though JavaScript has a special primitive value called undefined, undefined is not a JavaScript keyword nor does it have any special meaning. You can break code which tests for the existance of an object by comparing to undefined by defining it.
var obj = { BKEY: 'I exist!' };
if (obj.AKEY == undefined) console.log ('no AKEY');
if (obj.BKEY == undefined) console.log ('should not happen');
undefined='uh oh';
if (obj.AKEY == undefined) console.log ('oops!'); // Logically, we want this to execute, but it will not!
if (obj.BKEY == undefined) console.log ('should not happen');
The only console output will be 'no AKEY'. After we've assigned to the global variable undefined, obj.AKEY == undefined becomes false because undefined != 'uh oh'. obj.BKEY == undefined still returns false, but only because we're lucky. If I had set obj.BKEY='uh oh', then obj.BKEY == undefined would be true, even though it actually exists!
You probably want to explicity set AKEY to null. (By the way, null is a keyword; null='uh oh' throws an exception).
You could also simply omit AKEY from your JSON, in which case you would find:
typeof(example.AKEY) == 'undefined'
(If you set AKEY to null, then typeof(example.AKEY) == 'object'.)
The only real difference between setting to null and omitting is whether you want the key to appear in a foreach loop.
No, but null is. RFC 4627 §2.1:
A JSON value MUST be an object, array,
number, or string, or one of the
following three literal names:
false null true
var example = '{ "AKEY": null }';
Correct. Undefined and functions are not represented in JSON. http://www.json.org/js.html
They're not permitted in JSON...look at the alternative and it's clear as to why:
var example = '{}';
var obj = jQuery.parseJSON(example);
obj.AKEY //undefined
If it's undefined, when you go to access it, it's the same as the key not even being present. Since JSON's primary purpose is for transmitting data (otherwise the broader object literal syntax is fine)...it's better to leave it out altogether.