Stranger Things, JavaScript Edition
livecodestream.dev
livecodestream.dev
There is a relatively small list of "gotchas" in JavaScript that stem from the early days of the language. They are easily avoided. Use a linter, "use strict," use ===, and be explicit about your type conversions.
Not always. Don't forget about this, arrow functions and the fact that popular mocking frameworks can automatically mock regular class methods but not arrow methods.
I'm not saying these issues make the language unusable, but you've got to be a bit more honest that you were if you want to be taken seriously.
You were probably just trying to show off. But in case you weren't, here's how JS works.
In JavaScript, if you're passing in a function as a parameter, the normal way is to use an arrow function. Like this: `array.map((element) => yourFunction(element));`. This gives you explicit control over which parameters are passed in to your function and how.
As a shortcut, you can provide a function name rather than an arrow function. If you do so, you're saying that you want all parameters to be passed to that function. You're expected to know what those parameters are and how the function you're passing in will use them. If you don't know that, well, you're programming blind and bad things will sometimes happen. Maybe don't do that.
As with many things in JavaScript, it's better to be explicit than rely on the shortcut.
Edit: Just to be clear, here's the correct way to map an array of strings to an array of numbers in JavaScript: `array.map((s) => parseInt(s, 10));`
What exactly is the shortcut you mention? (wild your mind converting the example into the incorrect/dangerous version?)
I use map() all the time but I didn't know about that until I read this article. I wonder why map() functions this way in Javascript and if any other languages pass additional values like this in their own map() implementations.
I do think GP has a fair point of criticism - at least when I use map() I expect it to take each value in the array and pass it to the callback function. I don't expect it to take each value in the array, the index of that value and the entire array and pass all of that to the callback function instead.
Sometimes it's very convenient to be able to look ahead or behind the current element being map()'d to make decisions.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
Then you don't know the basics of the language you're using- how can you complain about it?
> when I use map() I expect it to take each value in the array and pass it to the callback function. I don't expect...
map is well documented. Making the element's index available is indeed pretty useful (the entire array less so, but sometimes it can be).
As an example of one of the many ways to solve this to make it more sane, the Rust language allows you to call .iter() on something that can be looped over, but also .enum(), which gives you an index and the item. In this way, you can manage expectations about what you are actually getting. Javascript hands you all the tools at once unconditionally which strips a lot of the abstracting power away.
['1', '7', '11'].map(Number)
And if I explicitly need integers I can always filter the result ['1', '7', '11'].map(Number).filter(Number.isInteger)
It also doesn't silently parse '123thisisnotanumber' or `0x11`More specifically, the first one was quite interesting and subtle enough that if I didn't have the `parseInt(N, 10)` rule ingrained in my head, if I had to parse a list of numbers I would try that and then scratch my head for like 30 minutes being very confused. It's also subtle enough that I could see it possibly going to production, because it could be missed if the code is only lightly tested and could be missed in a code review too.
The other one that intrigued me was the second one, and I had to look up why it works -- I didn't realize that using the + operator turns any non-parseable value into NaN.
Thanks for the cool article!
Understand the difference between primitive values and object values. There are few historical bugs here with typeof that are now defined in the spec (null, undefined etc are primitive values but will give object etc).
Floating point math:
https://en.m.wikipedia.org/wiki/Floating-point_arithmetic
Type coercion:
https://exploringjs.com/deep-js/ch_type-coercion.html
Prototypical inheritance:
https://javascript.info/prototype-inheritance
How this works:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
And you will be fine for the most part. Other things you will discover on your own.
And use typescript if you can.
No, they are an embarrassment.
They don't make the language cool or interesting, they aren't tricks. They are logically incoherent nonsense.
In some cases, the parseInt rules go sideways when your number string starts with a 0 (zero). That's going to be a rare occurrence that happens months after you write this code, works just fine on your machine, and is going to take days to find.
Per MDN [1]:
If radix is undefined, 0, or unspecified, JavaScript assumes the following:
1. If the input string begins with "0x" or "0X" (a zero, followed by lowercase or uppercase X), radix is assumed to be 16 and the rest of the string is parsed as a hexidecimal number.
2. If the input string begins with "0" (a zero), radix is assumed to be 8 (octal) or 10 (decimal). Exactly which radix is chosen is implementation-dependent. ECMAScript 5 clarifies that 10 (decimal) should be used, but not all browsers support this yet. For this reason, always specify a radix when using parseInt.
3. If the input string begins with any other value, the radix is 10 (decimal).
1: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
Any engineer that allows any of the code like this in their codebase has only themselves to blame.
Later formal standards created the “use strict” feature which alleviates a lot of problems.
'9' + 1
= "91"
+'9' + 1
= 10
It's all very weird though... >> +"2"
=> "2"
>> "2" + 1
TypeError (no implicit conversion of Integer into String)
python >>> +"2"
TypeError: bad operand type for unary +: 'str'
>>> "2" + 1
TypeError: can only concatenate str (not "int") to str
lua > +"2"
stdin:1: unexpected symbol near '+'
> "2" + 1
3.0 2 + 2 == 4
2 . 2 eq 22
You can even declare that failed conversions should throw: use warnings FATAL => qw(numeric)perl
print "2" + 1
3
print "2" - 1
1
js > "2" + 1
"21"
> "2" - 1
1 072 === 058 // returns true
Thankfully, doesn't work in strict mode.However, 058 should have been a parse error.
For what you would expect the output to be:
[1, 7, 11]
However, things get a bit off here, and the actual result is:
[1,NaN,3]
At first, this may look up very weird, but it actually has an elegant explanation. "
The elegant explanation is that JavaScript was taken over by psychopaths like bajcmartinez.
JavaScript is fine for button onClick code. Outside of that it's garbage.