# Session 6: Quirky Topics [slide online](https://hackmd.io/@e8KGkGmbTPWKGH_D_dy9DA/Bk0U-ppDo) --- ## Type casting ### Numbers > `+` operator ```javascript const initial = "1.2"; const converted = +initial; console.log(typeof initial); // String console.log(typeof converted); // Number console.log(converted); // 1.2 ``` --- ## Type casting ### Numbers > `+` operator ```javascript const nanInitial = "1.2whatever"; const converted = +nanInitial; console.log(typeof converted); // Number console.log(converted); // NaN ``` --- ## Type casting ### Numbers > `Number()` ```javascript const initial = "1.2"; const converted = Number(initial); console.log(typeof initial); // String console.log(typeof converted); // Number console.log(converted); // 1.2 ``` --- ## Type casting ### Numbers > `Number()` ```javascript const nanInitial = "1.2whatever"; const converted = Number(initial); console.log(typeof converted); // Number console.log(converted); // NaN ``` --- ## Type casting ### Numbers > `parseFloat()` ```javascript const initial = "1.2"; const converted = Number(initial); console.log(typeof converted); // Number console.log(converted); // 1.2 ``` --- ## Type casting ### Numbers > `parseFloat()` ```javascript const initial = "1.2whatever"; const converted = Number(initial); console.log(typeof converted); // Number console.log(converted); // 1.2 ``` --- ## Type casting ### Numbers > `parseInt()` - `parseInt(<castedString>[, <radix>])` - Casts to `number` _**and**_ only returns the integer part - `<radix>` - It does **NOT** always default to `10` - $ r \in \mathbb{Z} : r \in [2, 32] $ --- ## Type casting > Numbers ### `parseInt()` > Default radix | Value | Default radix | | ----------------- | ------------- | | `"^[+-]?0[xX].+"` | 16 | | Any other string | 10 | --- ## Type casting ### Numbers > Unexpected conversions | Original value | Converted to number | | -------------- | ------------------- | | `""` | `0` | | `[]` | `0` | | `[<number>]` | `<number>` | | `null` | `0` | --- ## Type casting ### String > Template literals ```javascript const original = 1.23; const converted = `${original}`; console.log(typeof original); // "number" console.log(typeof converted); // "string" ``` --- ## Type casting ### String > `String()` ```javascript const original = 1.23; const converted = String(original); console.log(typeof original); // "number" console.log(typeof converted); // "string" ``` --- ## Type casting ### String > `toString()` | Original value | Converted to String | | -------------- | --------------------------- | | `1.1` | `"1.1"` | | `true` | `"true"` | | `[1, "str"]` | `"1,str"` (`arr.join(",")`) | | Object | `[object Object]` | | Function | Function body | --- ## Type casting ### Boolean > Double negation ```javascript const original = "something"; const converted = !!original; console.log(typeof original); // "string" console.log(typeof converted); // "boolean" ``` --- ## Type casting ### Boolean > `Boolean()` ```javascript const original = "something"; const converted = Boolean(original); console.log(typeof original); // "string" console.log(typeof converted); // "boolean" ``` --- ## Type casting ### Boolean > Unexpected conversions | Original value | Converted to boolean | | -------------- | -------------------- | | `"0"` | `true` | | `"00"` | `true` | | `""` | `false` | --- ## Strict vs coersive equality ```javascript console.log("12.3" === 12.3); // false console.log("12.3" == 12.3); // true console.log("12.3" !== 12.3); // true console.log("12.3" != 12.3); // false ``` --- ## Deep comparison ### Arrays ```javascript const arr1 = [1, 2, 3]; const arr2 = [1, 2, 3]; console.log(arr1 === arr2); // false ``` --- ## Deep comparison ### Object ```javascript const obj1 = { a: 1 }; const obj2 = { a: 1 }; console.log(obj1 === obj2); // false ``` --- ## Deep comparison ### Other objects (Set, Date, etc.) - Keep in mind that most of the utility types behave like objects - Some utility types offer a unique representation using some instance method, e.g.: `<date>.getTime()` --- ## Closures - A function + its surrounding lexical environment - An inner function with access to the outer function scope even after the outer function was executed --- ## Scopes ```mermaid flowchart TB 0(JS Scopes)--->1(Global) 2(Function) 3(Block*) 0--->2 0--->3 ``` _(\*) Introduced in ES6 (2015)_ --- ## Scopes ### Using `var` and assignment without declaration ```javascript { var global1 = "something 1"; global2 = "something 2"; let blockScoped = "something 3"; } console.log(global1); // "something 1" console.log(global2); // "something 2" console.log(blockScoped); // ReferenceError ``` --- ## Scopes ### Block scope > Typical scenario ```javascript for (let i = 0; i < 10; i++) { console.log(i); // i } console.log(window.i); // undefined console.log(i); // ReferenceError ``` --- ## Scopes ### Block scope > Typical scenario ```javascript for (var i = 0; i < 10; i++) { console.log(i); // i } console.log(window.i); // 10 console.log(i); // 10 ``` --- ## IIFEs ```javascript (function () { var someVar = 1; console.log(window.someVar); })(); ``` --- ## Hoisting - Variable _declarations_ are hoisted - Variable _initializations_ are _NOT_ hoisted - `let` and `const` will throw an error if you try to use the variable before the declaration - `var` won't throw but the value may be `undefined` --- ## Hoisting - Functions are hoisted - Classes are *NOT* hoisted (even though they're technically functions too) --- ## Method chaining ### Depending on the type ```javascript const arr = [1, 2, "hi", 3, "John"]; arr .filter((item) => typeof item === "string") .join(" ") .replace(/^./, (c) => c.toUpperCase()); ``` --- ## Method chaining ### Using `this` ```javascript class MyClass { constructor(str) { this.str = str; } append1() { this.str = `${this.str}1`; return this; } append2() { this.str = `${this.str}1`; return this; } } ``` --- ## Method chaining ### Using `this` ```javascript const instance = new MyClass("0"); console.log(instance.str); // "0" instance.method1().method2(); console.log(instance.str); // "012" ``` --- ## Prototypal inheritance - Objects have a special hidden property called _prototype_ - If JavaScript can't find a property in the object, it will try to find it in its prototype --- ## Prototypal inheritance ```javascript function Animal(name) { this.name = name; } Animal.prototype.breathe = function () { console.log("breathing..."); }; ``` --- ## Prototypal inheritance ```javascript function Dog(name) { Animal.call(this, name); } Object.setPrototypeOf(Dog.prototype, Animal.prototype); // Alternative: // Dog.prototype = Animal.prototype; ``` --- ## Prototypal inheritance ```javascript const d = new Dog("Courage"); d.breathe(); console.log(d.name); ``` --- ## Strict mode - Declared using `"use strict";` - Can be only declared: - At the beginning of the global scope - At the beginning of a function scope --- ## Strict mode ### Most important modifications - You must declare variables before using them - Functions aren't hoisted - More details - [Strict Mode on MDN](https://devdocs.io/javascript/strict_mode) - [JS Strict Mode on W3Schools](https://www.w3schools.com/js/js_strict.asp) --- ## Wrapping up - Topics covered - Quirky topics - Next session - Coming up... - Schedule ---
{"metaMigratedAt":"2023-06-17T16:15:46.875Z","metaMigratedFrom":"YAML","title":"Session 6: Quirky Topics","breaks":true,"contributors":"[{\"id\":\"7bc28690-699b-4cf5-8a18-7fc3fddcbd0c\",\"add\":7878,\"del\":0}]"}
    209 views