Unsure as to what this formatting means - javascript

I am fairly new to JavaScript and am going over some code. However there is one bit i am unsure about.
product = product !== null && product[0] !== null && product[0].id || "";
Where product is an array. Could someone please help me understand what this does. Any help would be much appreciated. Many thanks =)

One way to understand what this does it to run it and observe the result.
Here's a JSBin showing 3 examples - which produce a different outcome, depending on the initial value of product - https://jsbin.com/roruvecubi/edit?js,console
To further clarify this with an explanation...
It will attempt to evaluate that all the following premises are true at the same time and re-assign product to the value of id of the first object found (if these are found) or an empty string if otherwise.
product array is NOT null
AND
First element of product array is NOT null
AND
First element of product array is an object containing a truthy key-value pair with key id. I.e. First element could like this:
{
id: "someValue" // product[0].id would be a truthy value in this case
}
AND
If 3.0 is true - assign value of id. If 3.0 is NOT true (id: does not contain a truthy object, array, number, string, true - Google the precise definition of truthy), then just assign empty string "" and thus result will be product = "";

product !== null it checks if product is null if it is it will stop right here and not do the other calculations (this is practiced so you won't get undefined, in this case, hmm null)
product[0] !== null checks if null, so when .id you won't get an error can't find id of undefined / null
let usr = null
console.log(usr.id)
GIVES ERROR Uncaught TypeError: Cannot read property 'id' of null
enter code here
With a few words, these are some practices to check if the VARIABLE has unwanted values to stop the calculations right there and not get errors.
Some prefer to try catch v--

Related

Checking value of child that doesn't exist?

My html code contains a <ul id="users"></ul>, which is then populated dynamically with JS code
const li = document.createElement("li");
li.appendChild(document.createTextNode(`${nameInput.value} : ${emailInput.value}`)
I added a button in the html code to delete all users in that <ul>,as such: <button class="btn" id="del-user-list" onClick="deleteUserList()">Delete User List</button>.
My deleteUserList function in the JS code looks like this:
function deleteUserList() {
while (userList.firstChild != "") {
userList.firstChild.remove();
}
}
This works on the surface, however I realize that after the last child, my function will check once again for the value of a child that doesn't exist. I remember from studying C and playing with linked lists that you don't want to dereference a pointer that points to null.
Sure enough, when I look at the console I get
Uncaught TypeError: Cannot read properties of null (reading 'remove') at deleteUserList (main.js:31:25) at HTMLButtonElement.onclick ((index):29:77)
Is this a problem and what can I do about it? I just started playing with Javascript and don't have a good sense of how those things work right now.
Instead of comparing userList.firstChild to an empty string, you should compare it against null or omit the comparison operator entirely:
while (userList.firstChild != null)
// or
while (userList.firstChild)
The latter one works because converting null to a boolean value returns false
null != '' will always be true because userList.firstChild will never be an empty string anyway. It will either be a DOM node or null.

how to stop mongoose/javascript adding null values to arrays?

I have a mongoose schema which has a field of comments: [String].
When I try to update the schema, I am checking if the value is null or empty by adding the following code into my controller,
if (req.body.comments !== null || req.body.comments !== '') {
container.comments.push(req.body.comments)
}
container.save() ...
However when I run this code (using postman for testing) and do not provide a value for the comment field, it updates in the database as null in the array.
comments: [String] is in the main schema definition and not part of a suc-document or anything like that.
Would anybody know a way round this issue or why this happens?
Make sure that comments is not undefined, you can handle all cases this way:
if (req.body.comments && req.body.comments !== '') {
container.comments.push(req.body.comments)
}
That way empty strings, null and undefined values are not added, assuming req.body.comments always comes in as a string.
You need to set container.comments as an empty array before you reach your condition statement
container.comments = container.comments || []
if (req.body.comments && req.body.comments !== '') {
container.comments.push(req.body.comments)
}
this way the data saved on your database will always be an array, regardless of your sending comments on your request or not.
also its worth mentioning that saving an empty array on monggose will result to undefined unless you override it.
edited the example to take consideration if the array is not empty

Why are these undefined variables not equal javascript?

Suppose I have the following event handler:
function handleCsvDump(e) {
console.log(e.currentTarget.getAttribute('download'));
e.currentTarget.download = undefined;
console.log(e.currentTarget.getAttribute('download'));
console.log(e.currentTarget.getAttribute('download') === undefined);
The information logged to the console when the corresponding button is clicked is:
mycsv.csv
undefined
false
Why is the last value false? Since e.currentTarget.getAttribute('download') is undefined, shouldn't it be true? If this is the wrong way to go about this, how can I test whether a variable is undefined?
You have to be careful when setting things this way, often things are expected to be strings, and if you set a value that isn't a string, it will first be coerced to a string, then assigned.
The download attribute is indeed a DOMString, meaning that anything you assign to it will first be coerced to a string if it isn't already, so when you assign undefined, it's actually first coerced to "undefined" and that is stored.
When you get it back out, and compare it to undefined, you're actually doing:
console.log("undefined" === undefined)
Hence getting false. If you do actually want to remove it, which is implied by wanting to set it to undefined (or null), you can instead use removeAttribute:
e.currentTarget.removeAttribute('download')

When to check for undefined and when to check for null

[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'.

IE8 Javascript: '2' is null or not an object

I'm getting a nonsensical error message in IE8, tell me that the constant '2' is null or not an object. The line of code is:
if (! localtree[idx][2]) {
I also tried coding it like this:
if (localtree[idx][2] == 0) {
The value in the array at that location is always zero (for now).
How can IE8 think that the number 2 is null? I'm mystified!
The exact error is:
Message: '2' is null or not an object
Has anyone seen this?
EDIT : This is a very misleading error message. See my answer below for what actually went wrong.
This is a very confusing error message. It turned out that I was stepping one element beyond the end of the array. 'idx' was referencing a non-existent value that I was attempting to treat as an array reference (with the [2]).
Rather than telling me that '2' was null, it should have said that 'localtree[idx]' was null.
The root cause of this was that I had a trailing comma where I defined the array, leading to an extra, null value in the array. In firefox, trailing commas are ignored (like in perl), but in IE, they are significant.
the constant '2' is null or not an object
if (! localtree[idx][2]) {
JavaScript doesn't have constants, at least not yet. And you aren't checking a number, but a member of an array, i.e.: the variable with index number 2 of object localtree[idx] (where idx must contain a string to refer to an object property or an index number to refer to an array).

Categories