The threshold example is way too... atomic. I would use +(0.1+0.2).toPrecision(digits after decimal point). It will make a string rounded down to the chosen decimal digit and convert back to number. There is also another similar method that takes amount of all digits, including the whole numbers, and I always conflate the two.
That's just masking the problem - rounding like that should be left for presentation purposes - there's a reason `.toPrecision()` returns a string. See e.g. (+(0.1+0.2).toPrecision(10)).toPrecision(18) which shows that your number is *still* not really equal to 0.3
VSCode with deno as linter has everything you just showed. Saying this for many people who already use VSCode. You can write jsdoc and it will be rendered, you can press shift f12 to see all references, and of course you can quick fix.
I would love for JavaScript to gain more options for strict mode, with JavaScript runtimes, it’s now possible to redefine many of the language features and not worry about browser compatibility. It is already possible to use TypeScript on them and they will serve the JavaScript equivalent code to the browsers, so even that isn’t an issue. On of the features I would suggest is disabling type coercion and making the “typeof” operator return more appropriate types, since these two deal with types, I normally group them together but they could be separate options. Another would be introducing errors as values and not allowing try/catch, of which has the ability to be used in a catch all capacity and is frequently abused, where having to deal with the value at the time of error would greatly reduce this risk. These are just the ones I could think of off the top of my head and would love to hear if anyone else would like to see more options for strict mode and what they would be.
The for/in problem is worse for those who use Python and JavaScript in a project, like when you are on a web app that is served by Python. Those developers have to constantly make the mental switch between languages and ensure that for/of is used in JavaScript, but the opposite will give an error as Python doesn’t have the “of” keyword.
”foreach in” in C# is the same as ”for of” in JavaScript. So I use foreach in for of for in interchangebly every day 😅 ”for in” is probably confusing for new JS developers. Just use array.keys()
The weird thing here if you read the code "of" should be for class Like for (key of ) it much easier to read And vice versa for (item in ) much easier to read But well here we are. I guess just use some kind of hint technique.
I had no need to check if the object is not an array, but I think the check can be written in shorter form maybe using val?.constructor?.name. This should avoid inheritance hurdles and show you the latest constructor that created the thing, it should be "Object" for a straight fresh object, not a class or an array.
I just this week arrived at the same conclusion as you about option chaining. But i use a jsr:@std/assert function instead of the if. And i finally arrived at a consistent pattern for when values can be 'whatever-type' | undefined. Somehow this all fell out of my new work with deno.
The decimal adding solution is weird. Are you saying we need to do Math.abs(num - something) < n? (Then you have to know if you need to use episilon or not) For every condition? That is a weird solution.
Well you don’t need to use epsilon ever if you don’t want to, but otherwise yes. If you don’t want occasional bugs, you should never use direct equality on decimals in JavaScript (or most languages for that matter).
@ConnerArdman that's weird and sad to know. Because decimal is used so much. You said don't use direct equality. So it means there's another options there.
@@asagiai4965 no, there is no other way. Simply never use equality operator on floating point numbers. Regardless of a programming language. The shown solution is the only way. You can make a shorthand wrapper function for it, e.g. 'function comp(a, b) { return Math.abs(a - b) < N; }', where N is some constant precision value.
Can someone tell me if this solution works const sumOfFloat = 0.1 + 0.2 //Because I believe this works. if(Math.abs(sumOfFloat - sumOfFloat) < Number.EPSILON) { console.log("Equals") } //Or what about if (Math.floor(sumOfFloat * 10) - Math.floor(sumOfFloat * 10) < Number.EPSILON) { console.log("Equals") } //Or what about comparing it to the lowest floating point possible (that is not 0) Math.abs(sumOfFloat - 0.3) < Lowest_Floating_Point //Or What about the ability to drop insignificant digit Also what I find funny is not all floating point numbers and not all operations follows this bug. 0.2 + 0.2 = 0.4 ? this is correct 0.1 - 0.2 = -0.1 ? this is correct 0.2 - 0.1 = 0.1 ? And yet these are the same numbers with just different operations. Even 0.01 + 0.02 = 0.03 gives the correct answer
In the null vs. object example, you use `x !== null`, which doesn't catch undefined. Null and undefined are often used interchangeably, which is IMO best practice in most cases, so `x != null` should be used in general.
In general I'd agree, and it is fine here but unnecessary. You can see I do == null in the last example, and I do the same in 99% of my videos. The reason for using strict equality in the object case though is that the edge case is actually specifically with null, so there's no reason to check for undefined (typeof undefined is "undefined" not "object").
@@danser_theplayer01 This is not true. Checking == null and == undefined are the exact same thing, as both are only true for an exact match or the other value. It has nothing to do with truthy/falsy values. From the MDN docs on ==: "If one of the operands is null or undefined, the other must also be null or undefined to return true. Otherwise return false." developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality It is a widely accepted industry practice to use == null. For example, here is the Google style guide saying exactly this: google.github.io/styleguide/jsguide.html#features-equality-checks-exceptions
Can you reveal some advanced js code for front end, i just checked bootstrap source code for components like navbar and accordion,i felt sooo overwhelmed, its just another level
I'm working on a codebase with optional chaining just goes infinity like a?.b?.c?.d?.e?.f and it looks really bad. It does not fix the root problem at all (why do we have to optional chaining at the first place). I agree with you that we should handle properties being undefined in the first place by throwing an error (or if you don't want, create some default value if possible) because we need that property anyway
You can, although you would probably still need the optional chaining as well. So this could throw before getting to the ?? If config or api are nullish return config.api.key ?? “Missing key” Instead you would need to do this to get roughly equivalent behavior return config?.api?.key ?? “Missing key” That said, I don’t really like this solution. The reason being we are returning a string regardless. This means the calling function now needs to check if our function returned an actual api key or if it returned this error string. In most cases, not having a key is an error and should be treated as such imo.
@@Jonulf87 that's exactly why I don't like typescript and will never use it. You think you're good because the object is """frozen""", when at runtime anything can happen. It's something so trivial as well, all typescript compiler bros have to do it just write it so "as const" recursively freezes an object ONCE at runtime. The javascript engine already handles everything that happens after, it's not like I'm asking for something expensive like validating all types at runtime.
Start of video, in/of, instantly you can see how stupid JS as language is. IN is as in(side)of array. Python is slow i know, but it is so much more friendly.
I’m glad you used terms like “people” and “advanced developers” since they cover an incredibly broad array of individuals. Baffles me how lazy one has to be to make these mistakes.
Literally never use array methods and instead use a simple "for" loop. A regular for loop is much more flexible, always very readable, and the fastest execution wise. "for in" loops are useful for recursion, and "for of" loops are useful for custom iterable and async iterable implementations. As a simple example: I can make all numbers (or numbers created by an extension class) iterable, so that I can write "for (const i of 8) { console.log(i) }" to get 0,1,2,3,4,5,6,7,8 with typeof number.
Yh thus true but that only happens when you want to change the variable completely to another variable. For instance, const obj={name:"Paul",age:12} If you try obj={} or obj=anything else you are going to get an error that you cannot reassign a constant. But with an object, the js engine doesnt care if it was declared a constant or not when you try to mutate it(thus doing obj.property=newValue) because with that you are changing the object not the variable . Hope this helps
For primitives, freezing is irrelevant because strings, numbers, and booleans are immutable by default. Const works as you expect - you cannot alter the value (or more precisely, reassignment) of a const. However, for custom objects, const prevents reassignment (e.g., x = new Object()), but it doesn't stop the object's properties (e.g., x.y = 9) from being modified. This is where Object.freeze() comes in, making every attribute read-only.
That is because the value of something like "const obj = { x:5, y:20 }" is not the object itself, but rather the reference to that object that has been created somewhere in the computer's memory. So, whenever you say something like "obj.x", what the interpreter sees is "go to the memory address stored in 'obj' and look for a field named 'x'". This also means that saying something like "const obj2 = obj" doesn't create any new objects - it simply assigns the address of an already created object to a new name. Now, the "const" constraint forbids the alteration of the name's _value,_ that is to say, you won't be able to say something like "obj = 5" or "obj = { foo: 'bar' }". However, "const" knows nothing about the data structure that is referenced by its name. Which means that doing "obj.x = 99" is perfectly valid, won't throw any errors and will modify the x field of the object. This is why you need freezing. What freezing will do is ensure that none of the fields of the created object are able to be modified.
@@jojohehe3251 you're basically naming a pointer as const. If you were to have a let obj variable then it would be possible to reassign obj to be something else entirely.
@@EdwinMartin The joke was that "this" in JS and the DOM in general is so volatile/unpredictable, that if you dont have the hours to spend to learn how it works, youre better off just not using it.
@@EdwinMartinin modern TS you can simply forgot about "this". Who's using classes or similar? The only time I had to use it in the last years was for a validation with yup, but that's yup fault 😂
The threshold example is way too... atomic.
I would use +(0.1+0.2).toPrecision(digits after decimal point). It will make a string rounded down to the chosen decimal digit and convert back to number. There is also another similar method that takes amount of all digits, including the whole numbers, and I always conflate the two.
That's just masking the problem - rounding like that should be left for presentation purposes - there's a reason `.toPrecision()` returns a string.
See e.g. (+(0.1+0.2).toPrecision(10)).toPrecision(18) which shows that your number is *still* not really equal to 0.3
@@RayBellis Of course it won't be equal, you "overflowed" precision. Usually only the first 14-15 digits are reliable.
The way I remember the difference between for in and for of loop is, "in" stands for index in my mental model
VSCode with deno as linter has everything you just showed. Saying this for many people who already use VSCode.
You can write jsdoc and it will be rendered, you can press shift f12 to see all references, and of course you can quick fix.
Agreed. Deno has upped my quality of code.
I would love for JavaScript to gain more options for strict mode, with JavaScript runtimes, it’s now possible to redefine many of the language features and not worry about browser compatibility. It is already possible to use TypeScript on them and they will serve the JavaScript equivalent code to the browsers, so even that isn’t an issue.
On of the features I would suggest is disabling type coercion and making the “typeof” operator return more appropriate types, since these two deal with types, I normally group them together but they could be separate options. Another would be introducing errors as values and not allowing try/catch, of which has the ability to be used in a catch all capacity and is frequently abused, where having to deal with the value at the time of error would greatly reduce this risk.
These are just the ones I could think of off the top of my head and would love to hear if anyone else would like to see more options for strict mode and what they would be.
The for/in problem is worse for those who use Python and JavaScript in a project, like when you are on a web app that is served by Python. Those developers have to constantly make the mental switch between languages and ensure that for/of is used in JavaScript, but the opposite will give an error as Python doesn’t have the “of” keyword.
For in/of seems like a footgun.
😂 yeah…
”foreach in” in C# is the same as ”for of” in JavaScript. So I use
foreach in
for of
for in
interchangebly every day 😅
”for in” is probably confusing for new JS developers. Just use array.keys()
The weird thing here if you read the code "of" should be for class
Like
for (key of ) it much easier to read
And vice versa
for (item in ) much easier to read
But well here we are. I guess just use some kind of hint technique.
The entire language is a footgun.
I had no need to check if the object is not an array, but I think the check can be written in shorter form maybe using val?.constructor?.name. This should avoid inheritance hurdles and show you the latest constructor that created the thing, it should be "Object" for a straight fresh object, not a class or an array.
Congrats on 100k subs 🤜🤛
Thank you!
I just this week arrived at the same conclusion as you about option chaining. But i use a jsr:@std/assert function instead of the if. And i finally arrived at a consistent pattern for when values can be 'whatever-type' | undefined. Somehow this all fell out of my new work with deno.
Thanks for tut, looking for more series like this
Very handy. Thanks Conner!
Could also use a try/catch block to handle the error instead of optional chaining
The decimal adding solution is weird.
Are you saying we need to do Math.abs(num - something) < n? (Then you have to know if you need to use episilon or not)
For every condition? That is a weird solution.
Well you don’t need to use epsilon ever if you don’t want to, but otherwise yes. If you don’t want occasional bugs, you should never use direct equality on decimals in JavaScript (or most languages for that matter).
@ConnerArdman that's weird and sad to know. Because decimal is used so much.
You said don't use direct equality. So it means there's another options there.
@@asagiai4965 no, there is no other way. Simply never use equality operator on floating point numbers. Regardless of a programming language.
The shown solution is the only way. You can make a shorthand wrapper function for it, e.g. 'function comp(a, b) { return Math.abs(a - b) < N; }', where N is some constant precision value.
@@mk72v2oq I kind of beg to differ.
Can someone tell me if this solution works
const sumOfFloat = 0.1 + 0.2
//Because I believe this works.
if(Math.abs(sumOfFloat - sumOfFloat) < Number.EPSILON)
{
console.log("Equals")
}
//Or what about
if (Math.floor(sumOfFloat * 10) - Math.floor(sumOfFloat * 10) < Number.EPSILON)
{
console.log("Equals")
}
//Or what about comparing it to the lowest floating point possible (that is not 0)
Math.abs(sumOfFloat - 0.3) < Lowest_Floating_Point
//Or What about the ability to drop insignificant digit
Also what I find funny is not all floating point numbers and not all operations follows this bug.
0.2 + 0.2 = 0.4 ? this is correct
0.1 - 0.2 = -0.1 ? this is correct
0.2 - 0.1 = 0.1 ? And yet these are the same numbers with just different operations.
Even 0.01 + 0.02 = 0.03 gives the correct answer
Nice deep dive, keep these videos coming.
Thankyou, I learn a lot from this video
In the null vs. object example, you use `x !== null`, which doesn't catch undefined. Null and undefined are often used interchangeably, which is IMO best practice in most cases, so `x != null` should be used in general.
In general I'd agree, and it is fine here but unnecessary. You can see I do == null in the last example, and I do the same in 99% of my videos. The reason for using strict equality in the object case though is that the edge case is actually specifically with null, so there's no reason to check for undefined (typeof undefined is "undefined" not "object").
wrong, x == null will trigger on any falsey value. For null/undefined specifically use x == undefined. Common mistake.
@@ConnerArdman don't do x == null, it can triger on empty string and 0, use x == undefined which is nullish.
@@danser_theplayer01 This is not true. Checking == null and == undefined are the exact same thing, as both are only true for an exact match or the other value. It has nothing to do with truthy/falsy values.
From the MDN docs on ==:
"If one of the operands is null or undefined, the other must also be null or undefined to return true. Otherwise return false."
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Equality
It is a widely accepted industry practice to use == null. For example, here is the Google style guide saying exactly this:
google.github.io/styleguide/jsguide.html#features-equality-checks-exceptions
great and helpful, thanks
Can you reveal some advanced js code for front end, i just checked bootstrap source code for components like navbar and accordion,i felt sooo overwhelmed, its just another level
Congrats on getting to 100K 🎉👍
Thank you!
I'm working on a codebase with optional chaining just goes infinity like a?.b?.c?.d?.e?.f and it looks really bad. It does not fix the root problem at all (why do we have to optional chaining at the first place). I agree with you that we should handle properties being undefined in the first place by throwing an error (or if you don't want, create some default value if possible) because we need that property anyway
13:18 why not use Nullish coalescing operator (??) here.
Exactly : return config.api.key ?? 'Missing API Key'
You can, although you would probably still need the optional chaining as well.
So this could throw before getting to the ?? If config or api are nullish
return config.api.key ?? “Missing key”
Instead you would need to do this to get roughly equivalent behavior
return config?.api?.key ?? “Missing key”
That said, I don’t really like this solution. The reason being we are returning a string regardless. This means the calling function now needs to check if our function returned an actual api key or if it returned this error string. In most cases, not having a key is an error and should be treated as such imo.
@@ataru-music Because returning 'Missing API Key' as a string and throwing an error are not the same
@@ConnerArdmanYou could do something like this
return config?.api?.key ?? (() => {throw new Error("Missing key")})();
what is that ide?
webstorm
the biggest error you can make is not using typescript. until you use plain js you won't learn anything.
Object.freeze only works on the first layer. Ideally in a real big project you'd use a helper function to recursively freeze all objects and arrays.
You can use as Const. That will make nested objects also read-only, but only during compile time, not run-time
@@Jonulf87 that's exactly why I don't like typescript and will never use it. You think you're good because the object is """frozen""", when at runtime anything can happen.
It's something so trivial as well, all typescript compiler bros have to do it just write it so "as const" recursively freezes an object ONCE at runtime. The javascript engine already handles everything that happens after, it's not like I'm asking for something expensive like validating all types at runtime.
Start of video, in/of, instantly you can see how stupid JS as language is. IN is as in(side)of array. Python is slow i know, but it is so much more friendly.
It's funny how the year I stopped renewing my WebStorm license it became free...
are you using some kind of copilot?
No, just all the Webstorm default functionality
Date is also an "object" type
Pls don't do math with floating point numbers. Store all in integer or bigInt
It's certainly a mistake to assume all mutability is a mistake. :)
More zoom man !!!!
First most common mistake javascript developers do is javascript instead of typescript
I’m glad you used terms like “people” and “advanced developers” since they cover an incredibly broad array of individuals. Baffles me how lazy one has to be to make these mistakes.
Running a jetbrains IDE is a senior move
Facts 😎
Literally never use array methods and instead use a simple "for" loop. A regular for loop is much more flexible, always very readable, and the fastest execution wise.
"for in" loops are useful for recursion, and "for of" loops are useful for custom iterable and async iterable implementations. As a simple example: I can make all numbers (or numbers created by an extension class) iterable, so that I can write "for (const i of 8) { console.log(i) }" to get 0,1,2,3,4,5,6,7,8 with typeof number.
Why is freezing a thing if the object has been declared a const? I thought you already couldn't alter the value of a const?
Yh thus true but that only happens when you want to change the variable completely to another variable. For instance,
const obj={name:"Paul",age:12}
If you try obj={} or obj=anything else you are going to get an error that you cannot reassign a constant. But with an object, the js engine doesnt care if it was declared a constant or not when you try to mutate it(thus doing obj.property=newValue) because with that you are changing the object not the variable . Hope this helps
For primitives, freezing is irrelevant because strings, numbers, and booleans are immutable by default. Const works as you expect - you cannot alter the value (or more precisely, reassignment) of a const.
However, for custom objects, const prevents reassignment (e.g., x = new Object()), but it doesn't stop the object's properties (e.g., x.y = 9) from being modified. This is where Object.freeze() comes in, making every attribute read-only.
That is because the value of something like "const obj = { x:5, y:20 }" is not the object itself, but rather the reference to that object that has been created somewhere in the computer's memory.
So, whenever you say something like "obj.x", what the interpreter sees is "go to the memory address stored in 'obj' and look for a field named 'x'".
This also means that saying something like "const obj2 = obj" doesn't create any new objects - it simply assigns the address of an already created object to a new name.
Now, the "const" constraint forbids the alteration of the name's _value,_ that is to say, you won't be able to say something like "obj = 5" or "obj = { foo: 'bar' }".
However, "const" knows nothing about the data structure that is referenced by its name. Which means that doing "obj.x = 99" is perfectly valid, won't throw any errors and will modify the x field of the object.
This is why you need freezing. What freezing will do is ensure that none of the fields of the created object are able to be modified.
@@jojohehe3251 you're basically naming a pointer as const. If you were to have a let obj variable then it would be possible to reassign obj to be something else entirely.
You can cast the const to an object and still change it. With const you can never change it 😉
First
The title should be Please STOP USING JAVASCRIPT
use ts
Key takeaway: Dont use "this" ever when in JS/TS
‘This’ is very useful. You just have to know how it works.
@@EdwinMartin The joke was that "this" in JS and the DOM in general is so volatile/unpredictable, that if you dont have the hours to spend to learn how it works, youre better off just not using it.
@@EdwinMartinin modern TS you can simply forgot about "this". Who's using classes or similar? The only time I had to use it in the last years was for a validation with yup, but that's yup fault 😂
Js is not good Python The God of Programming