By Sebastian Pennino
By Sebastian Pennino
The following presentation may contain:
On November 5, 1955, Brendan Eich was hanging a clock while standing on his toilet. The porcelain on the toilet was wet and he slipped, hitting his head on the sink, when he woke up he wrote what he saw in a piece of paper...
On Sept 1995, Brendan was asked by Netscape Communications to design a versatile programming language that could speed up web development and serve as a scripting companion for Java. He did it in 10 days. The original purpose was:
Starting on the next slide we will be discussing individual cases. I will present an example and we will discuss the outcome
// Case 1
const a = [10, 10, 10, 10].map(parseInt)
// Case 2
const b = 0.1 + 0.2
// Sebas: press U for fun
a -> [10, NaN, 2, 3]
b -> 0.30000000000000004
...?
// Case 1
const a = [10, 10, 10, 10].map(parseInt); // -> [10, NaN, 2, 3]
ParseInt:
parseInt(string[, radix])
Array.prototype.map:
(callbackfn, thisArg?: any): any[]
The callbackfn:
(value: number, index: number, array: number[]) => any
IMO in this case there's no Javascript quirk perse. This might be a misusage (due to unfamiliarity) with the parseInt function and the map method
// Case 2
const b = 0.1 + 0.2; // -> 0.30000000000000004
When JS was designed it was decided that all numbers should have the same representation
So instead of having Integers, floats, signed, unsigned, etc we only got a 32-bit floating point representation for all numbers
There's a long explanation (here) that requires understanding binary but in a nutshell its a rounding error of the numeric representation, you can reproduce this error on any language that uses the 32-bit floating point representation
Converting a value from one type to another is often called "type casting," when done explicitly, and "coercion" when done implicitly (forced by the rules of how a value is used).
However, in JS, most people refer to all these types of conversions as coercion, so the way I prefer to distinguish is to say "implicit coercion" vs. "explicit coercion."
const a = 42;
const b = a + ""; // implicit coercion
const c = String( a ); // explicit coercion
const value1 = '6';
const value2 = 3;
let sum = value1 + value2;
console.log(sum); // what will log?
it will log: '63' // jelinek
In javascript, a truthy value is a value that is considered true when encountered in a Boolean context. Also, all values are truthy unless they are defined as falsy
Falsy values are: false, 0, -0, 0n, "", null, undefined, NaN
0 (zero) and one have a special place in javascript, if you often minify your code, you will find that any true and any false in the code will be transpiled to !0 and !1 respectively (to save 2 and 3 characters!). (Online minifier https://codebeautify.org/minify-js)
This simple character has different functions: precedes its operand and evaluates to its operand but attempts to convert it into a number, if it isn't already.
Otherwise produces the sum of numeric operands or string concatenation
+true // -> 1
+false // -> 0
+null // -> 0
// Number + Number -> addition
1 + 2 // -> 3
// Boolean + Number -> addition
true + 1 // -> 2
// Boolean + Boolean -> addition
false + false // -> 0
// String + String -> concatenation
'foo' + 'bar' // -> "foobar"
// Number + String -> concatenation
5 + 'foo' // -> "5foo"
// String + Boolean -> concatenation
'foo' + false // -> "foofalse"
All the different natives have a toString method that will be used implicitly by javascript
Note: there's also toNumber, and toBoolean, but we kinda cover those.
Now that we have some tools let's dive in
'true' == true // false
false == 'false' // false
'true' == true
==> NaN == 1
==> false
false == 'false'
==> 0 == NaN
==> false
== operator triggers numeric conversion,
string 'true' is converted to NaN,
boolean true is converted to 1.
("foo" + + "bar") === "fooNaN" // true
"b" + "a" + +"a" + "a"; // -> 'baNaNa'
"foo" + + "bar"
==> "foo" + (+"bar")
==> "foo" + NaN
==> "fooNaN"
Unary + operator has higher precedence over binary + operator.
So +'bar' expression evaluates first.
Unary plus triggers numeric conversion for string 'bar'.
Since the string does not represent a valid number, the result is NaN.
On the second step, expression 'foo' + NaN is evaluated.
[1, 2, 3] + [4, 5, 6]; // -> '1,2,34,5,6'
// The concatenation happens. Step-by-step, it looks like this:
[
// call toString()
(1, 2, 3)
].toString() +
[4, 5, 6].toString();
// concatenation
"1,2,3" + "4,5,6";
// ->
("1,2,34,5,6");
[] == ![]; // -> true
// Here is how this expression simplifies. Step-by-step:
+[] == +![];
0 == +false;
0 == 0;
true;