It is just a matter of understanding and remembering which values are considered falsey. I always write code like this (short hand that is) and had no problem with it.
Yes, this. The programmer has to understand the context in which their code is written, and make sure the appropriate constructs are used. It's not that using "if (!something) {...}" is inherently bad; it's using it incorrectly that's bad.
@@mikeonthebox That's the biggest issue I have with his videos and advice in general. What he says isn't necessarily bad, but he sometimes tries to back it up with awful examples.
Javascript’s falsy/truthy evaluation is one of its worst features. It’s terrible. Stop using it. Be explicit by comparing to undefined or null or empty string or whatever. You’ll thank me some day.
@@TrackedHiker Depends on what you're trying to do though. Checking if a string input is empty and then doing an early return is fine. Then you don't care if it's undefined, null or whatever else it may be. If a string is required for further usage, I'd say the following is sufficient: if (!input || typeof input !== 'string') return; The thing I find more evil is the following: if (input) { // Do stuff } The problem with that code is that you've really only asserted that there is a value, not what it is. That is inviting far more trouble than !input will ever do based off my own experiences.
The problem is not type coercion, the problem is not understanding falsies. ![].length is a common pattern to check for empty arrays. Ps. Your code allows negative values, that's a bug.
But he wasn't doing this video to write an actual check on number of children. It was to prove how to properly check if (in this instance) that value was an actual number, and a negative number is still a number. Right?
@@debo4jc Then the example shouldn't say number of children. It should say enter a number. I don't think this is a good example about the pitfalls of type coercion. null is an assigned value, all variables start with undefined. The proper solution is if (numberOfChildren !== NaN && numberOfChildren > -1)
I think what using this operator is very useful, espacially with objects. It covers undefined and null. Bang operator only makes problem with number type.
It's all about knowing what you are actually checking for. If I check for a number or string, I use typeof instead. for anything else, bang does the job just fine.
@@DzikiMoronHackshield There is absolutely nothing wrong with it, and it's easy to understand the question posed in the if. Is the bag(array) empty? This video uses a very common mistake in coding, but it's not the bang operators fault. The coder is simply asking the wrong question. I read somewhere, (cant remember where anymore), that the best way to handle branching logic is by posing it as proper questions first, then convert it to code afterwards. Have made a lot less mistakes after changing to that method.
@@DzikiMoronHackshield Array being undefined will throw error. At least make it array?.length. In which case !array?.length would be appropriate to check for empty or null array.
I can't say how much I appreciate the content you created over the years. I watched a lot of RU-vid tutorials, but you're the only one that made me actually want to learn new things, because you explained every concept in the most clear and logical way. I might soon get a job in the field, and I don't think I would if I haven't stumbled onto your channel. I am eternally grateful for everything you do, you're the best, thank you, have a nice day!
I have to disagree on this one, JS gives you power tools, use them right. 0 == false isn't a bug. write your code knowing what it does and you're perfectly fine with this "!value" syntax
“Power tools” like a chainsaw that has no kickback bar and randomly turns on by itself? Yeah no thanks. Falsiness and truthiness aren’t features of JavaScript. They’re defects.
But the main problem with your code is that you fixed the ! stuff but what about negativ values -so a full done xample would have been really apreciated, now it looks a little bit incomplete
Yeah this isn't necessarily bad, it just has its quirks. When it comes to numbers, I usually go for more explicit checks such as "x > 0" or "arr.length === 0" etc. in order to make it clearer what I'm checking for and to avoid these quirks. For example, when it comes to React, using "arr.length && " will result in number 0 being shown in UI when that arr has no elements, so being more explicit will avoid that bug.
The thumbnail is incomplete, using the bang operator is bad if you don't know its implicit implications. Otherwise it's pretty useful. And much more powerful with typescript.
The only values with which cast to boolean doesn't work fine are zero and enpty string. The most common case of using if (!smth.smth) is to check for object. Completely disagree with the point that implicit coercion should be avoided. It should be used almost always unless in this place it doesn't fit. But parseInt should be avoided almost always. It introduces the bug with parsing prefix instead of the whole input. But in you code normal cast to number will return 0 and not null, so that code is already broken. Instead for numeric inputs you should use input.valueAsNumber. And for string input check to space-only string before cast to number.
This is only a problem in weakly typed languages. In strongly typed languages, if statements require a boolean, if you are checking anything else, there must be an explicit comparison somewhere.
I never saw a person using a bang operator on a integer value. I think this video is addressing a problem that in almost all cases doesn't even exist, in all modern compiled language you can't even use this operator on value types, it's just how js works which allow any kind of operation. I mean, the video give some interesting explanation for newer people but really not pratical, if the documentation says that the parse might return NaN just check for NaN?
When I'm checking if a value is a number, I use Number.isFinite(value) (not the same as window.isFinite). It returns false if the type of the value is not a number, and also returns false if it is NaN.
That's a nice way to ensure a value is a non-problematic valid numerical value. The only downside is that it doesn't support object-wrapped Numbers, because it sees them as Objects instead of Numbers, even though we can use valueOf() to get the internal primitive value
@@juliohintze595 No, lol. They're not necessary in most cases. They could be seen as a consequence of how ECMAscript works, and the fact that "everything is an object" in JS. Some JS methods are "aware" of Object-Wrapped primitives, but Number static methods intentionally ignore them because they are not quite primitive numbers
We (by we I mean I) had a case of this in our production code. Basically, we had old BE data that was being passed to us, and potentially new FE data that the user was inputing. They could save, so we would need to transform the data and send it to the backend, EITHER the old data or the new data. Of course, dumb me used code like this NewBeData = NewFEData || OldBeData. After watching the video you will understand why this is bad. If the user types in valid but falsey values, it will not update. So if a fee was 0 dollars, it would not save that...oops. And while the video suggests a great pattern, another is the null coalescing operator. You can think of it as a special case || operator. It looks at the first value, and if it is null or undefined, it uses the second value. Super handy in very specific Type Coercion situations.
Something I would like to know is if this is as important in typescript? for example you know the input will be (string | undefined) or (boolean | undefined).
String is problematic because the empty string is falsy. But sometimes you do want that behavior. Overall I think it’s common to use the bang operator liberally in typescript because it’s less likely to cause an unexpected type coercion.
@@jacobstern2150 Ah I see how that can be a problem and could cause some issues. Definitly something to keep in mind when using. Thanks for the knowledge.
@@a-fletcher Yeah as I said it’s still okay to use the bang operator for strings in my opinion but you have to be aware when reading and writing that it means (s != null && s.length > 0)
I always end up adding z bunch of explicit options rather than just using the bang operator. I only use the bang operator when im literally thinking "is it 0, bull, undefined, or an empty string" specifically, which is rare.
Thanks for the details!This is why I never feel comfortable on js… so many edge cases I can go wrong… and not easy to test it out. I know I am going to forget this video next week. Why don’t we all go back the strong typed…
Well jotting these tips down in a note could help for you to remember until it comes automatically with practice. As for strong typing, you could always just use TypeScript instead
It's a js problem, any type other than bool shouldn't be allowed to use "!" The first place, unless in something like "! int1 == int2", anyway .. RU-vid suggested the wrong thing again, please guys add "JS" to the title of your js videos if you can, keep up the good work man 👍.
At 6:22, shouldn't you use the || operator ? With the && the if will always be false no ? Since the variable can't be null and NaN at the same time. Or am I missing something ?
the expression inside the if statement in 6:26 can never be true because they are mutually exclusive, there should be an OR not an AND there, i know you know, but i just wanted to point it out in case you missed it in the editing.
@@mikeonthebox it’s more of a general way I use for all inputs not just numbers. So spaces can be used. 4.345 would still be a string when the value is taken from the input so it would still work.
It should use Number.isNaN(), also using Typescript would solve most of this kind of problems. I get you make videos mostly for new developers, so take the time and teach them Typescript instead
Assuming this is for inputting how many children you have (and not some weird setting where negative children makes sense, whatever that might be), the most correct and readable solution would be: if(numberOfChildren >= 0) { // success } else { //error } Here you let type coercion work for you and not against you. Since parseInt will return only NaN or a Number, and NaN is neither equal, greater than or smaller than anything, so this would only accept positive integer values of children.
Assuming this is an application that deals with something perverse where children can be owed so it makes sense to have negative numbers, so you want this to be success for any finite integer, use if(isFinite(numberOfChildren) { // success } else { //error }
After a while in web dev, I stopped using ! Operator and shifted to underscore to check whether something is empty or not I use _.isEmpty utility to keep my code predictable because the library I'm using takes care of so many edge cases.
False is different from null, so I guess your solution is not "universal". So I feel this video, despite being useful for some and you having explained there's different cases, doesn't reach its potential of explaining checking falsy stuffs. Thanks anyway, you do a great job!
The great prophet Douglas Crockford told us a long time ago not to use the bang operator and we didn't listen, and now we are paying for our sins. Thanks again for bring us back to the light.
I'm not sure how/when/why the ! operator became known as the "BANG" operator, but I've always called it the "negation" operator. Of course, my programming lineage is along the BASIC/assembly/C/C++/C# line, so maybe that's why. And maybe this is in JavaScript only. I know that Unix refers to "!" as BANG (because onomatopoeia, perhaps?), so I suspect someone with Unix experience started working in JavaScript and carried terminology over. Regardless, I'm sticking with "negation", as that describes what the operator does. And "BANG" tells me nothing about it.
The thing with the != null is that I think that wouldnt always work with undefined or NaN values, so you'd have to write 3 or more checks in your if statement
This video is absolute clickbait and it makes me mad. Making claims that "this stuff is bad... Do this don't do that", and particularly in this case, is so harmful... If you know JavaScript (or any programming language) well enough you can use the bang, or any other, operator, as you may need. Learn how things work, don't avoid stuff just because you don't understand them
This looks like: Hey! Don't buy shampoo if doesn't have printed instructutions in the package. Remember, read instructions each time to use it, for the rest of your life, is for your safety
One of the things that drove me crazy with learning JS was how something like a number could be 3 different types (or a value that is literally _not_ a number but is of type number, but I digress). Rather than constantly checking for null/undefined or NaN you could just give numbers a default value and correct the result of functions like parseInt to be a default value, like 0. The point is the same though, implicit typing can create unneeded risk. It can also get in the way of self-documentation because it's not clear if not allowing 0 is a bug or a requirement.
My perfectionistic OCD has apparently saved me from a problem I didn't even know about. I use explicit type exclusively just because I need things to be on the same page or I'm not happy xD ::edit:: I should say, I knew about type conversion for boolean comparisons, I just never liked it. Would rather do the conversion myself manually and then run my comparisons because then I know what's actually happening. Probably means I write more code than I need to sometimes but eh.
Using an inverter in the first if() statement is already wrong in my book. Save your brain some processing time. Don't start with inverted checks. X ) Then doing boolean checks on numbers is also wrong.
Yea, this is the first video I remember that I disagree with you! I like coercion for shorthands and I think it shows I know what I'm doing. Until it shows the opposite of course
@@mikeonthebox It's not about the appearance of the code, but about errors associated with it. Run this code to see what happens: const test = 12 ['c','d'].forEach((letter) => console.log(letter))
@@grzegorzt well obv that will throw an error but ask yourself how often do you write something like that, most people don't just write plain array without assigning it to a variable. also why use .forEach???
@@RedStone576 It's not about that particular code, it's just an example. I can give you dozens of such examples where there is an error when we do not use a semicolon.
what you said makes no sense. Someone needs to study a bit longer if they are confused by this kind of simplest type conversion. It is not too deep too unexpectable behaviour.