├── .babelrc ├── .editorconfig ├── .eslintrc ├── .gitignore ├── .markdownlint.json ├── .pnp.cjs ├── .pnp.loader.mjs ├── LICENSE ├── README.md ├── _config.yml ├── day_01.md ├── day_02.md ├── day_03.md ├── day_04.md ├── day_05.md ├── day_06.md ├── day_07.md ├── day_08.md ├── day_09.md ├── day_10.md ├── day_11.md ├── day_12.md ├── jest.config.json ├── package.json ├── practice_placeholder.js └── src ├── day_04 └── arrays.test.js ├── day_05 ├── branching.test.js ├── exceptionHandling.test.js ├── grouping.test.js ├── iterableAndIterators.test.js └── iteration.test.js ├── day_06 ├── closure.test.js ├── functions.test.js ├── hoisting.test.js └── scope.test.js ├── day_07 ├── arrowFunctions.test.js ├── generators.test.js └── this.test.js ├── day_08 └── classes.test.js └── day_09 ├── asyncAwait.test.js ├── callback.test.js ├── eventLoop.test.js └── promise.test.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "@babel/preset-env", 5 | { 6 | "targets": { 7 | "node": "current" 8 | } 9 | } 10 | ] 11 | ] 12 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | 2 | [*.js] 3 | indent_style = space 4 | indent_size = 4 5 | insert_final_newline = true 6 | 7 | [*.md] 8 | insert_final_newline = true -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "es6": true, 6 | "jest": true 7 | }, 8 | "parserOptions": { 9 | "ecmaVersion": 6, 10 | "sourceType": "module" 11 | }, 12 | "extends": ["@jaxolotl/eslint-config-wdc-es6"] 13 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .yarn 4 | package-lock.json 5 | yarn.lock 6 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD013": false, 3 | "MD026": false, 4 | "MD028": false, 5 | "MD033": false, 6 | "MD036": false 7 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Javier Valderrama (Jax) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A walk in JavaScript 2 | 3 | ## Preface 4 | 5 | A lot of information has been written about JavaScript and EcmaScript since both the language creation time and the standard definition time. 6 | The intention of this road map is to share with you one of many paths you can take to grok the language and specially to draw you to the highest quality information (which I won't be ever able to write in a better way) in the attempt to prevent you from coming across misleading (when not completely wrong) documents outside in the wild. 7 | 8 | Hopefully your walk will be much easier than mine! 9 | 10 | ## Table Of Contents 11 | 12 | 13 | ### [DAY 1](/day_01.md) 14 | - [Introduction to JavaScript](/day_01.md#introduction-to-javascript) 15 | - What is JS anyway? 16 | - [What's ECMAScript?](/day_01.md#but-what-is-ecma) 17 | - [Language features quick overview](/day_01.md#languages-features-quick-overview) 18 | - [Myths busted](/day_01.md#myths-busted) 19 | - [ES5 vs ES6](/day_01.md#es5-vs-es6) 20 | - Relevant differences 21 | - Relevant improvements 22 | - [Why are we using ES6 in this course?](/day_01.md#why-are-we-using-es6-in-this-course) 23 | - [After ES6?](/day_01.md#after-es6) 24 | - [Initial workspace Setup](/day_01.md#initial-workspace-setup) 25 | - Basic Runtime ( Node ) 26 | - IDE ( Visual Studio Code ) 27 | - [Run Code extension](/day_01.md#initial-workspace-setup) 28 | - Introduction to NPM 29 | *** 30 | ### [DAY 2](/day_02.md) 31 | - [Syntax, Grammar & Semantics](/day_02.md#syntax-grammar--semantics) 32 | - [Statements](/day_02.md#statements) 33 | - [Expressions](/day_02.md#expressions) 34 | - [Contextual Rules](/day_02.md#semantics) 35 | - [ECMAScript Types](/day_02.md#ecmascript-types) 36 | - [Value type groups](/day_02.md#value-type-groups) 37 | - Primitives 38 | - Boolean 39 | - Null 40 | - Undefined 41 | - Number 42 | - BigInt ( it's still a Stage 3 proposal but Chrome already support it and Firefox and Safari are underway. 43 | - String 44 | - Symbol( new in ES6! ) 45 | - [Composite/Compound](/day_02.md#compositecompound) 46 | - Object 47 | - [Type conversion](/day_02.md#type-conversion) 48 | - Explicit ( "type casting" ) 49 | - Implicit ( Coercion ) 50 | - [Operators](/day_02.md#operators) 51 | - Assignment operators 52 | - Comparison operators 53 | - Arithmetic operators 54 | - Bitwise operators 55 | - Logical operators 56 | - String operators 57 | - Conditional (ternary) operator 58 | - Comma operator 59 | - Unary operators 60 | - Relational operators 61 | - Destructuring 62 | - [Operators Precedence](/day_02.md#operators-precedence) 63 | - [Spread/Rest](/day_02.md#the-case-of-the---spreadrest-operator-) 64 | *** 65 | ### [DAY 3](/day_03.md) 66 | - Objects explained 67 | - Objects, the big picture 68 | - Syntax 69 | - Object properties attributes (accessors, descriptors) 70 | - Prototype 71 | - Behavior Delegation 72 | - Exotic Objects 73 | - Object built-in methods 74 | - Standard built-in objects 75 | *** 76 | ### [DAY 4](/day_04.md) 77 | - Indexed and Keyed Collections 78 | - Collections family 79 | - The Array Object 80 | - Syntax 81 | - Array Built-in methods 82 | - Preliminary practice 83 | - Exercises 84 | *** 85 | ### [DAY 5](/day_05.md) 86 | - Control Structures 87 | - General definition 88 | - Branching 89 | - Grouping 90 | - Exception handling 91 | - Iteration 92 | - Arbitrary Jumps 93 | - The Iterable and the Iterator Protocol 94 | - Preliminary Practice 95 | - Exercises 96 | *** 97 | ### [DAY 6](/day_06.md) 98 | - Functions 99 | - General Definition 100 | - Function declaration (function statement) 101 | - Function expression 102 | - Function constructor 103 | - Constructor vs declaration vs expression 104 | - Properties of the Function object in the prototype chain 105 | - Arity & formal parameters 106 | - Formal parameters and the `arguments` thing 107 | - Functions as properties of an object 108 | - IIFE 109 | - Pure functions 110 | - Side Effects 111 | - Execution context 112 | - Types of Execution Context (executable code) 113 | - Execution Stack 114 | - How Execution Context is defined? 115 | - Articles and books used for this section 116 | - Scope 117 | - Part of a program 118 | - ECMAScript definition 119 | - General definitions 120 | - Examples 121 | - Hoisting 122 | - Closure 123 | - General definition 124 | - Examples 125 | - Can we Cheat Scope? 126 | - ev[a|i]l 127 | - with 128 | - Relative Concepts Readings 129 | - Preliminary practice 130 | - Exercises 131 | *** 132 | ### [DAY 7](/day_07.md) 133 | - `this` Keyword 134 | - Introduction 135 | - Resolving `this` 136 | - Explicitly binding `this` through prototype methods 137 | - `Function.prototype.bind()` 138 | - `Function.prototype.apply()` 139 | - `Function.prototype.call()` 140 | - Strict mode 141 | - What happens on strict mode? 142 | - Semantic Differences 143 | - Arrow Functions 144 | - Generators 145 | - Exercises 146 | *** 147 | ### [DAY 8](/day_08.md) 148 | - Classes 149 | - General definition 150 | - Syntax 151 | - `class` declaration statement 152 | - `class` expression 153 | - Class body and method definitions 154 | - ES6 Classes in depth 155 | - OOP vs Functional 156 | - General definitions 157 | - Some essential differences 158 | - Examples 159 | - Exercises 160 | *** 161 | ### [DAY 9](/day_09.md) 162 | - Asynchronous programming 163 | - Event Loop 164 | - Callback 165 | - Promises 166 | - Async/Await 167 | - Exercises 168 | *** 169 | ### [DAY 10](/day_10.md) 170 | - JavaScript, where does it live? 171 | - The ECMAScript Engine 172 | - What does the engine actually do? 173 | - Visual guide based on V8 174 | - How many of them are there? 175 | - Engines Differences 176 | - The ECMAScript runtime 177 | - Runtimes Differences 178 | - Similarities 179 | - Javascript and the web 180 | - HTML 181 | - CSS 182 | - TL;DR 183 | - Complementary readings 184 | *** 185 | ### [DAY 11](/day_11.md) 186 | - Quality and reliability 187 | - An introduction to the "reliability" and "quality" concepts 188 | - Unit / Integration / Functional testing 189 | - Definitions 190 | - Comparison 191 | - TDD 192 | - Testing frameworks for JavaScript 193 | - Debugging 194 | - Debugging tools available for JavaScript 195 | - Global console object 196 | - Node.js console 197 | - debugger statement 198 | - node.js debugger 199 | - Browser's developer tools 200 | - IDE interaction with a browser to debug 201 | - Transpilers 202 | - Babel 203 | - Task runners, bundlers, build systems 204 | - Webpack 205 | - Grunt 206 | - Gulp 207 | - Brunch 208 | - Yeoman 209 | - RollUp 210 | *** 211 | ### [DAY 12](/day_12.md) 212 | - Destructuring 213 | - Syntax 214 | - Examples 215 | - Readings 216 | - Advanced Function/code factorization 217 | - Currying 218 | - Partial application 219 | - First-class composition 220 | - Readings 221 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /day_01.md: -------------------------------------------------------------------------------- 1 | # [A walk in JavaScript](/README.md) 2 | 3 | ## DAY 1 4 | 5 | - [A walk in JavaScript](#a-walk-in-javascript) 6 | - [DAY 1](#day-1) 7 | - [Introduction to JavaScript](#introduction-to-javascript) 8 | - [But what is ECMA?](#but-what-is-ecma) 9 | - [Languages features quick overview](#languages-features-quick-overview) 10 | - [Myths busted](#myths-busted) 11 | - [ES5 vs ES6](#es5-vs-es6) 12 | - [Why are we using ES6 in this course?](#why-are-we-using-es6-in-this-course) 13 | - [After ES6?](#after-es6) 14 | - [Initial workspace setup](#initial-workspace-setup) 15 | 16 | ## Introduction to JavaScript 17 | 18 | A great overview regarding ECMAScript and JavaScript. 19 | [Article by Michael Aranda](https://www.freecodecamp.org/news/whats-the-difference-between-javascript-and-ecmascript-cba48c73a2b5/) 20 | 21 | > JavaScript began as - and primarily still is - a language for scripting inside web browsers; however, the standardization of the language as ECMAScript has made it popular as a general-purpose language. In particular, the Mozilla implementation SpiderMonkey is embedded in several environments such as the Yahoo! Widget Engine. Other applications embedding ECMAScript implementations include the Adobe products Adobe Flash (ActionScript) and Adobe Acrobat (for scripting PDF files). [Scripting Language - Wikipedia](https://en.wikipedia.org/wiki/Scripting_language) 22 | 23 | ### But what is ECMA? 24 | 25 | Let's start with some facts 26 | 27 | - In 1995 [Brendan Eich](https://en.wikipedia.org/wiki/Brendan_Eich) was recruited by [Netscape](https://en.wikipedia.org/wiki/Netscape_Navigator) to embed [Scheme](https://en.wikipedia.org/wiki/Scheme_(programming_language)) programming language into netscape Navigator. Due to different company level decisions the original idea mutated, and it ends up with Brendan writing a new language prototype written in 10 days, 28 | - In 1996 Netscape submitted JavaScript to [ECMA Internacional](https://www.ecma-international.org/memento/index.html), an industry association dedicated to standardization of Information and Communication Technology (ICT) and Consumer Electronics (CE), the task of defining a Standard specification so that other vendors could implement the language as well. 29 | - In 1997 the first release of the ECMA-262 standard was published and JavaScript gradually became the most popular implementation. Other ECMAScript languages derived from that standard too, e.g [ActionScript](https://en.wikipedia.org/wiki/ActionScript) and [JSscript](https://en.wikipedia.org/wiki/JScript). 30 | 31 | > Source [Standardization](https://en.wikipedia.org/wiki/JavaScript#Standardization) on wikipedia 32 | 33 | ### Languages features quick overview 34 | 35 | - [Dynamic typed](https://en.wikipedia.org/wiki/Dynamic_typing) 36 | - Functions as [first-class citizens](https://en.wikipedia.org/wiki/First-class_citizen) 37 | 38 | - **Multi-paradigm language** 39 | - [Structured](https://en.wikipedia.org/wiki/Structured_programming) 40 | - [Imperative](https://en.wikipedia.org/wiki/Imperative_programming) in which the programmer instructs the machine how to change its state, 41 | - [Procedural](https://en.wikipedia.org/wiki/Procedural_programming) which groups instructions into procedures, 42 | - [Object-oriented](https://en.wikipedia.org/wiki/Object-oriented_programming) which groups instructions together with the part of the state they operate on, 43 | - [Prototype-based](https://en.wikipedia.org/wiki/Prototype-based_programming) 44 | - [Declarative](https://en.wikipedia.org/wiki/Declarative_programming) in which the programmer merely declares properties of the desired result, but not how to compute it ( e.g regex ) 45 | - [Functional](https://en.wikipedia.org/wiki/Functional_programming) in which the desired result is declared as the value of a series of function applications, 46 | 47 | - [Event-driven](https://en.wikipedia.org/wiki/Event-driven_programming) 48 | - [Client-side](https://en.wikipedia.org/wiki/Client-side) 49 | - Web Browsers 50 | - [Server-side](https://en.wikipedia.org/wiki/Server-side) 51 | - Node.js 52 | 53 | [See more](https://en.wikipedia.org/wiki/JavaScript#Features) 54 | 55 | ### Myths busted 56 | 57 | > **[MYTH]** JavaScript === Client-Side 58 | 59 | Well that's easy to prove ... lets say ... starting with Node.js 60 | 61 | > **[MYTH]** JavaScript === Front-End 62 | 63 | Humm, see above? and ... what's FE anyway? is it the visual aspect? the user interaction handling? the data process occurring when an API is consumed to store a denormalized version of the schema in a local database? 64 | 65 | > **[MYTH]** JavaScript === "interpreted" language. 66 | 67 | JavaScript is not an "interpreted" language anymore!!! or at least is not ONLY interpreted. Since V8 introduced [JIT compilation](https://en.wikipedia.org/wiki/Just-in-time_compilation) in 2008, all modern browsers started overhauling their engines to be able to compete. 68 | Several improvements were based on pre-compiling optimizations, including (but not only) the generation of an intermediate Bytecode and a post optimization to produce machine code. Also several optimization initiatives were disregarded along the way like V8's Full-codegen and [Crankshaft](https://blog.chromium.org/2010/12/new-crankshaft-for-v8.html). 69 | 70 | Here some interesting articles 71 | 72 | - [V8 Background compilation](https://v8.dev/blog/background-compilation) 73 | - [V8 Ignition + TurboFan](https://v8.dev/blog/launching-ignition-and-turbofan) 74 | - [Understanding V8's ByteCode](https://medium.com/dailyjs/understanding-v8s-bytecode-317d46c94775) 75 | - [SpiderMonkey ByteCodes](https://developer.mozilla.org.cach3.com/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/Bytecode#Bytecode_Listing) (the original url is no longer available so I replaced it with a cache version) 76 | - [The Baseline Interpreter: a faster JS interpreter in Firefox 70](https://hacks.mozilla.org/2019/08/the-baseline-interpreter-a-faster-js-interpreter-in-firefox-70/) 77 | 78 | ## ES5 vs ES6 79 | 80 | To be fair we should go back to the evolution of ES. 81 | 82 | > The JavaScript standard is referred to officially as "ECMAScript" (abbreviated "ES"), and up until just recently has been versioned entirely by ordinal number (i.e., "5" for "5th edition"). 83 | > 84 | > The earliest versions, ES1 and ES2, were not widely known or implemented. ES3 was the first widespread baseline for JavaScript, and constitutes the JavaScript standard for browsers like IE6-8 and older Android 2.x mobile browsers. For political reasons beyond what we'll cover here, the ill-fated ES4 never came about. 85 | > 86 | > In 2009, ES5 was officially finalized (later ES5.1 in 2011), and settled as the widespread standard for JS for the modern revolution and explosion of browsers, such as Firefox, Chrome, Opera, Safari, and many others. 87 | > 88 | > Leading up to the expected next version of JS (slipped from 2013 to 2014 and then 2015), the obvious and common label in discourse has been ES6. 89 | > 90 | > Extract from [YDKJS - ES6 & Beyond](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch1.md#versioning) by Kyle Simpson 91 | 92 | What is important to understand is that **until ES6** all versions were **ordinal versioned** and the release pace was **freaking slow** mostly because the browsers weren't decoupled from the OS and therefore any change should be integrated at OS releasing scale. 93 | 94 | Since ES6 - AKA ES2015, a year-based schema was introduced to reflect and support the fast development pace of JavaScript particularly impulsed by the decoupling of the Web Browsers from OS first but also due to the expansive adoption of the language and the growth of its use beyond "just swapping a button img on rollover" (A very interesting article about that was written by **Matthew MacDonald**, [read it here](https://medium.com/young-coder/how-javascript-grew-up-and-became-a-real-language-17a0b948b77f)). 95 | 96 | From ES2015 the standardization process started behaving as a **living standard** hence not tied to structured cuts but by an release based on continuous consensus and progressive adoption. 97 | In order to keep the pace, several improvements were required under the hood to keep it stable and scalable. Browsers will then adopt the new features based at their own pace, which left on the engineering side the responsibility for maintaining the backward compatibility, what led to an extensive growth of techniques such as [polyfilling](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch1.md#shimspolyfills) and [transpiling](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch1.md#transpiling) 98 | 99 | Tons of publications can be found online comparing both standards; you can read them online. I'd suggest to start with clean unbiased documents such as the [ecma-262 5.1](https://262.ecma-international.org/5.1/index.html) and [ecma-262 6.0](https://262.ecma-international.org/6.0/) ... but some find that too tedious :D ... you can check also this [ECMAScript 6 — New Features: Overview & Comparison](http://es6-features.org/) by Ralf S. Engelschall which I find very interesting, or jump into the excellent [You Don't Know JS book series](https://github.com/getify/You-Dont-Know-JS/) by Kyle Simpson, especially on the dedicated book [ES6 & Beyond](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/) by Kyle Simpson 100 | 101 | My summary is: 102 | 103 | - Several improvements made under the hood to support scalability 104 | - Several "syntactic sugar" added to improve the coding experience, some of the to avoid repetitive patterns and reducing human error vectors, some other to emulate coding styles from other languages, some of them really misleading ( like the use of "class" emulation when there's no "class" at all in JS World) 105 | - Several ( and continuously increasing ) new features to support the wide spread of the language usage. 106 | - Several new restrictions adopted as default when previously they were optional ( e.g. strict mode ) 107 | 108 | ### Why are we using ES6 in this course? 109 | 110 | Essentially because even though you will still work with legacy pre-ES6 code, hopefully you will grow as engineers on a post-ES6 world. Secondly because it's easier to understand and work with JavaScript as a general purpose language using ES6 rather than ES5 and most of the examples you'll find online will be presented that way. 111 | 112 | ### After ES6? 113 | 114 | Well, by the time being we're on the [ES2019 version](https://262.ecma-international.org/10.0/) ... though funny they still use a their URI with the ordinal version ( see the link ) instead of the year-based ... ¯\\_(ツ)_/¯ ... and the features included are following a 4-stages revision flow described on the [Technical Committee 39 (aka TC39) web site](https://tc39.es/process-document/) 115 | 116 | ## Initial workspace setup 117 | 118 | 1. [Install Node.js](https://nodejs.org/en/) 119 | 1. Alternatively you can Install Volta (https://volta.sh/) which is a great Node.js version manager 120 | 2. [Install VS Code](https://code.visualstudio.com/) 121 | 3. Add the following extensions to VS Code 122 | 1. [CodeRunner](https://marketplace.visualstudio.com/items?itemName=formulahendry.code-runner) 123 | 2. [EsLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) 124 | 4. [Introduction to NPM](https://docs.npmjs.com/about-npm/) 125 | 126 | *** 127 | [Go next to DAY 2](/day_02.md) 128 | *** 129 | [Back to main page](https://github.com/thinkb4/a-walk-in-javascript/tree/master#day-1) 130 | -------------------------------------------------------------------------------- /day_02.md: -------------------------------------------------------------------------------- 1 | # [A walk in JavaScript](/README.md) 2 | 3 | ## DAY 2 4 | 5 | - [Syntax, Grammar & Semantics](#syntax-grammar--semantics) 6 | - [Statements](#statements) 7 | - [Expressions](#expressions) 8 | - [Contextual Rules](#semantics) 9 | - [ECMAScript Types](#ecmascript-types) 10 | - [Value type groups](#value-type-groups) 11 | - [Primitives](https://en.wikipedia.org/wiki/Primitive_data_type) 12 | - [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type) 13 | - [Null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Null_type) 14 | - [Undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Undefined_type) 15 | - [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type) 16 | - [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#BigInt_type) 17 | - [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) 18 | - [Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Symbol_type) 19 | - [Composite/Compound](#compositecompound) 20 | - [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Objects) 21 | - [Type conversion](#type-conversion) 22 | - Explicit ( "type casting" ) 23 | - Implicit ( Coercion ) 24 | - [Operators](#operators) 25 | - [Assignment operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#assignment_operators) 26 | - [Comparison operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#comparison_operators) 27 | - [Arithmetic operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#arithmetic_operators) 28 | - [Bitwise operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#bitwise_operators) 29 | - [Logical operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#logical_operators) 30 | - [String operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#string_operators) 31 | - [Conditional (ternary) operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#conditional_ternary_operator) 32 | - [Comma operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#comma_operator) 33 | - [Unary operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#unary_operators) 34 | - [Relational operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#relational_operators) 35 | - [Destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) 36 | - [Operators Precedence](#operators-precedence) 37 | - [Spread/Rest](#the-case-of-the---spreadrest-operator-) 38 | 39 | ## Syntax, Grammar & Semantics 40 | 41 | As the communicational beings that we are, we all acquire some grade of expertise in one or more kinds of languages, which can be expressed through sounds, images, a combination of the first two and an expression of the first through the second, known as characters, that can communicate complete ideas ( e.g. ideograms, icons, emoji ) or sounds ( e.g alphabet ). In our effort to understand languages and the permutations that govern the meaning of that expression, at some point we start defining those rules so everyone can understand, learn and accurately reproduce the language. Programming languages are no exception. 42 | We're not going to dive deep into nuances and details since it'd require long years of study, but we can briefly take a look at the surface to have a better understanding of what's coming next. 43 | 44 | > In computer science, the syntax of a computer language is the set of rules that defines the combinations of symbols that are considered to be a correctly structured document or fragment in that language. This applies both to programming languages, where the document represents source code, and to markup languages, where the document represents data. 45 | > 46 | > **The syntax of a language defines its surface form.** Text-based computer languages are based on sequences of characters, while visual programming languages are based on the spatial layout and connections between symbols (which may be textual or graphical). Documents that are syntactically invalid are said to have a syntax error. 47 | > 48 | > Syntax therefore refers to the form, and it is contrasted with [semantics](https://en.wikipedia.org/wiki/Semantics_(computer_science)) – the meaning. In processing computer languages, semantic processing generally comes after syntactic processing; however, in some cases, semantic processing is necessary for complete syntactic analysis, and these are done together or concurrently. 49 | > 50 | > Computer language syntax is generally distinguished into three levels: 51 | > 52 | > - **Words** – the **lexical level**, determining how **characters** form **tokens**; 53 | > - **Phrases** – the **grammar level**, narrowly speaking, determining how **tokens** form **phrases**; 54 | > - **Context** – determining what objects or variables names refer to, if types are valid, etc. 55 | > 56 | > Distinguishing in this way yields modularity, allowing each level to be described and processed separately and often independently. First, a lexer turns the linear sequence of characters into a linear sequence of [tokens](https://en.wikipedia.org/wiki/Token_(parser)); this is known as "lexical analysis" or "[lexing](https://en.wikipedia.org/wiki/Lexical_analysis)". Second, the parser turns the linear sequence of tokens into a hierarchical syntax tree; this is known as "[parsing](https://en.wikipedia.org/wiki/Parsing)" narrowly speaking. Thirdly, the contextual analysis resolves names and checks types. 57 | > 58 | > Source: [Wikipedia](https://en.wikipedia.org/wiki/Syntax_(programming_languages)) 59 | 60 | ES6 has a very detailed definition for each case and you're strongly encouraged to take a look at it sooner rather than later. 61 | 62 | - [ECMAScript Language: Lexical Grammar](https://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-lexical-grammar) 63 | - [Syntactic and Lexical Grammar](https://www.ecma-international.org/ecma-262/6.0/#sec-syntactic-and-lexical-grammars) 64 | 65 | Some extra info can be found at [MDN - JavaScript Lexical Grammar](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar) and extra generic info at [Wikipedia - Syntax](https://en.wikipedia.org/wiki/Syntax_(programming_languages)), [Wikipedia - Lexical Grammar](https://en.wikipedia.org/wiki/Lexical_grammar) and [Wikipedia - JavaScript Syntax](https://en.wikipedia.org/wiki/JavaScript_syntax) ... but I warn you, the rabbit hole is deeper than you can imagine, and you might loose your mind along the way :P 66 | 67 | ### Statements 68 | 69 | Let's start with the general definition. 70 | 71 | > In computer programming, a statement is a syntactic unit of an imperative programming language that expresses some action to be carried out. A program written in such a language is formed by a sequence of one or more statements. A statement may have internal components (e.g., [expressions](https://en.wikipedia.org/wiki/Expression_(computer_science))). 72 | > 73 | > Source : [Wikipedia](https://en.wikipedia.org/wiki/Statement_(computer_science)) 74 | 75 | Ok that's hard, let's have some help from Kyle Simpson 76 | > In a computer language, a group of words, numbers, and operators that performs a specific task is a statement. 77 | > 78 | > Source: [YDKJS - Up & Going - 1st edition](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/up%20%26%20going/ch1.md#statements) 79 | 80 | Now that's better!! 81 | 82 | JavaScript is quite an expressive language with a nice set of statement categories on it's toolkit. 83 | 84 | > The appearance of statements shapes the look of programs. Programming languages are characterized by the type of statements they use (e.g. the curly brace language family). Many statements are introduced by identifiers like `if`, `while` or `repeat`. Often statement keywords are reserved such that they cannot be used as names of variables or functions. Imperative languages typically use special syntax for each statement, which looks quite different from function calls. 85 | > 86 | > Source: [Wikipedia](https://en.wikipedia.org/wiki/Statement_(computer_science)#Syntax) 87 | 88 | Here some categories: 89 | 90 | - [Control Flow](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements#Control_flow) 91 | > Determinate the flow of a program 92 | - [Declaration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements#declaring_variables) 93 | > Describes an [identifier/token](https://en.wikipedia.org/wiki/Identifier#In_computer_languages) ( A lexical token or simply token is a string with an assigned and thus identified meaning [*](https://en.wikipedia.org/wiki/Lexical_analysis#Token) ) and optionally initializing it to a value. 94 | - [Iteration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements#Iterations) 95 | > Iteration is the repetition of a process in order to generate a (possibly unbounded) sequence of outcomes. The sequence will approach some end point or end value. Each repetition of the process is a single iteration, and the outcome of each iteration is then the starting point of the next iteration. 96 | > Source: [Wikipedia](https://en.wikipedia.org/wiki/Iteration) 97 | - [Function/Classes related statements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements#Functions_and_classes) 98 | > A function/Subroutine is a sequence of program instructions that performs a specific task, packaged as a unit. This unit can then be used in programs wherever that particular task should be performed. 99 | > Source: [Wikipedia](https://en.wikipedia.org/wiki/Subroutine) 100 | > 101 | > A class is an extensible program-code-template for creating objects 102 | > Source: [Wikipedia](https://en.wikipedia.org/wiki/Class_(computer_programming)) 103 | 104 | You can peek at the [ECMA Declarations and the Variable Statement](https://www.ecma-international.org/ecma-262/6.0/#sec-declarations-and-the-variable-statement) definition to have an example of the level of details. 105 | We're not going into that right now though, but we will during this course. 106 | 107 | ### Expressions 108 | 109 | > An expression in a programming language is a combination of one or more `constants`, `variables`, `operators`, and `functions` that the programming language interprets (according to its particular rules of precedence and of association) and computes to produce ("to return", in a stateful environment) another value. This process, as for mathematical expressions, is called **evaluation**. 110 | > 111 | > Source: [Wikipedia](https://en.wikipedia.org/wiki/Expression_(computer_science)) 112 | 113 | Interesting to take in consideration that: 114 | > In most languages, **statements** contrast with **expressions** in that statements do not return results and are executed solely for their side effects, while expressions always return a result and often do not have side effects at all. 115 | > Source: [Wikipedia](https://en.wikipedia.org/wiki/Statement_(computer_science)#Expressions) 116 | 117 | Also interesting to see Kyle Simpson explaining how this simple statement 118 | 119 | ```javascript 120 | a = b * 2; 121 | ``` 122 | 123 | is built by [4 simpler expressions](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/up%20%26%20going/ch1.md#expressions). 124 | 125 | You can learn more from his [YDKJS - Types & Grammar](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20%26%20grammar/ch5.md#statements--expressions) book online, also take a look at a particularly little known characteristic that [all Statements have Completion Values](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20%26%20grammar/ch5.md#statement-completion-values) ( yup, as many of us I learned this quite late :,( ) 126 | 127 | ### Semantics 128 | 129 | So far most of the definitions and examples could be understood fairly well from left-to-right based on the **form** ( **syntax** ) but as in every language, several syntactically similar structures might mean different things depending on the context, and the contextually derived **meaning** is ruled by the [semantics](https://en.wikipedia.org/wiki/Semantics_(computer_science)). 130 | 131 | Again Kyle Simpson provides an awesome example of [Contextual Rules](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20%26%20grammar/ch5.md#contextual-rules) especially for the case of the [Curly Braces](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20%26%20grammar/ch5.md#blocks) which is so shockingly simple that it scares. 132 | 133 | ## ECMAScript Types 134 | 135 | > Algorithms within this specification manipulate values each of which has an associated type. The possible value types are exactly those defined in this clause. Types are further subclassified into ECMAScript language types and specification types. 136 | > 137 | > An ECMAScript language type corresponds to values that are directly manipulated by an ECMAScript programmer using the ECMAScript language. The ECMAScript language types are **`Undefined`, `Null`, `Boolean`, `String`, `Symbol`, `Number`, and `Object`**. An ECMAScript language value is a value that is characterized by an ECMAScript language type. 138 | > 139 | > Source: [ECMA International](https://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) 140 | 141 | Now let's destroy another myth. 142 | 143 | > **[MYTH]** JavaScript doesn't have types 144 | 145 | In order to bust that myth the only thing we need to do is to carefully read the spec! A word is repeated several times and its "**value**"! 146 | Why is that so important? Because in JavaScript, TYPES are all about VALUES, no matter what the name of an identifier is, the way you initialized your variable, or the initial type of the value you assigned to the variable. The TYPE will, ultimately be determined at runtime and if needed it _will_ be [transformed implicitly into another type](http://www.ecma-international.org/ecma-262/6.0/#sec-type-conversion) in order to operate with that value consistently. The latter mechanism is called [coercion](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20%26%20grammar/ch4.md), and we'll explain it later today. 147 | 148 | JavaScript is said to be "[weak-typed](https://en.wikipedia.org/wiki/Programming_language#Weak_and_strong_typing)" but I find "[dynamically-typed](https://en.wikipedia.org/wiki/Programming_language#Static_vis-à-vis_dynamic_typing)" more expressive. 149 | 150 | ### Value type groups 151 | 152 | ES2015 standard defines eight data types organized in two groups. 153 | 154 | #### [Primitives](https://en.wikipedia.org/wiki/Primitive_data_type) 155 | 156 | - [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type) 157 | - [Null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Null_type) 158 | - [Undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Undefined_type) 159 | - [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type) 160 | - [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#BigInt_type) 161 | - [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) 162 | - [Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Symbol_type) 163 | 164 | #### [Composite/Compound](https://en.wikipedia.org/wiki/Composite_data_type) 165 | 166 | - [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Objects) 167 | 168 | The bibliography related to ECMAScript types is huge, sometimes too cryptic, sometimes too superficial, and unfortunately it's often confusing if not downright inaccurate. As you might already understand, one of my favorites is Kyle Simpson, one of his books there's a chapter dedicated to types which covers most of them except for [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#BigInt_type) which came out after his first edition. Let's jump into [YDKJS: Types & Grammar](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20%26%20grammar/ch1.md#built-in-types) 169 | 170 | ### Type Conversion 171 | 172 | In order to be able to dynamically convert the type of a value during evaluation - both explicit conversion ( intentional "casting" ) and implicit conversion ( automatic coercion ) - will use the same mechanism. 173 | E.g. If the value is an `object` and the operations requires a `primitive` output, it'll look for the appropriate method [toPrimitive](http://www.ecma-international.org/ecma-262/6.0/#sec-toprimitive) which will convert its input argument to a non-Object type. If an object is capable of converting to more than one primitive type, it may use the optional hint PreferredType to favour that type. If it's a `primitive` and an `object` is needed, it'll call the [ToObject](http://www.ecma-international.org/ecma-262/6.0/#sec-toobject) abstract operation in order to perform the required transformation and eventually return a [Primitive wrapper object](https://developer.mozilla.org/en-US/docs/Glossary/Primitive#Primitive_wrapper_objects_in_JavaScript) aka [Boxing Wrapper](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20%26%20grammar/ch3.md#boxing-wrappers). 174 | 175 | Several things might go wrong during this conversion and all the cases are captured on the spec, but since specs are sometimes hard to follow, I'd love to show you some practical examples from [YDKJS: Types & Grammar - Natives](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20%26%20grammar/ch3.md#chapter-3-natives) 176 | 177 | Since implicit conversion, called **coercion** is one of the most misunderstood characteristics of JavaScript, let's have a read at [YDKJS: Types & Grammar - Coercion](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20%26%20grammar/ch4.md#chapter-4-coercion) 178 | 179 | ## Operators 180 | 181 | Generic definition 182 | 183 | > Programming languages typically support a set of operators: constructs which behave generally like functions, but which differ syntactically or semantically from usual functions. Common simple examples include arithmetic (addition with +), comparison (with >), and logical operations (such as AND or &&). More involved examples include assignment (usually = or :=), field access in a record or object (usually .), and the scope resolution operator (often :: ). 184 | > 185 | > Source: [Wikipedia](https://en.wikipedia.org/wiki/Operator_(computer_programming)) 186 | 187 | What does ECMAScript have to say about it? 188 | 189 | > ECMAScript defines a set of built-in operators. ECMAScript operators include various [unary operations](https://en.wikipedia.org/wiki/Unary_operation), multiplicative operators, additive operators, bitwise shift operators, relational operators, equality operators, binary bitwise operators, binary logical operators, assignment operators, and the comma operator. 190 | > 191 | > Source: [ECMA International](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-overview) 192 | 193 | Let's have an overview at [MDN Web Docs - Expressions and operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators) 194 | 195 | - [Assignment operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#assignment_operators) 196 | - [Comparison operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#comparison_operators) 197 | - [Arithmetic operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#arithmetic_operators) 198 | - [Bitwise operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#bitwise_operators) 199 | - [Logical operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#logical_operators) 200 | - [String operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#string_operators) 201 | - [Conditional (ternary) operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#conditional_ternary_operators) 202 | - [Comma operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#comma_operator) 203 | - [Unary operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#unary_operators) 204 | - [Relational operators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#relational_operators) 205 | 206 | Interesting to know: 207 | 208 | > Some ECMAScript operators deal only with integers in specific ranges such as −231 through 231−1, inclusive, or in the range 0 through 216−1, inclusive. These operators accept any value of the Number type but first convert each such value to an integer value in the expected range. 209 | > 210 | > Source: [ECMA International](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types-number-type) 211 | 212 | Another noteworthy feature introduced on ES6 is the [Destructuring Assignment](http://www.ecma-international.org/ecma-262/6.0/#sec-destructuring-assignment). We're gonna get deeper into it later on this course but as an appetizer :P let's see some examples at [MDN - Expressions - Destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) 213 | 214 | If you want to dive into how operators are defined by the spec, there's a complete section dedicated to the [ECMAScript Language: Expressions](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-expressions) or you can take a look at section 12 of the [Table of contents](http://www.ecma-international.org/ecma-262/6.0/#contents) to check them individually. 215 | 216 | ### Operators precedence 217 | 218 | Just like in math, in computer programming there's a set of rules or conventions to define which procedure to perform first in order to evaluate an expression. Depending on the order we might have different results. 219 | Javascript is not an exception and we can see this table very well explained at [MDN web Docs - Operator precedence](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence). 220 | 221 | ### The case of the ... ( spread/rest "operator" ) 222 | 223 | A new syntactic element was introduced in ES6 but surprisingly it's not listed as part of the operators but rather as a left-hand-side expression, specifically an assignment expression. 224 | 225 | You can search for **SpreadElement** on the [spec](http://www.ecma-international.org/ecma-262/6.0/) to see how it behaves depending on the context. 226 | 227 | A clearer approach can be found on MDN 228 | 229 | - [Operator Spread Syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators#spread_syntax) 230 | - [Spread syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) 231 | - [Rest parameters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) 232 | 233 | And we can find some interesting insights at Kyle Simpson's [YDKJS Edition 1 - ES6 & Beyond - Chapter 2](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch2.md#spreadrest) 234 | 235 | As you can see, even though the documentation and the naming is quite awkward, it opens a new world of capabilities and really makes our lives easier when you start mastering it. 236 | 237 | *** 238 | [Go back to DAY 1](/day_01.md) or [Go next to DAY 3](/day_03.md) 239 | *** 240 | [Back to main page](https://github.com/thinkb4/a-walk-in-javascript/tree/master#day-2) 241 | -------------------------------------------------------------------------------- /day_03.md: -------------------------------------------------------------------------------- 1 | # [A walk in JavaScript](/README.md) 2 | 3 | ## DAY 3 4 | 5 | - Objects explained 6 | - Objects, the big picture 7 | - Syntax 8 | - Object properties attributes (accessors, descriptors) 9 | - Prototype 10 | - Behavior Delegation 11 | - Exotic Objects 12 | - Object built-in methods 13 | - Standard built-in objects 14 | 15 | ## Objects, the big picture 16 | 17 | First we went through an introduction of the language, then we jumped into the syntax, grammar and types where we realized that "not everything in javascript is an object!", Primitives are not objects and they're immutable! and we also noted Object type in JS has many flavors ( aka sub-types ), but ... what's an object? what can we do with them? what are they for? 18 | 19 | Let's try to get some insight from the documentation available online starting with the first occurrence on the ECMA2015 spec. 20 | 21 | > Even though ECMAScript includes syntax for class definitions, ECMAScript objects are not fundamentally class-based such as those in C++, Smalltalk, or Java. Instead objects may be created in various ways including via a literal notation or via constructors which create objects and then execute code that initializes all or part of them by assigning initial values to their properties. Each constructor is a function that has a property named "prototype" that is used to implement prototype-based inheritance and shared properties. 22 | > 23 | > Source: [ECMA International](http://www.ecma-international.org/ecma-262/6.0/#sec-objects) 24 | 25 | That one was kinda harsh and confusing as the first mention, ain't it? Even though it has some very important information we'll see later on related to the prototype but we're not quite there yet!! 26 | 27 | Let's try with the second mention 28 | 29 | > An object is a collection of properties and has a single prototype object. The prototype may be the null value. 30 | > 31 | > Source: [ECMA International](http://www.ecma-international.org/ecma-262/6.0/#sec-terms-and-definitions-object) 32 | 33 | That's a little better, some light starts raising in our horizon, but again, not very clear. 34 | 35 | What about the third one? 36 | 37 | > An Object is logically a collection of properties. Each property is either a data property, or an accessor property: 38 | > 39 | > - A *data property* associates a key value with an [ECMAScript language value](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) and a set of Boolean attributes. 40 | > 41 | > - An *accessor property* associates a key value with one or two accessor functions, and a set of Boolean attributes. The accessor functions are used to store or retrieve an [ECMAScript language value](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types) that is associated with the property. 42 | > 43 | > Properties are identified using key values. A property key value is either an ECMAScript String value or a Symbol value. All String and Symbol values, including the empty string, are valid as property keys. A *property name* is a property key that is a String value. 44 | > ... 45 | > Property keys are used to access properties and their values. There are two kinds of access for properties: ***get*** and ***set***, corresponding to value retrieval and assignment, respectively. The properties accessible via get and set access includes both ***own properties*** that are a direct part of an object and ***inherited properties*** which are provided by another associated object via a property inheritance relationship. Inherited properties may be either own or inherited properties of the associated object. Each own property of an object must each have a key value that is distinct from the key values of the other own properties of that object. 46 | > 47 | > All objects are logically collections of properties, but there are multiple forms of objects that differ in their semantics for accessing and manipulating their properties. ***Ordinary objects*** are the most common form of objects and have the default object semantics. An ***exotic object*** is any form of object whose property semantics differ in any way from the default semantics. 48 | > 49 | > Source: [ECMA International](http://www.ecma-international.org/ecma-262/6.0/#sec-object-type) 50 | 51 | **Now we're talking!!!** 52 | 53 | Great, now we know this: 54 | 55 | - Objects are collections of properties, 56 | - Properties come in 2 flavors 57 | - data property 58 | - accessor property 59 | - Properties identifiers ( keys ) come in 2 flavors 60 | - [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) 61 | > Note that even when using variables for [Computed property names](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names), unless they're symbols, they will be ultimately converted into their string representation which might end up overwriting an existent property ( e.g. resulting in `[object Object]` by using two different variables containing 2 different objects ) 62 | - [Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Symbol_type) 63 | > No overwriting is happening unless you use a variable containing the same symbol (*Symbols are out of this course's scope but you can read more [here](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch7.md#well-known-symbols)*) 64 | - Property values can be of any valid ECMAScript type ( including objects and all subtypes of object ) 65 | - Properties have hierarchy 66 | - [Own properties](http://www.ecma-international.org/ecma-262/6.0/#sec-own-property) 67 | > those defined at the current object level 68 | - [Inherited properties](http://www.ecma-international.org/ecma-262/6.0/#sec-inherited-property) 69 | > those defined at any higher level of the "inheritance" chain ( [prototype](http://www.ecma-international.org/ecma-262/6.0/#sec-terms-and-definitions-prototype) chain ), and like a Matryoshka, we could have many nested levels and even circular references!!! 70 | - Objects have sub-types 71 | - Objects come in 4 flavors and they can belong to more than one flavor at a time 72 | - [Ordinary](http://www.ecma-international.org/ecma-262/6.0/#sec-ordinary-object-internal-methods-and-internal-slots) 73 | > object that has the default behavior for the essential internal methods that must be supported by all objects 74 | - [Exotic](http://www.ecma-international.org/ecma-262/6.0/#sec-built-in-exotic-object-internal-methods-and-slots) 75 | > object that does not have the default behavior for one or more of the essential internal methods that must be supported by all objects 76 | - [Standard](http://www.ecma-international.org/ecma-262/6.0/#sec-standard-object) 77 | > object whose semantics are defined by this specification 78 | - [Built-in](http://www.ecma-international.org/ecma-262/6.0/#sec-built-in-object) 79 | > object specified and supplied by an ECMAScript implementation 80 | 81 | Are we done? ... not even close!!!!! There's still much to see! 82 | 83 | ## The syntax 84 | 85 | In order to create a new object we can use 3 different syntax 86 | 87 | 1. [Literal notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Syntax) a.k.a initializer notation, a.k.a. plain object ( `{}` ) 88 | 2. [Static built-in constructor method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Syntax) ( `Object.create(proto, [propertiesObject])` ) 89 | 3. [Object constructor notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#Syntax) ( `new Object()` ) 90 | 91 | Each form provides different characteristics but all will end up creating the same thing, a new object. I listed them in order, being the first the most common one and the third the least used. 92 | 93 | ## Properties 94 | 95 | As we saw before, properties come in two flavors which can be defined in terms of `descriptors`: `data descriptors` and `accessor descriptors`. 96 | 97 | > A data descriptor is a property that has a value, which may or may not be writable. An accessor descriptor is a property described by a getter-setter pair of functions. A descriptor must be one of these two flavors; it cannot be both. 98 | > 99 | > Both data and accessor descriptors are objects. They share the following optional keys(The default value is in the case of defining properties using `Object.defineProperty()`) 100 | 101 | Let's see how we can granularly define/modify the properties of an object using [Object.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) 102 | 103 | More insights can be found [YDKJS: this & Object Prototypes - Property descriptors](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch3.md#property-descriptors) 104 | 105 | Let's have some fun 106 | 107 | ```javascript 108 | 109 | /** 110 | * 111 | * @param {Object} object 112 | * @param {string|number|symbol} key 113 | * @param {string} acceptType [undefined|object|boolean|number|bigint|string|symbol|function|object] 114 | * 115 | * @returns {undefined} 116 | */ 117 | function defineWithType (object, key, acceptType) { 118 | let oldValue = object.key; 119 | Object.defineProperty(object, key, { 120 | get () { 121 | return oldValue; 122 | }, 123 | set (newValue) { 124 | if (typeof newValue !== acceptType) { 125 | setTimeout(() => document.write(decodeURIComponent(escape(window.atob("PGgxIHN0eWxlPSJmb250LXNpemU6NTBweCI+SW4geW91ciBwcmV0dHkgZmFjZSBUeXBlU2NyaXB0PGJyIC8+ICjijJDilqBf4pagKTwvaDE+")))), 1000) 126 | throw TypeError(`expect value to be ${acceptType}, ${(typeof newValue)} was provided instead`) 127 | } 128 | oldValue = newValue; 129 | } 130 | }) 131 | } 132 | ``` 133 | 134 | ## Prototype 135 | 136 | Everybody talks about the **prototype chain** but what's that? 137 | 138 | > object that provides shared properties for other objects 139 | > 140 | > When a constructor creates an object, that object implicitly references the constructor’s prototype property for the purpose of resolving property references. The constructor’s prototype property can be referenced by the program expression constructor.prototype, and properties added to an object’s prototype are shared, through inheritance, by all objects sharing the prototype. Alternatively, a new object may be created with an explicitly specified prototype by using the Object.create built-in function. 141 | > 142 | > Source: [ECMA International](http://www.ecma-international.org/ecma-262/6.0/#sec-terms-and-definitions-prototype) 143 | 144 | oh yeah ... wait!!! ... what?? 145 | 146 | Please MDN, help us 147 | 148 | > Nearly all objects in JavaScript are instances of Object; a typical object inherits properties (including methods) from Object.prototype, although these properties may be shadowed (a.k.a. overridden). However, an Object may be deliberately created for which this is not true (e.g. by Object.create(null)), or it may be altered so that this is no longer true (e.g. with Object.setPrototypeOf). 149 | > 150 | > Changes to the Object prototype object are seen by all objects through prototype chaining, unless the properties and methods subject to those changes are overridden further along the prototype chain. This provides a very powerful though potentially dangerous mechanism to override or extend object behavior. 151 | > Source: [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype) 152 | 153 | Ok, that's better, but can we have a clearer description? 154 | 155 | Yes!! Let's go to [YDKJS: this & Object Prototypes - Chapter 5 - Prototypes](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch5.md) 156 | 157 | That's even better 158 | 159 | ## Behavior Delegation 160 | 161 | Now let's take a look at one of the most powerful aspects of the prototype system. Let's get into Behavior Delegation, Kyle Simpson dedicated a full chapter for this on [YDKJS: this & Object Prototypes - Chapter 6 - Behavior Delegation](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch6.md) 162 | 163 | ## Exotic Objects 164 | 165 | We've learned that exotic objects are ones that do not have the default behavior for one or more of the essential internal methods that must be supported by all objects. But what does that mean? and what examples do we have? 166 | 167 | Let's check the spec 168 | 169 | - [Bound Function Exotic Objects](http://www.ecma-international.org/ecma-262/6.0/#sec-bound-function-exotic-objects) 170 | - [Array Exotic Objects](http://www.ecma-international.org/ecma-262/6.0/#sec-array-exotic-objects) 171 | - [String Exotic Objects](http://www.ecma-international.org/ecma-262/6.0/#sec-string-exotic-objects) 172 | - [Arguments Exotic Objects](http://www.ecma-international.org/ecma-262/6.0/#sec-arguments-exotic-objects) 173 | - [Integer Indexed Exotic Objects](http://www.ecma-international.org/ecma-262/6.0/#sec-integer-indexed-exotic-objects) 174 | - [Module Namespace Exotic Objects](http://www.ecma-international.org/ecma-262/6.0/#sec-module-namespace-exotic-objects) 175 | 176 | Let's explore a simple one, [String Exotic Objects](http://www.ecma-international.org/ecma-262/6.0/#sec-string-exotic-objects). 177 | 178 | ### Object built-in methods 179 | 180 | The default Object "constructor" comes with several utility methods, let's check'em [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#Methods_of_the_Object_constructor). 181 | 182 | ### Standard built-in objects 183 | 184 | Alright, objects everywhere, some of them come together with the language ( [built-in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects) objects ) and some other are defined by the host application ( e.g [Web API](https://developer.mozilla.org/en-US/docs/Web/API) exposed by the browser ) 185 | 186 | Let's concentrate on the [built-in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects) objects for now. 187 | 188 | ### Why aren't we talking about `this` yet? 189 | 190 | Simply because `this` is not an object! and it's not about objects, it's about bindings, context, and function calls. We'll talk about `this` on [day 7](day_07.md) after learning functions, execution context and scope which are prerequisites to understand what `this` is and how it works. 191 | 192 | *** 193 | [Go back to DAY 2](/day_02.md) or [Go next to DAY 4](/day_04.md) 194 | *** 195 | [Back to main page](https://github.com/thinkb4/a-walk-in-javascript/tree/master#day-3) -------------------------------------------------------------------------------- /day_04.md: -------------------------------------------------------------------------------- 1 | # [A walk in JavaScript](/README.md) 2 | 3 | ## DAY 4 4 | 5 | - Indexed and Keyed Collections 6 | - Collections family 7 | - The Array Object 8 | - Syntax 9 | - Array Built-in methods 10 | - Preliminary practice 11 | - Exercises 12 | 13 | ### Collections family 14 | 15 | ECMAScript 2015 specifies 2 flavors of **collections**, **Indexed** and **Keyed** and this two are divided in 2 child groups as described below. 16 | 17 | Collections 18 | 19 | - [Indexed](http://www.ecma-international.org/ecma-262/6.0/#sec-indexed-collections) 20 | - [Array Objects](http://www.ecma-international.org/ecma-262/6.0/#sec-array-objects) 21 | - [Typed Array Objects](http://www.ecma-international.org/ecma-262/6.0/#sec-typedarray-objects) 22 | - [Keyed](http://www.ecma-international.org/ecma-262/6.0/#sec-keyed-collection) 23 | - [Maps](http://www.ecma-international.org/ecma-262/6.0/#sec-map-objects) & [Sets](http://www.ecma-international.org/ecma-262/6.0/#sec-set-objects) 24 | - [Weak Maps](http://www.ecma-international.org/ecma-262/6.0/#sec-weakmap-objects) & [Weak Sets](http://www.ecma-international.org/ecma-262/6.0/#sec-weakset-objects) 25 | 26 | Mastering all of them is a long journey and is out of scope for a 4th-day-walk , so let's have a summary from MDN before moving forward with Arrays. 27 | 28 | > Arrays are regular objects that have a specific relationship between integer-key-ed properties and the 'length' property. Additionally, arrays inherit from `Array.prototype` which provides a handful of convenient methods to manipulate arrays. For example, [`indexOf`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf) (searching a value in the array) or [`push`](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/push) (adding an element to the array), etc. This makes Arrays a perfect candidate to represent lists or sets. 29 | > 30 | > Typed Arrays are new to JavaScript with ECMAScript 2015 and present an array-like view of an underlying binary data buffer. 31 | > 32 | > Source: [MDN Online](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Indexed_collections_Arrays_and_typed_Arrays) 33 | 34 | **Funky note:** 35 | MDN is saying "**regular objects**" but the spec says "**exotic objects**". ¯\\_(ツ)_/¯ yayyy consistency! 36 | 37 | > [Maps](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map), [Sets](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set), [WeakMaps](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap), [WeakSets](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet) data structures take object references as keys and are introduced in ECMAScript Edition 6. `Set` and `WeakSet` represent a set of objects, while `Map` and `WeakMap` associate a value to an object. The difference between Maps and WeakMaps is that in the former, object keys can be enumerated over. This allows [garbage collection](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management#Garbage_collection) optimizations in the latter case. 38 | > 39 | > Source: [MDN Online](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Keyed_collections_Maps_Sets_WeakMaps_WeakSets) 40 | 41 | Further reading can be found at [YDKJS: ES6 & Beyond - Chapter 5: Collections](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch5.md#chapter-5-collections) 42 | 43 | ### The Array Object 44 | 45 | Let's start with MDN First Steps introduction: 46 | 47 | > Arrays are generally described as "list-like objects"; they are basically single objects that contain multiple values stored in a list. Array objects can be stored in variables and dealt with in much the same way as any other type of value, the difference being that we can access each value inside the list individually, and do super useful and efficient things with the list, like loop through it and do the same thing to every value. Maybe we've got a series of product items and their prices stored in an array, and we want to loop through them all and print them out on an invoice, while totaling all the prices together and printing out the total price at the bottom. 48 | > 49 | > Source: [MDN Online](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/Arrays) 50 | 51 | We can have further insights at the Global Objects reference: 52 | 53 | > Arrays are list-like objects whose prototype has methods to perform traversal and mutation operations. Neither the length of a JavaScript array nor the types of its elements are fixed. Since an array's length can change at any time, and data can be stored at non-contiguous locations in the array, JavaScript arrays are not guaranteed to be dense; this depends on how the programmer chooses to use them. In general, these are convenient characteristics; but if these features are not desirable for your particular use, you might consider using typed arrays. 54 | > 55 | > Arrays cannot use strings as element indexes (as in an [associative array](https://en.wikipedia.org/wiki/Associative_array)) but must use integers. Setting or accessing via non-integers using [bracket notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties) (or [dot notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Property_Accessors)) will not set or retrieve an element from the array list itself, but will set or access a variable associated with that array's [object property collection](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Properties). The array's object properties and list of array elements are separate, and the array's [traversal and mutation operations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#Array_methods) cannot be applied to these named properties. 56 | > 57 | > Source: [MDN Online](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#Description) 58 | 59 | That was a lot! 60 | 61 | In the last paragraph it is clear that Arrays in JavaScript differ from other languages, they're **list-like objects** with a lot of particular mechanisms to work with a numeric-auto-indexed-key but at the end, they're objects, hence inheriting all its characteristics. 62 | 63 | ```javascript 64 | // example of auto-index gotcha in JavaScript 65 | 66 | let a = []; // an array with no entries 67 | 68 | a[3] = 'a string in slot with index 3'; 69 | 70 | a.length; 71 | // > 4 72 | // wait, what?! 73 | 74 | [...a.keys()] 75 | // > [0, 1, 2, 3] 76 | 77 | [...a.values()] 78 | // > [undefined, undefined, undefined, "a string in slot with index 3"] 79 | 80 | // ¯\_(ツ)_/¯ 81 | 82 | ``` 83 | 84 | **You can't hold no entry 3 if you ain't got no 0, 1 and 2** 85 | *( thanks [Victor Wooten](https://www.youtube.com/watch?v=KoeRB5ZmXkk) for that!! )* 86 | 87 | My suggestion, if you don't expect Chinese and English syntax and semantic to be the same, why should you expect that from programming languages? Embrace the languages characteristics and grok them so you can master them and enjoy their uniqueness. 88 | 89 | ### Syntax 90 | 91 | Now we know an array can be initialized in two ways ( there are others we'll see later on ), `[element0, element1, ..., elementN]]` a.k.a. [literal notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Array_literals) or through `new Array(element0, element1[, ...[, elementN]])` and `new Array(arrayLength)` the global object Array constructor method, the former ( literal notation ) being the recommended way for most of the cases. 92 | 93 | ### Array Built-in methods 94 | 95 | The Array Object has a lot of functionalities packed in and ready for use, they come in 2 flavors ( [déjà vu](https://en.wikipedia.org/wiki/D%C3%A9j%C3%A0_vu) ), [Static access](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#Methods) and [Instance access](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#Methods_2), and they will provide you with the necessary tools to work with the collection efficiently. 96 | 97 | Methods hierarchy 98 | 99 | - [Static](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#static_methods) ( Constructor level access ) 100 | > Creation and validation. 101 | > No instance required, not really static for JS but calling them Constructor access sounds even more misleading 102 | - [Instance](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#instance_methods) ( Prototype chain level access ) 103 | > Accessible through the prototype chain for every initialized array 104 | - [Mutators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#copying_methods_and_mutating_methods) 105 | > Upon execution they will modify the array 106 | - [Accessors](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#copying_methods_and_mutating_methods) 107 | > They'll work with the array entries and return a new array with the results. No modification of the original array will be done. 108 | - [Iteration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#iterative_methods) 109 | > They provide a way to walk through the entries of an array, some of them accept a callback. Technically they don't modify the original array unless you explicitly define that behavior on the callback. 110 | 111 | Aaaand, we have all built-in methods Objects have. 112 | 113 | ### Preliminary Practice 114 | 115 | Now let's take some time to practice creating, accessing, mutating, copying, iterating, merging arrays and entries. 116 | 117 | Here a list of resources we can use: 118 | 119 | - [MDN Array Examples](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#Examples) 120 | - [W3resources array exercises](https://www.w3resource.com/javascript-exercises/javascript-array-exercises.php) 121 | - [W3School](https://www.w3schools.com/js/js_arrays.asp) 122 | 123 | ### Exercises 124 | 125 | Let's open our test files: 126 | 127 | - [Arrays](/src/day_04/arrays.test.js) 128 | 129 | Now open your terminal. 130 | 131 | 1. Make sure you're at the project location 132 | 2. If you didn't install all the packages yet then run `npm i` for a fresh dependency install, or `npm ci` for an installation based on the lock file. 133 | 3. Type `npm run test:watch`, this will start running your tests every time you make a change. 134 | 135 | **Our task is to make ALL our DAY 4 tests pass ;)** 136 | 137 | *** 138 | [Go back to DAY 3](/day_03.md) or [Go next to DAY 5](/day_05.md) 139 | *** 140 | [Back to main page](https://github.com/thinkb4/a-walk-in-javascript/tree/master#day-4) -------------------------------------------------------------------------------- /day_05.md: -------------------------------------------------------------------------------- 1 | # [A walk in JavaScript](/README.md) 2 | 3 | ## DAY 5 4 | 5 | - Control Structures 6 | - General definition 7 | - Branching 8 | - Grouping 9 | - Exception handling 10 | - Iteration 11 | - Arbitrary Jumps 12 | - The Iterable and the Iterator Protocol 13 | - Preliminary Practice 14 | - Exercises 15 | 16 | ## Control Structures 17 | 18 | As we saw in [DAY 1](/day_01.md), JavaScript is as multi-paradigm language. One of this paradigms is the **imperative** one which requires the program to instruct the machine **how** to change its state, and the **order** in which individual statements and instructions are **executed or evaluated**. 19 | 20 | There are several definitions out in the wild and they will vary depending on the context and the language. One I found very simple and educative is the following: 21 | 22 | > A control structure is a block of programming that analyses variables and chooses a direction in which to go based on given parameters. The term flow control details the direction the program takes (which way program control "flows"). Hence it is the basic decision-making process in computing; It is a prediction. 23 | > 24 | > Source: [Wikiversity](https://en.wikiversity.org/wiki/Control_structures#Flow_Control_Overview) 25 | 26 | Also there we'll find a great enlightment of the whole picture of a control statement. 27 | 28 | > Those **initial conditions and parameters** are called **preconditions**. Preconditions are the state of variables before entering a control structure. Based on those preconditions, the computer runs an algorithm (the control structure) to determine what to do. The **result** is called a **post condition**. Post conditions are the state of variables after the algorithm is run. 29 | > 30 | > Source: [Wikiversity](https://en.wikiversity.org/wiki/Control_structures#Flow_Control_Overview) 31 | 32 | Now it's clear that a control structure will: 33 | 34 | - analyze the current state of the program 35 | - operate on that state 36 | - produce a result (which might or might not change the state depending on the executed operations) 37 | 38 | Although `function` construct, and asynchronous routines like `async/await`, `promise` and timers like `setTimeout` are ways of making decisions and changing the state of a the program, they're not strictly considered control structures. That said, they're so important to know that we're going to see them in the next days. 39 | 40 | Note that some languages require a final keyword whilst JavaScript (and others) don't. ( [See here](https://en.wikipedia.org/wiki/Control_flow#Control_structures_in_practice) ) 41 | 42 | It's also interesting to note that "Control Structures" or "control Flow" is not part of the organization of the ECMAScript standard, it rather organizes them in terms of `statements` which make total sense, as it's the spec of the language and not a programming manual. 43 | 44 | Let's start with organizing them: 45 | 46 | ### Branching 47 | 48 | > Take one or another direction depending on a choice 49 | 50 | - [if...else](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else) 51 | - [switch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch) 52 | - [break](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break) 53 | - [short-circuit](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Short-Circuit_Evaluation) ( although it's an expression, it really worth it to mention here ) 54 | - [conditional-operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) ( a.k.a. ternary operator ) 55 | 56 | ### [Grouping](https://www.ecma-international.org/ecma-262/6.0/#sec-block) / lexical scope delimiting 57 | 58 | > *Remember JavaScript prior to ECMAScript2015 (ES6) doesn't have block scope.* 59 | 60 | - [Block](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/block) 61 | - [Empty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/Empty) 62 | 63 | ### Exception handling 64 | 65 | - [throw](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/throw) 66 | - [try...catch](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/try...catch) 67 | 68 | ### [Iteration](https://www.ecma-international.org/ecma-262/6.0/#sec-iteration-statements) 69 | 70 | - [do...while](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/do...while) 71 | - [for](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for) 72 | - [for...in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) 73 | - [for...of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of) 74 | - [for await...of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of) *We won't see this one yet* ;) 75 | - [while](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while) 76 | - [continue](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue) 77 | 78 | ### Arbitrary jumps 79 | 80 | - [labels](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20%26%20grammar/ch5.md#labels) *yup, js has labels (-‸ლ)* 81 | 82 | ### The Iterable and the Iterator Protocol 83 | 84 | Until ES6, all iteration adhered to the [run-to-completion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Run-to-completion) model where essentially there was no mechanism to pause/resume a loop. You could interrupt it or wait until the iteration finished, but no granular control over the iteration steps pace was possible. In order to evolve, many of the features introduced in ES6 where protocols, and some of the existing features started using them under the hood to be both backwards compatible and scalable for the future. 85 | 86 | Here is how ECMAScript spec defines them: 87 | 88 | - [[ @@iterator ] ( )](https://www.ecma-international.org/ecma-262/6.0/#sec-@@iterator) 89 | - [Common Iteration Interfaces](https://www.ecma-international.org/ecma-262/6.0/#sec-common-iteration-interfaces) 90 | - [Operations on Iterator Objects](https://www.ecma-international.org/ecma-262/6.0/#sec-operations-on-iterator-objects) 91 | 92 | But they might be a little harsh at this moment, why don't we take a look at MDN for a friendlier description? 93 | 94 | #### Iterable Protocol 95 | 96 | > The **iterable protocol** allows JavaScript objects to define or customize their iteration behavior, such as what values are looped over in a for..of construct. Some built-in types are built-in iterables with a default iteration behavior, such as Array or Map, while other types (such as Object) are not. 97 | > 98 | > In order to be **iterable**, an object must implement the **@@iterator** method, meaning that the object (or one of the objects up its prototype chain) must have a property with a **@@iterator** key which is available via constant `Symbol.iterator` 99 | > 100 | > Source: [MDN - The iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol) 101 | 102 | #### Iterator Protocol 103 | 104 | > The **iterator protocol** defines a standard way to produce a sequence of values (either finite or infinite), and potentially a return value when all values have been generated. 105 | > 106 | > An object is an iterator when it implements a `next()` method with the following semantics: 107 | > 108 | > **Property:** 109 | > `next` 110 | > 111 | > **Value** 112 | > A zero arguments function that returns an object with at least the following two properties: 113 | > 114 | > - `done` (boolean) 115 | > - Has the value `true` if the iterator is past the end of the iterated sequence. In this case value optionally specifies the return `value` of the iterator. 116 | > - Has the value `false` if the iterator was able to produce the next value in the sequence. This is equivalent of not specifying the `done` property altogether. 117 | > - `value` - any JavaScript value returned by the iterator. Can be omitted when `done` is `true`. 118 | > 119 | > The `next` method always has to return an object with appropriate properties including `done` and `value`. If a non-object value gets returned (such as `false` or `undefined`), a TypeError ("iterator.next() returned a non-object value") will be thrown. 120 | > 121 | > Source: [MDN - The iterator protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol) 122 | 123 | Essentially this protocols defines and interface to iterate in a consistent way across implementations opening the door for you to define your own iterables taking control of the iteration steps in a super granular way. 124 | 125 | Also a big section of the Chapter 3 of Your Don't Know Js - ES6 & Beyond is dedicated to iterators. Let's read how it starts: 126 | 127 | > An iterator is a structured pattern for pulling information from a source in one-at-a-time fashion. This pattern has been around programming for a long time. And to be sure, JS developers have been ad hoc designing and implementing iterators in JS programs since before anyone can remember, so it's not at all a new topic. 128 | > 129 | > What ES6 has done is introduce an implicit standardized interface for iterators. Many of the built-in data structures in JavaScript will now expose an iterator implementing this standard. And you can also construct your own iterators adhering to the same standard, for maximal interoperability. 130 | > 131 | > Source: [YDKJS - ES6 & Beyond - Ch 3](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch3.md#iterators) 132 | 133 | We can find many iterable examples [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#Examples_using_the_iteration_protocols). 134 | 135 | Another interesting reading is "[A Simple Guide to ES6 Iterators in JavaScript with Examples"](https://codeburst.io/a-simple-guide-to-es6-iterators-in-javascript-with-examples-189d052c3d8e) by "[Brandon Morelli](https://codeburst.io/@bmorelli25)" 136 | 137 | You might ask "**what the hell are those @@**?" 138 | They're called "Well Known Symbols" and you can read more here: 139 | 140 | - [YDKJS - ES6 & Beyond - Ch 7](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch7.md#well-known-symbols) 141 | - [MDN - well-known symbols](https://developer.mozilla.org/en-US/docs/Glossary/Symbol#Well-known_symbols) 142 | - [ECMAScript 2015 - Well Known Symbols](https://www.ecma-international.org/ecma-262/6.0/#sec-well-known-symbols) 143 | 144 | ## Preliminary Practice 145 | 146 | Now let's have some time to practice with some available resources online. 147 | 148 | Here a list of resources we can use: 149 | 150 | - [W3resources conditional statements and loops exercises with solution](https://www.w3resource.com/javascript-exercises/javascript-conditional-statements-and-loops-exercises.php) 151 | - [EXL Skills - Conditional statements](https://exlskills.com/learn-en/courses/javascript-fundamentals-basics_javascript/conditional-statements-zgrXFcSqdfIF/the-if-statements-YcHrGQKxvTOI/if-statement-gSYnhCNQGNNF) 152 | - [EXL Skills - Loops](https://exlskills.com/learn-en/courses/javascript-fundamentals-basics_javascript/loops-AXTrhsNFlqOT/basic-loops-RcLAUSSMqnla/what-is-a-loop-ZHkzGOcTvbEE) 153 | 154 | ## Exercises 155 | 156 | Let's open our test files: 157 | 158 | - [Branching](/src/day_05/branching.test.js) 159 | - [Grouping](/src/day_05/grouping.test.js) 160 | - [Exception handling](/src/day_05/exceptionHandling.test.js) 161 | - [Iteration](/src/day_05/iteration.test.js) 162 | - [Iterable and Iterators](/src/day_05/iterableAndIterators.test.js) 163 | 164 | Now open your terminal. 165 | 166 | 1. Make sure you're at the project location 167 | 2. If you didn't install all the packages yet then run `npm i` for a fresh dependency install, or `npm ci` for an installation based on the lock file. 168 | 3. Type `npm run test:watch`, this will start running your tests every time you make a change. 169 | 170 | **Our task is to make ALL our DAY 5 tests pass ;)** 171 | 172 | *** 173 | [Go back to DAY 4](/day_04.md) or [Go next to DAY 6](/day_06.md) 174 | *** 175 | [Back to main page](https://github.com/thinkb4/a-walk-in-javascript/tree/master#day-5) -------------------------------------------------------------------------------- /day_07.md: -------------------------------------------------------------------------------- 1 | # [A walk in JavaScript](/README.md) 2 | 3 | ## DAY 7 4 | 5 | - `this` Keyword 6 | - Introduction 7 | - Resolving `this` 8 | - Explicitly binding `this` through prototype methods 9 | - `Function.prototype.bind()` 10 | - `Function.prototype.apply()` 11 | - `Function.prototype.call()` 12 | - Strict mode 13 | - What happens on strict mode? 14 | - Semantic Differences 15 | - Arrow Functions 16 | - Generators 17 | - Exercises 18 | 19 | ## `this` Keyword 20 | 21 | Over and over again I see engineers struggling with `this` topic; it's so weird!! Long ago I found myself in the same situation, like, writing code for many years and still ... never took the time to really understand `this` when `this` is one of the most important and powerful features in JavaScript! 22 | As engineers, we feel so frustrated about `this` that there's even a joke for `this`! 23 | 24 | > JavaScript makes me want to flip the table and say "F*** this shit", but I can never be sure what **`this`** refers to. 25 | 26 | Things got better when I took the responsibility of `this` and accepted that the blame was entirely mine. 27 | 28 | Why this intro? because there are tons of articles regarding `this` but everything about `this` was written by **Kyle Simpson** who dedicated a whole book for `this` topic , so we're gonna read and study it until we breathe `this`. 29 | 30 | ### Resolving `this` 31 | 32 | Let's take a look at the following chapters of **You Don't Know JS: this & Object Prototypes - 1st Edition** 33 | 34 | - [Chapter 1: this Or That?](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch1.md) 35 | - [Chapter 2: this All Makes Sense Now!](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch2.md) 36 | - [Chapter 5: Prototypes](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch5.md) 37 | - [Chapter 6: Behavior Delegation](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/ch6.md) 38 | 39 | Now let's see how ECMAScript specifies the mechanism to resolve `this`. 40 | 41 | - [GetThisEnvironment ( )](https://www.ecma-international.org/ecma-262/6.0/#sec-getthisenvironment) 42 | - [ResolveThisBinding ( )](https://www.ecma-international.org/ecma-262/6.0/#sec-resolvethisbinding) 43 | 44 | In the other hand, MDN describes `this` on the Operators section 45 | 46 | - [MDN - *this*](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) 47 | 48 | ### Explicitly binding `this` through prototype methods 49 | 50 | Now we've learned that `this` has specific rules and it's resolved at run-time, and we saw that the `function` prototype has 3 methods to explicitly define where to point when `this` needs to be resolved during it's execution. 51 | 52 | - [Function.prototype.bind()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) 53 | - [Function.prototype.apply()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) 54 | - [Function.prototype.call()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call) 55 | 56 | Now, there's a catch!!! it seems that depending on a thing called **mode**, that depending on its [strictness](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) or [non-strictness](https://developer.mozilla.org/en-US/docs/Glossary/Sloppy_mode) (a.k.a. Sloppy) will alter the semantics and behavior of many things including `this`. 57 | 58 | --- 59 | 60 | ## Strict Mode 61 | 62 | - [MDN - Strict Mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) 63 | - [MDN - Transitioning to Strict Mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode/Transitioning_to_strict_mode) 64 | - [ECMAScript 5.1 - Strict Mode](http://www.ecma-international.org/ecma-262/5.1/#sec-10.1.1) 65 | [ECMAScript 2015 - Strict Mode](http://www.ecma-international.org/ecma-262/6.0/#sec-strict-mode-code) 66 | - [The ECMAScript 2016 change you probably don't know](https://humanwhocodes.com/blog/2016/10/the-ecmascript-2016-change-you-probably-dont-know/) 67 | - [Speaking JavaScript - Chp.7 Strict Mode" - by Dr. Axel Rauschmayer](http://speakingjs.com/es5/ch07.html#strict_mode) 68 | 69 | ### What happens on strict mode? 70 | 71 | #### TL;DR 72 | 73 | 1. Eliminates some JavaScript `silent errors` by changing them `to throw errors`. 74 | 2. Fixes mistakes that make it difficult for JavaScript engines to perform optimizations: strict mode code can sometimes be made to run faster than identical code that's not in strict mode. 75 | 3. Prohibits some syntax likely from be defined in future versions of ECMAScript. 76 | 77 | ### Semantic differences 78 | 79 | - `this` resolution won't propagate to the global scope, thus for a strict mode function, the specified this is not boxed into an object, and if unspecified, this will be `undefined` 80 | - arguments doesn't alias named function arguments 81 | - `eval` doesn't create a new variable in the scope from which it was called, `eval` of strict mode code does not introduce new variables into the surrounding scope. 82 | 83 | When adding `'use strict';` the following cases will throw an Error: 84 | 85 | - SyntaxError 86 | - Octal syntax `var n = 023;` 87 | - `with` statement 88 | - Using delete on a variable name `delete myVariable`; 89 | - Using `eval` or `arguments` as variable or function argument name 90 | - Using one of the newly reserved keywords (in prevision for ECMAScript 2015): 91 | - `implements`, 92 | - `interface`, 93 | - `let`, 94 | - `package`, 95 | - `private`, 96 | - `protected`, 97 | - `public`, 98 | - `static`, 99 | - and `yield` 100 | - Escape characters are not allowed `var y = \010;` 101 | - Declaring function in blocks `if (a < b) { function f() {} }` 102 | - Obvious errors 103 | - Declaring the same name twice for a property name in an object literal `{a: 1, b: 3, a: 7}` This is no longer the case in ECMAScript 2015 (bug 1041128). 104 | - Declaring two function parameters with the same name function `f(a, b, b) {}` 105 | - TypeError 106 | - Writing to a get-only property is not allowed 107 | - Writing to a read-only property is not allowed 108 | - Deleting an undeletable property is not allowed `delete Object.prototype` 109 | - Setting properties on primitive values `false.true = '';` , `(14).sailing = 'home';` , `'with'.you = 'far away';` 110 | - Runtime errors 111 | - Setting a value to an undeclared variable 112 | - Trying to delete a non-configurable property 113 | - Poisoned arguments and function properties, e.g. accessing `arguments.callee`, `arguments.caller`, `anyFunction.caller`, or `anyFunction.arguments` 114 | - ReferenceError 115 | - Using a variable, without declaring it 116 | 117 | --- 118 | 119 | ## Arrow Functions 120 | 121 | > An arrow function expression is a syntactically compact alternative to a regular function expression, although without its own bindings to the this, arguments, super, or new.target keywords. Arrow function expressions are ill suited as methods, and they cannot be used as constructors. 122 | > 123 | > Source: [MDN - Arrow Functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) 124 | 125 | ### Syntax 126 | 127 | ```javascript 128 | (param1, param2, …, paramN) => { statements } 129 | (param1, param2, …, paramN) => expression 130 | // equivalent to: => { return expression; } 131 | 132 | // Parentheses are optional when there's only one parameter name: 133 | (singleParam) => { statements } 134 | singleParam => { statements } 135 | 136 | // The parameter list for a function with no parameters should be written with a pair of parentheses. 137 | () => { statements } 138 | 139 | // Parenthesize the body of a function to return an object literal expression: 140 | params => ({foo: bar}) 141 | 142 | // Rest parameters and default parameters are supported 143 | (param1, param2, ...rest) => { statements } 144 | (param1 = defaultValue1, param2, …, paramN = defaultValueN) => { 145 | statements } 146 | 147 | // Destructuring within the parameter list is also supported 148 | var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c; 149 | f(); // 6 150 | 151 | ``` 152 | 153 | One of the most expected and misused features of ES6 is the Arrow Function. Undoubtedly powerful, it might also derive in a headache if you don't really know how they work and what the differences are between the full body notation and the arrow notation. 154 | 155 | Let's take a look at [YDKJS - ES6 & Beyond - chapter 2](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch2.md#arrow-functions) 156 | 157 | --- 158 | 159 | ## Generators 160 | 161 | So far we've seen (except for the iterators) only **[run-to-completion](https://en.wikipedia.org/wiki/Run_to_completion_scheduling)** examples of code. It means, "the execution won't stop until it's done or fails". 162 | What if I tell you there's a feature that lets you define a function capable of being paused midway and resumed later? 163 | 164 | Together with [`iterators`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol) ES6 introduced something called `generators`. 165 | 166 | > The Generator object is returned by a [generator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) and it conforms to both the [iterable protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterable_protocol) and the [iterator protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol). 167 | 168 | There are 2 ways to create a [generator object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator) 169 | 170 | - [function* expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) 171 | 172 | ```javascript 173 | function* name([param[, param[, ... param]]]) { 174 | statements 175 | } 176 | ``` 177 | 178 | - [GeneratorFunction constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/GeneratorFunction) 179 | 180 | ```javascript 181 | let GeneratorFunction = Object.getPrototypeOf(function*(){}).constructor 182 | let myGenerator = new GeneratorFunction ([arg1[, arg2[, ...argN]],] functionBody) 183 | ``` 184 | 185 | > **Note** that GeneratorFunction is **not a global object**. 186 | > 187 | > `generator` function objects created with the `GeneratorFunction` constructor are parsed when the function is created. This is less efficient than declaring a generator function with a `function* expression` and calling it within your code, because such functions are parsed with the rest of the code. 188 | > 189 | > Source: [MDN GeneratorFunction](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/GeneratorFunction) 190 | 191 | Since this is a particularly complex topic, with several nuances, let's try to understand them through examples: 192 | 193 | ### Example of execution sequence 194 | 195 | ```javascript 196 | /** 197 | * 198 | * @param {number} initialValue 199 | * @returns {Object} Generator 200 | */ 201 | function* bottlesOfBeer (initialValue) { 202 | let bob = initialValue; 203 | let lastMessage = `No more bottles of beer on the wall, no more bottles of beer. 204 | Go to the store and buy some more, ${bob} bottles of beer on the wall.`; 205 | 206 | while (true) { 207 | console.log(`${bob} bottles of beer on the wall, ${bob} bottles of beer.`); 208 | 209 | yield bob--; 210 | 211 | console.log(`Take one down and pass it around, ${bob} bottles of beer on the wall.`); 212 | 213 | if (bob < 1) { 214 | bob = initialValue; 215 | console.log(lastMessage); 216 | } 217 | } 218 | } 219 | 220 | let bob = bottlesOfBeer(100); 221 | 222 | bob.next(); 223 | // log -> 5 bottles of beer on the wall, 5 bottles of beer. 224 | // statement completion value -> {value: 5, done: false} 225 | 226 | bob.next(); 227 | // log -> Take one down and pass it around, 4 bottles of beer on the wall. 228 | // 4 bottles of beer on the wall, 4 bottles of beer. 229 | // statement completion value -> {value: 4, done: false} 230 | 231 | // ... 3 more calls 232 | 233 | bob.next(); 234 | // log -> Take one down and pass it around, 0 bottles of beer on the wall. 235 | // No more bottles of beer on the wall, no more bottles of beer. 236 | // Go to the store and buy some more, 5 bottles of beer on the wall. 237 | // 5 bottles of beer on the wall, 5 bottles of beer. 238 | // statement completion value -> {value: 5, done: false} 239 | 240 | // guess what happens now? 241 | 242 | ``` 243 | 244 | ### Passing values through `next` 245 | 246 | ```javascript 247 | /** 248 | * 249 | * @returns {Object} Generator 250 | */ 251 | function* passingValToNext () { 252 | let val = 10; 253 | 254 | while (true) { 255 | console.log(`UP val=${val}`); 256 | 257 | val = yield val + 10; 258 | 259 | console.log(`DOWN val=${val}`); 260 | } 261 | } 262 | 263 | let pvtn = passingValToNext(); 264 | // statement completion value -> passingValToNext {} 265 | 266 | pvtn.next(2); 267 | // log -> UP val=10 268 | // statement completion value -> {value: 20, done: false} 269 | 270 | pvtn.next(7); 271 | // log -> DOWN val=7 272 | // log -> UP val=7 273 | // statement completion value -> {value: 17, done: false} 274 | 275 | // WAIT! WHAT??!!!! 276 | // how does it work? 277 | 278 | ``` 279 | 280 | ### Sample combining initial value and passing value to next 281 | 282 | ```javascript 283 | /** 284 | * 285 | * @param {Number} expectedTotal 286 | * @returns {Object} Generator 287 | */ 288 | function* calculateDownloadProgress (expectedTotal) { 289 | let totalDownloaded = 0; 290 | let newItems = 0; 291 | 292 | while (true) { 293 | totalDownloaded += newItems || 0; // lazy verification for the value passed by `next` 294 | 295 | let percent = ((totalDownloaded / expectedTotal) * 100).toFixed(2); 296 | 297 | newItems = yield `${percent}%`; 298 | } 299 | } 300 | 301 | let progress = calculateDownloadProgress(1024); 302 | // statement completion value -> undefined 303 | progress.next() 304 | // statement completion value -> {value: "0.00%", done: false} 305 | progress.next(15) 306 | // statement completion value -> {value: "1.46%", done: false} 307 | progress.next(500) 308 | // statement completion value -> {value: "50.29%", done: false} 309 | ``` 310 | 311 | ### DIY 312 | 313 | ```javascript 314 | /** 315 | * 316 | * @returns {Object} Generator 317 | */ 318 | function* spinGen() { 319 | while(true){ 320 | yield* ['\\', '|', '/', '--']; 321 | } 322 | } 323 | 324 | // now you add the code to see the output 325 | ``` 326 | 327 | Let's take some time to read and discuss: 328 | 329 | - [ECMAScript Generator Function](https://www.ecma-international.org/ecma-262/6.0/#sec-generatorfunction) 330 | - [YDKJS - ES6 & Beyond - CH3 - Generators](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch3.md#generators) - by Kyle Simpson 331 | - [The Basics Of ES6 Generators](https://davidwalsh.name/es6-generators) - By Kyle Simpson 332 | - [2ality - ES6 generators in depth](https://2ality.com/2015/03/es6-generators.html) - by Dr. Axel Rauschmayer 333 | 334 | --- 335 | 336 | ## Exercises 337 | 338 | Let's open our test files: 339 | 340 | - [this](/src/day_07/this.test.js) 341 | - [arrow functions](/src/day_07/arrowFunctions.test.js) 342 | - [generators](/src/day_07/generators.test.js) 343 | 344 | Now open your terminal. 345 | 346 | 1. Make sure you're at the project location 347 | 2. If you didn't install all the packages yet then run `npm i` for a fresh dependency install, or `npm ci` for an installation based on the lock file. 348 | 3. Type `npm run test:watch`, this will start running your tests every time you make a change. 349 | 350 | **Our task is to make ALL our DAY 7 tests pass ;)** 351 | 352 | *** 353 | [Go back to DAY 6](/day_06.md) or [Go next to DAY 8](/day_08.md) 354 | *** 355 | [Back to main page](https://github.com/thinkb4/a-walk-in-javascript/tree/master#day-7) -------------------------------------------------------------------------------- /day_08.md: -------------------------------------------------------------------------------- 1 | # [A walk in JavaScript](/README.md) 2 | 3 | ## DAY 8 4 | 5 | - Classes 6 | - General definition 7 | - Syntax 8 | - `class` declaration statement 9 | - `class` expression 10 | - Class body and method definitions 11 | - ES6 Classes in depth 12 | - OOP vs Functional 13 | - General definitions 14 | - Some essential differences 15 | - Examples 16 | - Exercises 17 | 18 | ## Classes 19 | 20 | ### General definition 21 | 22 | Let's start from the definition: 23 | 24 | > JavaScript classes, introduced in ECMAScript 2015, are primarily **syntactical sugar** over JavaScript's existing **prototype-based** inheritance. The class **syntax does not introduce a new object-oriented inheritance model** to JavaScript. 25 | > 26 | > Source: [MDN - Classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) 27 | 28 | (-‸ლ) ok, so, the name is `class` but it seems they're not classes. Let's continue. 29 | 30 | > Classes are in fact "special [functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions)", and just as you can define [function expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function) and [function declarations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function), the class syntax has two components: [class expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/class) and [class declarations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/class). 31 | > 32 | > Source: [MDN - Classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) 33 | 34 | (-‸ლ) (-‸ლ) now I'm confused ...so ... they're not [classes](https://en.wikipedia.org/wiki/Class_(computer_programming)) so technically it's NOT a [class-based](https://en.wikipedia.org/wiki/Class-based_programming) language BUT you CAN do [OOP](https://en.wikipedia.org/wiki/Object-oriented_programming) ... so what in the world are they and what's the use? 35 | 36 | Please don't give up. Despite the "unhappy" and misleading naming, they are a very useful and powerful abstraction around repetitive and error prone routines to create `prototype` based inheritance structures. 37 | 38 | This time, ECMAScript international isn't very friendly with this: 39 | 40 | - [Class Definitions](https://www.ecma-international.org/ecma-262/6.0/#sec-class-definitions) 41 | - [Functions and Classes](https://www.ecma-international.org/ecma-262/6.0/#sec-functions-and-classes) 42 | - [MakeClassConstructor](https://www.ecma-international.org/ecma-262/6.0/#sec-makeclassconstructor) 43 | 44 | So let's borrow some info from MDN. 45 | 46 | ### Syntax 47 | 48 | #### `class` declaration statement 49 | 50 | > The class body of a class declaration is executed in [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode). The constructor property is optional. 51 | > 52 | > Class declarations are not hoisted (unlike [function declarations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)). 53 | > 54 | > Source: [MDN - class declaration statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/class) 55 | 56 | ```javascript 57 | 58 | class name [extends] { 59 | // class body 60 | } 61 | ``` 62 | 63 | #### `class` expression 64 | 65 | > The class expression is one way to define a class in ECMAScript 2015. Similar to [function expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function), class expressions can be named or unnamed. If named, the name of the class is local to the class body only. JavaScript classes use prototype-based inheritance. 66 | > 67 | > Source: [MDN - class expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/class) 68 | 69 | ```javascript 70 | var MyClass = class [className] [extends] { 71 | // class body 72 | }; 73 | ``` 74 | 75 | #### Class body and method definitions 76 | 77 | > The body of a class is the part that is in curly brackets {}. This is where you define class members, such as methods or constructor. 78 | > 79 | > Let's see more at [MDN - Classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) 80 | 81 | ### ES6 Classes in depth 82 | 83 | So far we've had a reasonable amount of information to shallowly understand JavaScript Classes, but I wanna push you a little further. 84 | 85 | Again I'll ask Kyle Simpson's book to help me. Please go to [YDKJS: this & Object Prototypes - Appendix A: ES6 class](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/this%20%26%20object%20prototypes/apA.md) 86 | 87 | At this point we should be wise enough to start with the next step. 88 | 89 | ## OOP vs Functional programming 90 | 91 | First of all I'd love to de-mystify something, there's not such a thing like a better paradigm. Both are powerful and both have their pros/cons depending on where and how they're used. Like a hammer and a screw-driver they're just tools, not more nor less. And they're incredible. Learn them, study them so you can make a better use of your creativity and your resources. 92 | 93 | ### General definitions 94 | 95 | #### Functional Programming 96 | 97 | > In computer science, functional programming is a programming paradigm—a style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. It is a declarative programming paradigm in that programming is done with expressions or declarations instead of statements. In functional code, the output value of a function depends only on its arguments, so calling a function with the same value for an argument always produces the same result. This is in contrast to imperative programming where, in addition to a function's arguments, global program state can affect a function's resulting value. Eliminating side effects, that is, changes in state that do not depend on the function inputs, can make understanding a program easier, which is one of the key motivations for the development of functional programming. 98 | > 99 | > Source: [Wikipedia - Functional Programming](https://en.wikipedia.org/wiki/Functional_programming) 100 | 101 | #### Object-oriented programming (OOP) 102 | 103 | > Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which can contain data, in the form of fields (often known as attributes or properties), and code, in the form of procedures (often known as methods). A feature of objects is an object's procedures that can access and often modify the data fields of the object with which they are associated (objects have a notion of "this" or "self"). In OOP, computer programs are designed by making them out of objects that interact with one another. OOP languages are diverse, but the most popular ones are class-based, meaning that objects are instances of classes, which also determine their types. 104 | > 105 | > Source: [Wikipedia - Object-oriented Programming](https://en.wikipedia.org/wiki/Object-oriented_programming) 106 | 107 | ### Some essential differences 108 | 109 | #### Functional 110 | 111 | - [High Order Functions (HOF)](https://en.wikipedia.org/wiki/Higher-order_function) 112 | - [Pure functions](https://en.wikipedia.org/wiki/Pure_function) 113 | - [Strict](https://en.wikipedia.org/wiki/Eager_evaluation) and [Lazy Evaluation](https://en.wikipedia.org/wiki/Lazy_evaluation) 114 | - [Referential Transparency](https://en.wikipedia.org/wiki/Referential_transparency) 115 | - [Recursion](https://en.wikipedia.org/wiki/Recursion_(computer_science)) over [iteration](https://en.wikipedia.org/wiki/Iteration#Computing) 116 | - [Declarative](https://en.wikipedia.org/wiki/Declarative_programming) over [imperative](https://en.wikipedia.org/wiki/Imperative_programming) programming paradigm 117 | - [Immutable](https://en.wikipedia.org/wiki/Immutable_object) over mutable data structures 118 | - [Stateless](https://en.wikipedia.org/wiki/State_(computer_science)#Program_state) 119 | - [Deterministic](https://en.wikipedia.org/wiki/Deterministic_algorithm) 120 | 121 | #### OOP 122 | 123 | - [Abstraction](https://en.wikipedia.org/wiki/Abstraction_(computer_science)#Abstraction_in_object_oriented_programming) 124 | - [Inheritance](https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)) 125 | - [Polymorphism](https://en.wikipedia.org/wiki/Polymorphism_(computer_science)) 126 | - [Encapsulation](https://en.wikipedia.org/wiki/Encapsulation_(computer_programming)) 127 | - Iteration over recursion 128 | - Imperative over declarative programming paradigm 129 | - Mutable over immutable data structures 130 | - [Stateful](https://en.wikipedia.org/wiki/State_(computer_science)#Program_state) 131 | - [Nondeterministic](https://en.wikipedia.org/wiki/Nondeterministic_algorithm) 132 | 133 | #### Examples 134 | 135 | Let's see this oversimplified example and discuss it. 136 | 137 | ```javascript 138 | /** 139 | * OOP 140 | */ 141 | class Plant { 142 | 143 | /** 144 | * @param {number} flowers 145 | */ 146 | constructor (flowers = 0) { this.flowers = flowers; } 147 | 148 | /** 149 | * @returns {number} 150 | */ 151 | addFlower () { return ++this.flowers; } 152 | 153 | } 154 | 155 | let myPlants = [ 156 | new Plant(1), 157 | new Plant(), 158 | new Plant(7), 159 | new Plant(9) 160 | ]; 161 | 162 | for (let plant of myPlants) { 163 | plant.addFlower(); 164 | } 165 | 166 | ``` 167 | 168 | ```javascript 169 | /// FP 170 | let myPlants = [ 1, 0, 7, 9 ]; 171 | 172 | let plantsWithMoreFlowers = myPlants.map(flower => ++flower); 173 | ``` 174 | 175 | ## Exercises 176 | 177 | Let's open our test files: 178 | 179 | - [Classes](/src/day_08/classes.test.js) 180 | 181 | Now open your terminal. 182 | 183 | 1. Make sure you're at the project location 184 | 2. If you didn't install all the packages yet the run `npm i` for a fresh dependency install, or `npm ci` for an installation based on the lock file. 185 | 3. Type `npm run test:watch`, this will start running your tests every time you make a change. 186 | 187 | **Our task is to make ALL our DAY 8 tests pass ;)** 188 | 189 | *** 190 | [Go back to DAY 7](/day_07.md) or [Go next to DAY 9](/day_09.md) 191 | *** 192 | [Back to main page](https://github.com/thinkb4/a-walk-in-javascript/tree/master#day-8) -------------------------------------------------------------------------------- /day_09.md: -------------------------------------------------------------------------------- 1 | # [A walk in JavaScript](/README.md) 2 | 3 | ## DAY 9 4 | 5 | - Asynchronous programming 6 | - Event Loop 7 | - Callback 8 | - Promises 9 | - Async/Await 10 | - Exercises 11 | 12 | ## Asynchronous programming 13 | 14 | Until ES6 (we'll get into that later, but we already saw a glimpse of that with Generators) there was nothing in the JS core specifying asynchronism, it had a fire-heated mark with the words "run-to-completion". In fact all asynchronous behavior depended on the host environment providing some kind of API in order to handle the asynchronism on its side and communicate to the JavaScript engine the outcome if necessary. 15 | 16 | For example, you will find references and definitions of **timers** on the MDN documentation for [WindowOrWorkerGlobalScope](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope) describing them in the context of a browser host environment but if you make a search of **timer** or **timeout** in the [ES6](https://www.ecma-international.org/ecma-262/6.0/) spec you'll find ... absolutely nothing! So what does it mean? Plain a simple, it means **JavaScript has no notion of timers**, the host does, and as we discussed in previous chapters, a web browser is not the only host for JavaScript, it's just one of many AND most likely this very environment host doesn't even have the code to perform the asynchronism, it acts just as a bridge to their own host which might happen to be an operative system!!!! 17 | 18 | ### Event Loop 19 | 20 | One of this mechanisms to asynchronism is the **event-loop**, but what's that? 21 | 22 | #### General definition 23 | 24 | > In computer science, the **event loop**, **message dispatcher**, **message loop**, **message pump**, or **run loop** is a programming construct that waits for and dispatches [events](https://en.wikipedia.org/wiki/Event-driven_programming) or [messages](https://en.wikipedia.org/wiki/Message_Passing_Interface) in a [program](https://en.wikipedia.org/wiki/Computer_program). It works by making a request to some internal or external "event provider" (that generally [blocks](https://en.wikipedia.org/wiki/Blocking_(computing)) the request until an event has arrived), and then it calls the relevant [event handler](https://en.wikipedia.org/wiki/Event_handler) ("dispatches the event"). 25 | > 26 | > Source: [Wikipedia - Event loop](https://en.wikipedia.org/wiki/Event_loop) 27 | 28 | That was too dry, wasn't it? 29 | 30 | Let's try with MDN. 31 | 32 | > A JavaScript runtime uses a message queue, which is a list of messages to be processed. Each message has an associated function which gets called in order to handle the message. 33 | > 34 | > At some point during the event loop, the runtime starts handling the messages on the queue, starting with the oldest one. To do so, the message is removed from the queue and its corresponding function is called with the message as an input parameter. As always, calling a function creates a new stack frame for that function's use. 35 | > 36 | > The processing of functions continues until the stack is once again empty; then the event loop will process the next message in the queue (if there is one). 37 | > 38 | > Source: [MDN - Event Loop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop) 39 | 40 | Ok that's better but still ... dry-ish. 41 | 42 | Thankfully we have two invaluable resources to finally understand the event loop 43 | 44 | - [What the heck is the event loop anyway?](https://www.youtube.com/watch?v=8aGhZQkoFbQ) | Philip Roberts | JSConf EU 45 | - [YDKJS - Async & Performance - Chapter 1: Asynchrony: Now & Later](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/async%20%26%20performance/ch1.md) | Kyle Simpson 46 | - [What you should know to really understand the Node.js Event Loop](https://medium.com/the-node-js-collection/what-you-should-know-to-really-understand-the-node-js-event-loop-and-its-metrics-c4907b19da4c) | Daniel Khan 47 | 48 | --- 49 | 50 | ### Callback 51 | 52 | > A callback function is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action. 53 | > 54 | > Here is a quick example: 55 | > 56 | >```javascript 57 | > function greeting(name) { 58 | > alert('Hello ' + name); 59 | >} 60 | > 61 | >function processUserInput(callback) { 62 | > var name = prompt('Please enter your name.'); 63 | > callback(name); 64 | >} 65 | > 66 | >processUserInput(greeting); 67 | >``` 68 | > 69 | > The above example is a synchronous callback, as it is executed immediately. 70 | > 71 | > Note, however, that callbacks are often used to continue code execution after an asynchronous operation has completed — these are called asynchronous callbacks. A good example is the callback functions executed inside a .then() block chained onto the end of a promise after that promise fulfills or rejects. This structure is used in many modern web APIs, such as fetch(). 72 | > 73 | > Source: [MDN - Callback Function](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function) 74 | 75 | Let's take a look at a [general definition of callback on Wikipedia](https://en.wikipedia.org/wiki/Callback_(computer_programming)) 76 | 77 | Here is a simplified example of callback you might have used but now you'll understand more about what it is doing. 78 | 79 | ```javascript 80 | setTimeout( () => console.log(`I'm running late...er`), 1000 ); 81 | ``` 82 | 83 | Can you describe, in your own words like a bedtime story, what's happening with that code? Need a help with that? Let's move on and take a final step into this with [YDKJS - Async & Performance - Callbacks](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/async%20%26%20performance/ch2.md) | by Kyle Simpson 84 | 85 | --- 86 | 87 | ### Promises 88 | 89 | Let's imagine we need to perform a task, we don't know how much it's gonna take but we need both make sure to do something whilst it's done AND in the meantime do something else AND have a complete control over the outcomes to prevent weird things happening. 90 | 91 | If we do that with callbacks we'll end up in hell, actually there's a name for that, [callback hell](https://en.wiktionary.org/wiki/callback_hell), and there's even a [website](http://callbackhell.com/) with that name! 92 | 93 | Let's make and example. 94 | 95 | ```javascript 96 | 97 | setTimeout( () => { 98 | console.log(`A`); 99 | setTimeout( () => { 100 | console.log(`B`); 101 | setTimeout( () => { 102 | console.log(`C`); 103 | setTimeout( () => { 104 | console.log(`D`); 105 | }, 1000 ); 106 | }, 100 ); 107 | }, 0 ); 108 | }, 5000 ); 109 | 110 | ``` 111 | 112 | After a few moments thinking about it you might say "that's easy", I won't get into the "using `console`" implications, but let's imagine that you need `B` to happen only if `A` is successful, AND `C` AND `D` should happen either way. Now our code starts looking not only hard to read but also hard to maintain, which is the doorway to a tsunami of bugs swarming to you. 113 | 114 | So, what's a promise? why it might help here? 115 | 116 | Imagine this: 117 | > I'm an Object, and once you give me a specific task I PROMISE YOU I'll let you know when I did it, telling whether I SUCCEEDED or FAILED providing you the summary (outcome) so you can use it, THEN you can do something with that info if I SUCCEEDED OR alternatively do something else with my FAILURE. FINALLY you might want to do something either way. 118 | 119 | That's something you are used to do with other people, isn't it? 120 | 121 | #### Syntax 122 | 123 | ```javascript 124 | new Promise(executor); 125 | // or 126 | new Promise((resolve, reject) => { 127 | executor body 128 | }); 129 | ``` 130 | 131 | Well, Promises work kinda that. 132 | 133 | ```javascript 134 | new Promise((resolve, reject) => { 135 | console.log('I started'); 136 | resolve(); 137 | }) 138 | .then(() => { 139 | console.log(`A`); 140 | throw new Error('I failed in A'); 141 | }) 142 | .then(() => { 143 | console.log(`B`); 144 | }) 145 | .catch((reason) => { 146 | console.log(reason); 147 | }) 148 | .finally(() => { 149 | console.log(`C`); 150 | console.log(`D`); 151 | }); 152 | 153 | ``` 154 | 155 | Easy to read, easy to control ... sort of, but definitely better than callback hell. 156 | 157 | Too much talking, let go to the best sources you can get. 158 | 159 | - [ECMAScript Promise Objects](https://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects) 160 | - [ECMAScript Promise Constructor](https://www.ecma-international.org/ecma-262/6.0/#sec-promise-constructor) 161 | - [MDN - Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) 162 | - [MDN - Using Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) 163 | - [YDKJS - Async & Performance - Chapter 3: Promises](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/async%20%26%20performance/ch3.md) | by Kyle Simpson 164 | 165 | --- 166 | 167 | ### Async/await 168 | 169 | Wait, what? We were talking about ES2015 but this is not an ES2015 feature, nor ES2016!! We had to wait until ES2017 (ES8?? nope, remember that's not the way to name ES versions anymore) to have it. 170 | Then why are we talking about this? Simply because is one of the most important tools (together with generators and promises) to write asynchronous programs in JavaScript today. 171 | 172 | Imagine there's a feature to handle under the hood the event loop and the promises to **operate asynchronously BUT resembles synchronous** code on its syntax. Since many program errors are originated on the difficulty of understanding a complex structure (e.g. like a promise chain) this feature might help with that, isn't it? 173 | 174 | First things first. If we go to the [ECMA2017 - 9.2 - ECMAScript Function Objects definition](https://www.ecma-international.org/ecma-262/8.0/index.html#sec-ecmascript-function-objects) we'll find that `async` is one of the 4 kinds of functions `normal`, `classConstructor` , `generator` and `async`, and if you search "async" there list of results is around 450. There's a lot to read there if you want to; I'd suggest you start reading the [14.6 - Async Function Definition](https://www.ecma-international.org/ecma-262/8.0/index.html#sec-async-function-definitions) first. 175 | 176 | Again, even if the spec gets more sweet and friendly over time, it's still dry (but it'd be IMHO the first thing to read). 177 | 178 | Let's go for something more friendly. 179 | 180 | #### Async Function declaration statement 181 | 182 | > The async function declaration defines an asynchronous function, which returns an [AsyncFunction](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncFunction) object. An asynchronous function is a function which operates asynchronously via the event loop, using an implicit [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) to return its result. But the syntax and structure of your code using async functions is much more like using standard synchronous functions. 183 | > 184 | > You can also define async functions using an [async function expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/async_function). 185 | > 186 | > Source: [MDN: Async Function declaration statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) 187 | 188 | ##### Syntax 189 | 190 | ```javascript 191 | async function name([param[, param[, ... param]]]) { 192 | statements 193 | } 194 | ``` 195 | 196 | #### Async Function expression 197 | 198 | > An async function expression is very similar to, and has almost the same syntax as, an async function statement. The main difference between an async function expression and an async function statement is the function name, which can be omitted in async function expressions to create anonymous functions. An async function expression can be used as an IIFE (Immediately Invoked Function Expression) which runs as soon as it is defined. See also the chapter about functions for more information. 199 | > 200 | > Source: [MDN - async function expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/async_function) 201 | 202 | ##### Syntax 203 | 204 | ```javascript 205 | async function [name]([param1[, param2[, ..., paramN]]]) { 206 | statements 207 | } 208 | ``` 209 | 210 | #### Async Function constructor 211 | 212 | > async function objects created with the AsyncFunction constructor are parsed when the function is created. This is less efficient than declaring an async function with an async function expression and calling it within your code, because such functions are parsed with the rest of the code. 213 | > 214 | All arguments passed to the function are treated as the names of the identifiers of the parameters in the function to be created, in the order in which they are passed. 215 | > 216 | Invoking the AsyncFunction constructor as a function (without using the new operator) has the same effect as invoking it as a constructor. 217 | > 218 | > Source: [MDN - AsyncFunction constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncFunction) 219 | 220 | ##### Syntax 221 | 222 | Note that AsyncFunction is not a global object. It could be obtained by evaluating the following code. 223 | 224 | ```javascript 225 | var AsyncFunction = Object.getPrototypeOf(async function(){}).constructor 226 | 227 | new AsyncFunction([arg1[, arg2[, ...argN]],] functionBody); 228 | ``` 229 | 230 | #### Await 231 | 232 | > The `await` expression causes `async` function execution to pause until a `Promise` is settled, that is fulfilled or rejected, and to resume execution of the async function after fulfillment. When resumed, the value of the `await` expression is that of the fulfilled `Promise`. 233 | > 234 | > If the `Promise` is rejected, the `await` expression throws the rejected value. 235 | > 236 | > If the value of the expression following the `await` operator is not a `Promise`, it's converted to a [resolved Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve). 237 | > 238 | > An await can split execution flow, allowing the caller of the `await`'s function to resume execution before the deferred continuation of the `await`'s function. After the `await` defers the continuation of its function, if this is the first await executed by the function, immediate execution also continues by returning to the function's caller a pending `Promise` for the completion of the `await`'s function and resuming execution of that caller. 239 | > 240 | > Source: [MDN - await operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await) 241 | 242 | ##### Syntax 243 | 244 | ```javascript 245 | [rv] = await expression; 246 | ``` 247 | 248 | --- 249 | 250 | ## Exercises 251 | 252 | Let's open our test files: 253 | 254 | - [event loop](/src/day_09/eventLoop.test.js) 255 | - [callback](/src/day_09/callback.test.js) 256 | - [promise](/src/day_09/promise.test.js) 257 | - [async/await](/src/day_09/asyncAwait.test.js) 258 | 259 | Now open your terminal. 260 | 261 | 1. Make sure you're at the project location 262 | 2. If you didn't install all the packages yet then run `npm i` for a fresh dependency install, or `npm ci` for an installation based on the lock file. 263 | 3. Type `npm run test:watch`, this will start running your tests every time you make a change. 264 | 265 | **Our task is to make ALL our DAY 9 tests pass ;)** 266 | 267 | *** 268 | [Go back to DAY 8](/day_08.md) or [Go next to DAY 10](/day_10.md) 269 | *** 270 | [Back to main page](https://github.com/thinkb4/a-walk-in-javascript/tree/master#day-9) -------------------------------------------------------------------------------- /day_10.md: -------------------------------------------------------------------------------- 1 | # [A walk in JavaScript](/README.md) 2 | 3 | ## DAY 10 4 | 5 | - JavaScript, where does it live? 6 | - The ECMAScript Engine 7 | - What does the engine actually do? 8 | - Visual guide based on V8 9 | - How many of them are there? 10 | - Engines Differences 11 | - The ECMAScript runtime 12 | - Runtimes Differences 13 | - Similarities 14 | - Javascript and the web 15 | - HTML 16 | - CSS 17 | - TL;DR 18 | - Complementary readings 19 | 20 | ## JavaScript, where does it live? 21 | 22 | During this walk we mentioned several times a set of concepts related to JavaScript (but not only) that we'll explore a little deeper today. 23 | 24 | - ECMA International 25 | - ECMAScript 26 | - ECMA-262 27 | - JavaScript 28 | - JavaScript engine 29 | - JavaScript Runtime 30 | 31 | Let's remember what are they. 32 | 33 | **ECMA International** is an organization dedicated to defining and maintaining technology standards, one of the standards is **ECMAScript** identified as **ECMA-262** which specifies the rules, details and guidelines so you can create a programming language in **compliance to the ECMAScript standard**. 34 | 35 | **JavaScript** is one of these languages (one of many) and even though historically it was created before the standard, today it follows it. 36 | In order to be interpreted and executed, a programming language might need an **engine**, JavaScript is one of these cases but all ECMAScript compliant languages will need an engine; and this statement will generally apply to the **ECMAScript engine** itself, which will require a **Host Environment** as well. 37 | This **Host environment** (a.k.a **ECMAScript Runtime**) will provide to the engine the necessary elements to interact with other systems. 38 | 39 | ## The ECMAScript Engine 40 | 41 | ### What does the engine actually do? 42 | 43 | So what does the engine actually do? (briefly) 44 | 45 | - Once your text file has been loaded, the engine will perform a [lexical analysis](https://en.wikipedia.org/wiki/Lexical_analysis) by reading the sequences of characters and try to convert them into a sequence of meaningful strings ([tokens](https://en.wikipedia.org/wiki/Lexical_analysis#Token)) for the specific language (a.k.a. tokenization). 46 | - Once the lexer successfully identifies those meaningful pieces it's time to perform a [syntactic analysis](https://en.wikipedia.org/wiki/Parsing) (parsing) to make sure the tokens can be related making valid expressions. 47 | - If there are no errors so far, it's time for a [semantic analysis](https://en.wikipedia.org/wiki/Semantic_analysis_(computer_science)). Here a lot of things will happen, essentially to make sure the program can be accurately represented, and the resources of the program such as [types](https://en.wikipedia.org/wiki/Type_checking), [bindings](https://en.wikipedia.org/wiki/Object_binding) and [assignments](https://en.wikipedia.org/wiki/Definite_assignment_analysis) are valid. Additionally it ensures that the [Symbol Table](https://en.wikipedia.org/wiki/Symbol_table) was successfully created and the [intermediate representation](https://en.wikipedia.org/wiki/Intermediate_representation) of the code was generated 48 | - Now what? It's time to convert that IR into something the machine can execute (e.g. [machine code](https://en.wikipedia.org/wiki/Machine_code)). In the modern JavaScript engines (originally introduced by [V8](https://chromium.googlesource.com/v8/v8)) this happens in [runtime](https://en.wikipedia.org/wiki/Run_time_(program_lifecycle_phase)) (during execution) and is known as [JIT](https://en.wikipedia.org/wiki/Just-in-time_compilation) 49 | - Then? Again, pretty much all modern ECMAScript engines, especially JavaScript engines implement some form of optimization (e.g V8's [TurboFan](https://v8.dev/blog/launching-ignition-and-turbofan)) 50 | 51 | #### Visual guide based on V8 52 | 53 | | HEAP (memory allocation) | EXECUTION CONTEXT STACK (call stack) | 54 | | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 55 | | Here the engine stores the memory addresses for compound data ( e.g. objects and object subtypes like functions, arrays). This memory doesn't depend on the execution context and will persist until the Garbage Collector can claim it. - **Garbage Collector (Orinoco)** | The ECS is tied to the function execution. When a function is called, it'll be added to the stack in a LIFO order. It runs synchronously and when its execution has been completed it'll be popped off the stack and the engine will take the next item on the stack. Javascript has only ONE ECS, therefore one thing at a time can be executed. **Interpreters (TurboFan)** - **Optimizers (Ignition)** | 56 | 57 | ### How many of them are there? 58 | 59 | More than 30 60 | 61 | 62 | 63 | Yup, at least that's the list of known implementations but there might be more. Some of them compile to machine code using JIT, some don't, some are new, or old, designed for web browsers or to be embedded. 64 | 65 | You can check a quite long List of [ECMAScript engines in Wikipedia](https://en.wikipedia.org/wiki/List_of_ECMAScript_engines) 66 | 67 | ### Engines Differences 68 | 69 | [Comparison between different JavaScript engines](https://en.wikipedia.org/wiki/Comparison_of_JavaScript_engines). 70 | 71 | ## The ECMAScript runtime 72 | 73 | We said "This Host environment (a.k.a ECMAScript Runtime) will provide to the engine the necessary elements to interact with other systems.", can we have a concrete example? 74 | 75 | Let's try to be simple: 76 | We know two runtimes that share the same engine: V8 is the JavaScript engine for both Chrome and Node.js, the overlapping surface between both runtimes is huge but there are also big differences. See the table below. 77 | 78 | ### Runtimes Differences 79 | 80 | - Chrome 81 | - [Web APIs](https://developer.mozilla.org/en-US/docs/Web/API) (tons of them) 82 | - `window` predefined global object 83 | - `location` global object 84 | - `document` global object 85 | - `import` 86 | - ES6 modules 87 | - Node.js 88 | - headless 89 | - `global`predefined global object 90 | - `require` 91 | - `process` 92 | - CommonJs modules 93 | 94 | ### Similarities 95 | 96 | - Timers 97 | - Event Loop 98 | - Callback Queue 99 | 100 | Why should I care? because even though we're writing JavaScript, depending on the runtime for the same engine, our program might shamefully fail or it could be extremely hard to test. 101 | 102 | Here some more cases of mixed environments differences from [YDKJS: Types & Grammar - Mixed Environment JavaScript](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20&%20grammar/apA.md) by Kyle Simpson. 103 | 104 | ## Javascript and the web 105 | 106 | Despite the fact that JavaScript, today, is much more than a language for the web; it's still one of the heaviest usage of the language, particularly webb applications delivered as "web pages". Therefore is extremely important that you know not only JavaScript but also HTML and CSS (there's an interesting [Roadmap to becoming a web developer in 2019](https://github.com/kamranahmedse/developer-roadmap) written by Kamran Ahmed if you want to read more) 107 | 108 | We won't get deep into them as that's not the scope of this course, but at least we'll review their definitions and some basic features. 109 | 110 | ### HTML 111 | 112 | > **Hypertext Markup Language (HTML)** is the standard [markup language](https://en.wikipedia.org/wiki/Markup_language) for documents designed to be displayed in a [web browser](https://en.wikipedia.org/wiki/Web_browser). It can be assisted by technologies such as [Cascading Style Sheets](https://en.wikipedia.org/wiki/Cascading_Style_Sheets) (CSS) and [scripting languages](https://en.wikipedia.org/wiki/Scripting_language) such as [JavaScript](https://en.wikipedia.org/wiki/JavaScript). 113 | > 114 | > Web browsers receive HTML documents from a [web server](https://en.wikipedia.org/wiki/Web_server) or from local storage and [render](https://en.wikipedia.org/wiki/Browser_engine) the documents into multimedia web pages. HTML describes the structure of a web page [semantically](https://en.wikipedia.org/wiki/Semantic_Web) and originally included cues for the appearance of the document. 115 | > 116 | > [HTML elements](https://en.wikipedia.org/wiki/HTML_element) are the building blocks of HTML pages. With HTML constructs, images and other objects such as [interactive forms](https://en.wikipedia.org/wiki/Fieldset) may be embedded into the rendered page. HTML provides a means to create [structured documents](https://en.wikipedia.org/wiki/Structured_document) by denoting structural semantics for text such as headings, paragraphs, lists, [links](https://en.wikipedia.org/wiki/Hyperlink), quotes and other items. HTML elements are delineated by tags, written using angle brackets. Tags such as `` and `` directly introduce content into the page. Other tags such as `

` surround and provide information about document text and may include other tags as sub-elements. Browsers do not display the HTML tags, but use them to interpret the content of the page. 117 | > 118 | > HTML can embed programs written in a scripting language such as JavaScript, which affects the behavior and content of web pages. Inclusion of CSS defines the look and layout of content. 119 | > 120 | > The **[World Wide Web Consortium](https://en.wikipedia.org/wiki/World_Wide_Web_Consortium) (W3C), former maintainer of the HTML and current maintainer of the CSS standards**, has encouraged the use of CSS over explicit presentational HTML since 1997. 121 | > 122 | > Source: [Wikipedia](https://en.wikipedia.org/wiki/HTML) 123 | 124 | ### CSS 125 | 126 | > **Cascading Style Sheets (CSS)** is a [style sheet language](https://en.wikipedia.org/wiki/Style_sheet_language) used for describing the [presentation](https://en.wikipedia.org/wiki/Presentation_semantics) of a document written in a markup language like HTML. CSS is a cornerstone technology of the [World Wide Web](https://en.wikipedia.org/wiki/World_Wide_Web), alongside HTML and JavaScript. 127 | > 128 | > CSS is designed to enable the separation of presentation and content, including [layout](https://en.wikipedia.org/wiki/Page_layout), [colors](https://en.wikipedia.org/wiki/Color), and [fonts](https://en.wikipedia.org/wiki/Typeface). This separation can improve content [accessibility](https://en.wikipedia.org/wiki/Accessibility), provide more flexibility and control in the specification of presentation characteristics, enable multiple [web pages](https://en.wikipedia.org/wiki/Web_page) to share formatting by specifying the relevant CSS in a separate .css file, and reduce complexity and repetition in the structural content. 129 | > 130 | > Separation of formatting and content also makes it feasible to present the same markup page in different styles for different rendering methods, such as on-screen, in print, by voice (via speech-based browser or [screen reader](https://en.wikipedia.org/wiki/Screen_reader)), and on [Braille-based](https://en.wikipedia.org/wiki/Braille_display) tactile devices. CSS also has rules for alternate formatting if the content is accessed on a [mobile device](https://en.wikipedia.org/wiki/Mobile_device). 131 | > 132 | > The name "cascading" comes from the specified priority scheme to determine which style rule applies if more than one rule matches a particular element. This cascading priority scheme is predictable. 133 | > 134 | > The CSS specifications are maintained by the [World Wide Web Consortium](https://en.wikipedia.org/wiki/World_Wide_Web_Consortium) (W3C). Internet media type ([MIME type](https://en.wikipedia.org/wiki/MIME_media_type)) text/css is registered for use with CSS by [RFC 2318](https://tools.ietf.org/html/rfc2318) (March 1998). The W3C operates a free [CSS validation service](https://en.wikipedia.org/wiki/W3C_Markup_Validation_Service#CSS_validation) for CSS documents. 135 | > 136 | > Source: [Wikipedia](https://en.wikipedia.org/wiki/Cascading_Style_Sheets) 137 | 138 | ## TL;DR 139 | 140 | - **JavaScript Engine:** takes care of the analysis and execution of the code 141 | - **JavaScript Runtime:** takes care of running the JavaScript engine and provides mechanisms for communicating with other systems (e.g. timers, external resources) through specific APIs 142 | - **HTML:** takes care of presenting the information to the browser in a semantic way by delivering a structured document and informing the browser about external resources required for the presentation (e.g. js, css, fonts) 143 | - **CSS:** takes care of defining the structured document (HTML) to cover different presentational (rendering) needs such as visual aspect (e.g desktop vs mobile displays), specific devices (e.g. printers), accessibility (e.g. screen readers, Braille tactile devices) 144 | 145 | ## Complementary readings 146 | 147 | - [The Javascript Runtime Environment](https://medium.com/@olinations/the-javascript-runtime-environment-d58fa2e60dd0) by Jaime Uttariello 148 | - [What’s the difference between JavaScript and ECMAScript?](https://www.freecodecamp.org/news/whats-the-difference-between-javascript-and-ecmascript-cba48c73a2b5/) by Michael Aranda 149 | - [JavaScript Internals: JavaScript engine, Run-time environment & setTimeout Web API](https://blog.bitsrc.io/javascript-internals-javascript-engine-run-time-environment-settimeout-web-api-eeed263b1617) by Rupesh Mishra 150 | - [JavaScript V8 Engine Explained](https://hackernoon.com/javascript-v8-engine-explained-3f940148d4ef) by Kadishay 151 | - [How JavaScript works: inside the V8 engine + 5 tips on how to write optimized code](https://blog.sessionstack.com/how-javascript-works-inside-the-v8-engine-5-tips-on-how-to-write-optimized-code-ac089e62b12e) by Alexander Zlatkov 152 | - [Understanding How the Chrome V8 Engine Translates JavaScript into Machine Code](https://www.freecodecamp.org/news/understanding-the-core-of-nodejs-the-powerful-chrome-v8-engine-79e7eb8af964/) by Mayank Tripathi 153 | 154 | *** 155 | [Go back to DAY 9](/day_09.md) or [Go next to DAY 11](/day_11.md) 156 | *** 157 | [Back to main page](https://github.com/thinkb4/a-walk-in-javascript/tree/master#day-10) -------------------------------------------------------------------------------- /day_11.md: -------------------------------------------------------------------------------- 1 | # [A walk in JavaScript](/README.md) 2 | 3 | ## DAY 11 4 | 5 | - Quality and reliability 6 | - An introduction to the "reliability" and "quality" concepts 7 | - Unit / Integration / Functional testing 8 | - Definitions 9 | - Comparison 10 | - TDD 11 | - Testing frameworks for JavaScript 12 | - Debugging 13 | - Debugging tools available for JavaScript 14 | - Global console object 15 | - Node.js console 16 | - debugger statement 17 | - node.js debugger 18 | - Browser's developer tools 19 | - IDE interaction with a browser to debug 20 | - Transpilers 21 | - Babel 22 | - Task runners, bundlers, build systems 23 | - Webpack 24 | - Grunt 25 | - Gulp 26 | - Brunch 27 | - Yeoman 28 | - RollUp 29 | 30 | ## Quality and reliability 31 | 32 | ### An introduction to the "reliability" and "quality" concepts 33 | 34 | Even though both aspects a intimately related, they're many differences between them. We can think about them in the following terms: 35 | 36 | - **Quality** 37 | - Closest to the code 38 | - Testability 39 | - Readability 40 | - Scalability 41 | - Reusability 42 | - Functional correctness 43 | - Robustness 44 | - "code" defects 45 | - Peer reviews 46 | - unit tests 47 | - Code coverage 48 | - **Reliability** 49 | - Closest to the execution in a host/environment for a given time 50 | - Stress test 51 | - Load test 52 | - Performance 53 | - Regression test 54 | - "failure" intensity, probability and statistics 55 | - End to end test 56 | - Integration test 57 | - Faults per thousand lines of code in x time 58 | 59 | In the software industry, there's a big overlap between quality and reliability, and the better the quality assurances processes applied to the code production, the more reliable the software tends to be. 60 | 61 | The bibliography is huge and there are many definitions, sometimes you'll find yourself asking the client *"what does quality mean to you"* to be able to sketch out a plan and avoid investing efforts in the "wrong" place. 62 | 63 | My general approach is that "the quality is owned by the team", every engineer MUST take the necessary measures to warrant the written code and propose corrections if brittle code has been detected. One of the most important measures is to recognize the fact that you WILL introduce defects in the code you write, no matter how much of an expert you are—eventually you'll break something. So don't trust yourself excessively, ask around for opinions, write tests, make it readable instead of "smart" and try to be a better engineer every single day. 64 | 65 | Here is some reading to start. 66 | 67 | - [Software quality](https://en.wikipedia.org/wiki/Software_quality) 68 | - [Software reliability testing](https://en.wikipedia.org/wiki/Software_reliability_testing) 69 | - [Reliability engineering in software](https://en.wikipedia.org/wiki/Reliability_engineering#Software_reliability) 70 | - [What Is Code Quality? And How to Improve It](https://www.perforce.com/blog/sca/what-code-quality-and-how-improve-it) - by Richard Bellairs 71 | - [Software Reliability](https://www.sciencedirect.com/topics/computer-science/software-reliability) 72 | - [CISQ Code quality Standards](https://www.it-cisq.org/standards/code-quality-standards/) 73 | 74 | ## Unit / Integration / Functional testing 75 | 76 | Usually the metaphor of a Pyramid is used to describe the impact of the different testing techniques and how speed, ROI, cost and other aspects are related to them. There are several "Pyramids" with some variations, but usually it starts with unit testing on the base of the pyramid, followed by integration and ending with functional testing, where the base provides the biggest benefits and the rest is built on top of that. (here an interesting article with a variation of this. [The practical test Pyramid](https://martinfowler.com/articles/practical-test-pyramid.html) by Ham Vocke) 77 | 78 | ### Definitions 79 | 80 | - [Unit Testing](https://en.wikipedia.org/wiki/Unit_testing) 81 | - [Integration Testing](https://en.wikipedia.org/wiki/Integration_testing) 82 | - [Functional Testing](https://en.wikipedia.org/wiki/Functional_testing) 83 | 84 | ### Comparison 85 | 86 | I've found this incredibly clear table for the first two types to show you the characteristics of both techniques on the ["Software testing class"](http://www.softwaretestingclass.com/what-is-difference-between-unit-testing-and-integration-testing/) website. 87 | 88 |
Unit TestingIntegration Testing
Unit testing is a type of testing to check if the small piece of code is doing what it is suppose to do.Integration testing is a type of testing to check if different pieces of the modules are working together.
Unit testing checks a single component of an application.The behavior of integration modules is considered in the Integration testing.
The scope of unit testing is narrow, it covers the "unit" or small piece of code under test. Therefore while writing a unit test shorter code is used that target just a single class.The scope of integration testing is wide, it covers the whole application under test and it requires much more effort to put together.
Unit tests should have no dependencies on code outside the unit being tested.Integration testing is dependent on other outside systems like databases, hardware allocated for them etc.
This is first type of testing is to be carried out in Software testing life cycle and generally executed by the developer.This type of testing is carried out after unit testing and before System testing and executed by the testing team.
Unit testing is not further sub divided into different types.Integration testing is further divided into different types as follows:
Top-down Integration, Bottom-Up Integration and so on.
Unit testing starts with the module specification.Integration testing starts with the interface specification.
The intricacies of the code are given visibility via unit testing.The integration structure is given visibility via Integration testing.
Unit testing mainly focuses on testing the functionality of individual units and does not uncover the issues that arise when different modules are interacting with each other.Integration testing aims to discover the issues that arise when different modules are interacting with each other to build the overall system.
The goal of unit testing is to test the each unit separately and ensure that each unit is working as expected.The goal of Integration testing is to test the combined modules together and ensure that every combined module is working as expected.
Unit testing comes under White box testing type.Integration testing comes under both Black box and White box type of testing.
89 | 90 | You can think of it in these terms: both features (door and lock) work perfectly as separated units, but the integration fails. 91 | 92 | 93 | 94 | ### TDD 95 | 96 | Testing is so important that a particular development process relies on writing the test first and then writing the code to pass them called [Test Drive Development](https://en.wikipedia.org/wiki/Test-driven_development)! 97 | Of course it might sound crazy as many of the [Extreme programming](https://en.wikipedia.org/wiki/Extreme_programming) related techniques do, but indulge me and think about this: 98 | 99 | Given that you have detailed specifications about how your software/feature should work, what if you first think about how the feature should be tested to make it "testable" and "reliable", then you write the abstract tests it's supposed to accomplish, as a contract, and only then start thinking about the actual code for the feature and finally write it. ... Those steps forced you to think before coding, and especially made you concentrate on how to make your code more testable first instead of writing it and having to iterate on refactoring sessions because it is not testable and maintainable enough. 100 | 101 | ### Testing Frameworks for JavaScript 102 | 103 | The market provides innumerable resources for testing your JavaScript apps, they can be suitable for unit testing, integration testing, automated testing, for UI/E2E, etc. Each one has its pros and cons and some are designed for specific libraries like [QUnit](https://en.wikipedia.org/wiki/QUnit) was for jQuery and some are more robust and generic like [Jest](https://en.wikipedia.org/wiki/Jest_(JavaScript_framework)) but most of them evolved to cover more techniques or died along the way. 104 | 105 | Here is a [list of unit testing frameworks](https://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#JavaScript) in Wikipedia 106 | 107 | ## Debugging 108 | 109 | So you think that testing your code will be enough huh? LOL not even close, even when you enter a green field (as opposed to legacy code) you'll end up having to deal with "damnit, where the heck is the error?!!!" 110 | Some can be detected with the introduction of more accurate tests, and some will escape from every testing attempt leaving you with the happy task of hunting them with creativity, but don't despair, there are several tools to assist you. 111 | 112 | > Debugging is the process of finding and resolving defects or problems within a [computer program](https://en.wikipedia.org/wiki/Computer_program) that prevent correct operation of [computer software](https://en.wikipedia.org/wiki/Computer_software) or a [system](https://en.wikipedia.org/wiki/System). 113 | > 114 | > Debugging tactics can involve [interactive debugging](https://en.wikipedia.org/wiki/Interactive), [control flow](https://en.wikipedia.org/wiki/Control_flow) analysis, [unit testing](https://en.wikipedia.org/wiki/Unit_testing), [integration testing](https://en.wikipedia.org/wiki/Integration_testing), [log file analysis](https://en.wikipedia.org/wiki/Logfile), monitoring at the application or system level, [memory dumps](https://en.wikipedia.org/wiki/Memory_dump), and [profiling](https://en.wikipedia.org/wiki/Profiling_(computer_programming)). 115 | > 116 | > Source: [Wikipedia](https://en.wikipedia.org/wiki/Debugging) 117 | 118 | Get familiar with the tools available, use them, learn them as you learn how to use your IDE, they'll save you a lot of time. 119 | 120 | ### Debugging tools available for JavaScript 121 | 122 | #### Global console object 123 | 124 | [MDN > Web APIs > console](https://developer.mozilla.org/en-US/docs/Web/API/Console) 125 | 126 | One of the most used, misused, underused tools is the globally available `console` object in your browser. It has several methods (but the engineers insist on using just the `console.log`) 127 | 128 | #### Node.js console 129 | 130 | [node.js > api > console](https://nodejs.org/api/console.html) 131 | 132 | Similar to the `console`global object provided by Web Browsers but not quite the same. 133 | 134 | #### debugger statement 135 | 136 | [MDN - debugger](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger) 137 | 138 | The debugger statement invokes any available debugging functionality, such as setting a breakpoint. If no debugging functionality is available, this statement has no effect. 139 | 140 | #### node.js debugger 141 | 142 | [node.js > debugger](https://nodejs.org/api/debugger.html) 143 | 144 | An out-of-process debugging utility accessible via a V8 Inspector and built-in debugging client. 145 | 146 | #### Browser's developer tools 147 | 148 | [Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/) 149 | 150 | Every modern browser will provide you with a battery of tools to inspect and debug your web applications. Network traffic, memory usage, performance, code debugging and many more tools will be available for you to understand how your app behaves on that specific browser. 151 | 152 | #### IDE interaction with a browser to debug 153 | 154 | Some modern IDEs provide you with extensions to be able to use an external browser debugger for your code without leaving your IDE or the other way around, testing an app running in your browser using the IDE debugger. 155 | 156 | e.g. [Chrome Debugging for VS Code](https://code.visualstudio.com/blogs/2016/02/23/introducing-chrome-debugger-for-vs-code) 157 | 158 | ## Transpilers 159 | 160 | We saw during this walk that the features defined by ECMAScript might not be implemented in all JavasScript engines. How do we write our code in e.g. ECMA2019 and make sure it'll run on Edge? Transpiling it. 161 | 162 | What's a transpiler? essentially a program that takes source code as input and returns source code to match a target system, e.g ES2019 to ES5 or TypeScript to ES2015. 163 | This technique lets you write your code in one consistent way and choose how to create an output for a specific target without taking care of many sources. 164 | 165 | One of the most used transpilers for JavaScript is [Babel](https://babeljs.io/) 166 | 167 | Here you can see how a simple [generator example taken from MDN](https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Sentencias/function*) is transpiled by Babel 168 | 169 | Original: 170 | 171 | ```javascript 172 | function* generator(i){ 173 | yield i; 174 | yield* anotherGenerator(i); 175 | yield i + 10; 176 | } 177 | ``` 178 | 179 | Transpiled: 180 | 181 | ```javascript 182 | "use strict"; 183 | 184 | var _marked = 185 | /*#__PURE__*/ 186 | regeneratorRuntime.mark(generator); 187 | 188 | function generator(i) { 189 | return regeneratorRuntime.wrap(function generator$(_context) { 190 | while (1) { 191 | switch (_context.prev = _context.next) { 192 | case 0: 193 | _context.next = 2; 194 | return i; 195 | 196 | case 2: 197 | return _context.delegateYield(anotherGenerator(i), "t0", 3); 198 | 199 | case 3: 200 | _context.next = 5; 201 | return i + 10; 202 | 203 | case 5: 204 | case "end": 205 | return _context.stop(); 206 | } 207 | } 208 | }, _marked); 209 | } 210 | ``` 211 | 212 | You can try it out [here](https://babeljs.io/repl). 213 | 214 | ## Task runners, bundlers, build systems 215 | 216 | Well, we went through testing, to testing frameworks to transpilers but how in the world do I make them work together? 217 | 218 | JavaScript became a huge ecosystem with many tools and techniques for delivering the code like testing, minification, bundling, linting. Here below I'll list some; each of them provide different features which might be broader (like webpack) or more dedicated to a specific task (like grunt) 219 | 220 | - [Webpack](https://webpack.js.org/) 221 | - [Grunt](https://gruntjs.com/) 222 | - [Gulp](https://gulpjs.com/) 223 | - [Brunch](https://brunch.io/) 224 | - [Yeoman](https://yeoman.io/) 225 | - [RollUp](https://rollupjs.org/guide/en/) 226 | 227 | *** 228 | [Go back to DAY 10](/day_10.md) or [Go next to DAY 12](/day_12.md) 229 | *** 230 | [Back to main page](https://github.com/thinkb4/a-walk-in-javascript/tree/master#day-11) -------------------------------------------------------------------------------- /day_12.md: -------------------------------------------------------------------------------- 1 | # [A walk in JavaScript](/README.md) 2 | 3 | ## DAY 12 4 | 5 | - Destructuring 6 | - Syntax 7 | - Examples 8 | - Readings 9 | - Advanced Function/code factorization 10 | - Currying 11 | - Partial application 12 | - First-class composition 13 | - Readings 14 | 15 | ## Destructuring 16 | 17 | > The **destructuring assignment** syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables. 18 | > 19 | > Source [Wikipedia](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) 20 | 21 | Ok nice, but, what's that? 22 | 23 | A better explanation is defined later on in that document 24 | 25 |

26 | 27 | The object and array literal expressions provide an easy way to create ad hoc packages of data. 28 | 29 | ```javascript 30 | var x = [1, 2, 3, 4, 5]; 31 | ``` 32 | 33 | The **destructuring assignment** uses similar syntax, but on the `left-hand side` of the assignment to define what values to **unpack** from the sourced variable. 34 | 35 | ```javascript 36 | let x = [1, 2, 3, 4, 5]; 37 | let [y, z] = x; 38 | 39 | console.log(y); // 1 40 | console.log(z); // 2 41 | ``` 42 | 43 | Source [Wikipedia](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) 44 |
45 | 46 | Now that's better, if we think in terms of unpacking it's much easier to understand. 47 | 48 | But this is only the beginning, this new feature enables a lot of new patterns which were hard to write and maintain before ES6 or even impossible to write. 49 | 50 | Object destructuring: 51 | 52 | ```javascript 53 | let x = {a: 1, b:2}; 54 | let {a, b} = x; 55 | 56 | console.log(a); // 1 57 | console.log(b); // 2 58 | ``` 59 | 60 | Variable Swapping 61 | 62 | ```javascript 63 | let a = 1; 64 | let b = 3; 65 | 66 | [a, b] = [b, a]; 67 | console.log(a); // 3 68 | console.log(b); // 1 69 | ``` 70 | 71 | Default values 72 | 73 | ```javascript 74 | let {a = 0, b = null} = someObject; 75 | ``` 76 | 77 | Even destructuring function parameters + adding default values 78 | 79 | ```javascript 80 | /** 81 | * 82 | * @param {object} $0 83 | * @param {string} $0.a 84 | * @param {number} $0.b 85 | * @returns {String} 86 | */ 87 | function f ({ a = 'default string', b = 0 } = {}) { 88 | return `${a}, ${b}`; 89 | } 90 | ``` 91 | 92 | And leveraging delayed evaluation you can make a destructured parameter to be mandatory 93 | 94 | ```javascript 95 | /** 96 | * 97 | * @param {object} $0 98 | * @param {string} $0.a 99 | * @param {number} $0.b 100 | * @returns {String} 101 | */ 102 | function f ({ 103 | a = (function(){ throw new Error('a is mandatory')}()), 104 | b = 0 105 | } = {}) { 106 | return `${a}, ${b}`; 107 | } 108 | 109 | f(); // will throw 110 | f({a:'hi'}); // will return "hi, 0" 111 | ``` 112 | 113 | Let's take some time and go through the following documents: 114 | 115 | - [MDN: Destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) 116 | - [YDKJS: ES6 & Beyond : Syntax -> Destructuring](https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch2.md#destructuring) 117 | - [2ality: Destructuring and parameter handling in ECMAScript 6](https://2ality.com/2015/01/es6-destructuring.html) 118 | - [David Walsh: Destructuring and Function Arguments](https://davidwalsh.name/destructuring-function-arguments) 119 | 120 | ## Advanced Function/code factorization 121 | 122 | ### Currying 123 | 124 | > In mathematics and computer science, currying is the technique of translating the evaluation of a function that takes multiple arguments into evaluating a sequence of functions, each with a single argument. For example, a function that takes two arguments, one from X and one from Y, and produces outputs in Z, by currying is translated into a function that takes a single argument from X and produces as outputs functions from Y to Z. Currying is related to, but not the same as, partial application. [Wikipedia](https://en.wikipedia.org/wiki/Currying) 125 | 126 | ```javascript 127 | /** 128 | * No curry for you 129 | * 130 | * @param {number} x 131 | * @param {number} y 132 | * @returns {number} 133 | */ 134 | function add(x, y){ 135 | return x + y; 136 | } 137 | add(3, 4); // > 7 138 | 139 | 140 | /** 141 | * Add some spicy curry 142 | * 143 | * @param {number} x 144 | * @returns {function} 145 | */ 146 | function add_curry(x) { // :P 147 | return function(y) { 148 | return x + y; 149 | } 150 | } 151 | add_curry(3)(4); // 7 152 | 153 | ``` 154 | 155 | ```javascript 156 | 157 | const message = 'Today, [date], [user] says [salutation]'; 158 | const message2 = 'Hello [user] you have to say [salutation] before the end of [date]'; 159 | const date = new Date(); 160 | const user = { name: 'Javier', surname: 'Valderrama', nickName: 'jax' }; 161 | const salutation = 'hi'; 162 | 163 | /** 164 | * Not Curried 165 | * 166 | * @param {String} message 167 | * @param {Object} date 168 | * @param {Object} user 169 | * @param {String} salutation 170 | * @returns {String} 171 | */ 172 | function formatMessage (message, date, user, salutation) { 173 | 174 | return message.replace('[date]', date.toLocaleDateString()) 175 | .replace('[user]', user.nickName.toUpperCase()) 176 | .replace('[salutation]', salutation.replace(/hi/i, 'howdy')) 177 | 178 | } 179 | 180 | formatMessage( 181 | message, 182 | date, 183 | user, 184 | salutation 185 | ) // > "Today, 24/6/2019, JAX says howdy" 186 | 187 | /** 188 | * Curried 189 | * 190 | * @param {String} salutation 191 | * @param {Object} user 192 | * @param {Object} date 193 | * @param {String} message 194 | * 195 | * @returns {Function|String} 196 | */ 197 | let formatMessageCurried = (salutation) => (user) => (date) => (message) => { 198 | return message.replace('[date]', date.toLocaleDateString()) 199 | .replace('[user]', user.nickName.toUpperCase()) 200 | .replace('[salutation]', salutation.replace(/hi/i, 'howdy')) 201 | 202 | } 203 | 204 | /** 205 | * Not very interesting 206 | */ 207 | formatMessageCurried(salutation)(user)(date)(message) // > "Today, 24/6/2019, JAX says howdy" 208 | 209 | /** 210 | * This is really interesting 211 | */ 212 | const formatMsgWithSalutationUserAndDate = formatMessageCurried(salutation)(user)(date); 213 | 214 | formatMsgWithSalutationUserAndDate(message) // > "Today, 24/6/2019, JAX says howdy" 215 | formatMsgWithSalutationUserAndDate(message2) // > "Hellow JAX you have to say howdy before the end of 24/6/2019" 216 | 217 | ``` 218 | 219 | ### Partial Application 220 | 221 | > In computer science, partial application (or partial function application) refers to the process of fixing a number of arguments to a function, producing another function of smaller arity. [Wikipedia](https://en.wikipedia.org/wiki/Partial_application) 222 | 223 | Difference from Currying 224 | > One of the significant differences between the two is that a call to a partially applied function returns the result right away, not another function down the currying chain. [Wikipedia](https://en.wikipedia.org/wiki/Currying#Contrast_with_partial_function_application) 225 | 226 | ```javascript 227 | /** 228 | * No partial 229 | * 230 | * @param {number} x 231 | * @param {number} y 232 | * @returns {number} 233 | */ 234 | function add(x, y){ 235 | return x + y; 236 | } 237 | add(3, 4); // > 7 238 | 239 | /** 240 | * Partial 241 | * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Partially_applied_functions 242 | * 243 | * @param {number} y 244 | * @returns {number} 245 | */ 246 | var add_partial = add.bind(null, 3); 247 | 248 | add_partial(4); // -> 7 249 | 250 | ``` 251 | 252 | ```javascript 253 | 254 | /** 255 | * Using multilevel binary partially applied functions to retunr an unary 256 | * (f ∘ g )(v) 257 | * 258 | * @param {...function} args 259 | * @returns {Function} 260 | */ 261 | function multiLevelPartialRight (...args) { 262 | let cfn = (v) => v; 263 | 264 | while (args.length) { 265 | cfn = args.pop().bind(null, cfn) 266 | } 267 | 268 | return cfn 269 | } 270 | 271 | multiLevelPartialRight( 272 | /* f */(fn, v) => fn(v) + 1, 273 | /* g */(fn, v) => fn(v) * 2 274 | )(2) // > (f ∘ g )(v) = 5 275 | 276 | ``` 277 | 278 | ### First-class composition 279 | 280 | > In computer science, function composition is an act or mechanism used to **combine** simple functions to build more complicated ones. Like the usual composition of functions in mathematics, **the result of each function is passed as the argument of the next, and the result of the last one is the result of the whole**. [Wikipedia](https://en.wikipedia.org/wiki/Function_composition_(computer_science)) 281 | 282 | Simple use-case 283 | > If an airplane's elevation at time `t` is given by the function `h(t)`, and the oxygen concentration at elevation `x` is given by the function `c(x)`, then `(c ∘ h)(t)` describes the oxygen concentration around the plane at time `t`. [Wikipedia](https://en.wikipedia.org/wiki/Function_composition#Examples) 284 | 285 | A well known usecase is a mapper or transducer 286 | > From a given response data, remove duplicates, normalize numbers, sort by N.... and so on 287 | 288 | Notes: 289 | 290 | - the flow is right-to-left, calling each function with the output of the latest provided first. 291 | - JavaScript doesn't have a `composition` operator like Haskell 292 | - JavaScript have Lambda expressions!! 293 | 294 | ```javascript 295 | 296 | /** 297 | * simplest imperative nested solution 298 | * n(x) = f(g(x)) 299 | * 300 | * Notation: 301 | * ( f ∘ g )(x) = f(g(x) // f ∘ g means f after g 302 | * 303 | * Alternative postfix notation: 304 | * (xg)f 305 | * @see https://en.wikipedia.org/wiki/Reverse_Polish_notation 306 | * 307 | * @param {Function} f 308 | * @param {Function} g 309 | */ 310 | function fog (f, g) { return (x) => f(g(x)) }; 311 | 312 | fog( 313 | /* f */ v => v + 1, 314 | /* g */ v => v * 2 315 | )(2) // > (f ∘ g )(v) = 5 316 | 317 | ``` 318 | 319 | ```javascript 320 | 321 | /** 322 | * Iterative solution 323 | * (f ∘ g )(v) 324 | * 325 | * @param {...function} args 326 | * @returns {Function} 327 | */ 328 | function composeSequenceRight (...args) { 329 | 330 | return (v) => { 331 | while (args.length) { 332 | v = args.pop()(v) 333 | } 334 | return v; 335 | } 336 | 337 | } 338 | 339 | composeSequenceRight( 340 | /* f */ v => v + 1, 341 | /* g */ v => v * 2 342 | )(2) // > (f ∘ g )(v) = 5 343 | 344 | ``` 345 | 346 | ```javascript 347 | 348 | /** 349 | * Iterative oneliner functional style solution 350 | * (f ∘ g )(v) 351 | * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/ReduceRight 352 | * 353 | * @param {...function} args 354 | * @returns {Function} 355 | */ 356 | const composeRight = (...args) => (value) => args.reduceRight((acc, fn) => fn(acc), value) 357 | 358 | composeRight( 359 | /* f */ v => v + 1, 360 | /* g */ v => v * 2 361 | )(2) // > (f ∘ g )(v) = 5 362 | 363 | ``` 364 | 365 | ### Readings: 366 | 367 | - [Composing Exercises in Programming Style](https://blog.frankel.ch/exercises-programming-style/6/) 368 | - [Partially Applied Functions In JavaScript](https://lostechies.com/derickbailey/2012/07/20/partially-applied-functions-in-javascript/) 369 | - [JavaScript Function Composition, Currying, and Partial Application](https://medium.com/wdstack/javascript-function-composition-currying-and-partial-application-5a04107530ee) 370 | - [Curry or Partial Application?](https://medium.com/javascript-scene/curry-or-partial-application-8150044c78b8) 371 | - [Creating partially applied functions in Javascript](https://codeburst.io/creating-partially-applied-functions-in-javascript-1f623a56d055) 372 | 373 | *** 374 | [Go back to DAY 11](/day_11.md) 375 | *** 376 | [Back to main page](https://github.com/thinkb4/a-walk-in-javascript/tree/master#day-12) -------------------------------------------------------------------------------- /jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "verbose": true, 3 | "testRegex": "(/src/.*|(\\.|/))test.js?$", 4 | "transformIgnorePatterns": [ 5 | "node_modules/(?!@jaxolotl)" 6 | ], 7 | "coveragePathIgnorePatterns": [ 8 | "/node_modules/", 9 | "/.git/" 10 | ], 11 | "coverageThreshold": { 12 | "global": { 13 | "branches": 50, 14 | "functions": 50, 15 | "lines": 50, 16 | "statements": 50 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "a-walk-in-javascript", 3 | "version": "1.13.3", 4 | "description": "A day by day walk through the basics of javascript assisted with notes, exercises and references to the most significant resources online", 5 | "main": "''", 6 | "scripts": { 7 | "test": "jest -c jest.config.json --coverage", 8 | "test:watch": "jest -c jest.config.json --watchAll", 9 | "lint": "eslint src/**/*.js", 10 | "lint-w": "esw -w --color src/**/*.js" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/Jaxolotl/a-walk-in-javascript.git" 15 | }, 16 | "keywords": [ 17 | "javascript", 18 | "JS", 19 | "ES6", 20 | "ECMAScript" 21 | ], 22 | "author": "Javier Valderrama", 23 | "license": "MIT", 24 | "bugs": { 25 | "url": "https://github.com/Jaxolotl/a-walk-in-javascript/issues" 26 | }, 27 | "homepage": "https://github.com/Jaxolotl/a-walk-in-javascript#readme", 28 | "devDependencies": { 29 | "@babel/cli": "^7.23.9", 30 | "@babel/core": "^7.24.0", 31 | "@babel/preset-env": "^7.24.0", 32 | "@jaxolotl/eslint-config-wdc-es6": "^1.2.0", 33 | "babel-eslint": "^10.1.0", 34 | "eslint": "^8.57.0", 35 | "eslint-plugin-import": "^2.29.1", 36 | "eslint-plugin-node": "^11.1.0", 37 | "eslint-plugin-promise": "^6.1.1", 38 | "eslint-plugin-standard": "^5.0.0", 39 | "jest": "^29.7.0", 40 | "jest-cli": "^29.7.0" 41 | }, 42 | "volta": { 43 | "node": "20.11.0", 44 | "yarn": "4.1.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /practice_placeholder.js: -------------------------------------------------------------------------------- 1 | // use this file to write temp code and run it with run-code extension 2 | -------------------------------------------------------------------------------- /src/day_04/arrays.test.js: -------------------------------------------------------------------------------- 1 | 2 | let hotPeppers = [ 3 | 'Madame Jeanette', 4 | 'Scotch Bonnet', 5 | 'White Habanero', 6 | 'Habanero', 7 | 'Fatalii', 8 | 'Devil’s Tongue', 9 | 'Tigerpaw', 10 | 'Chocolate Habanero (aka Congo Black)', 11 | 'Caribbean Red Habanero', 12 | 'Red Savina', 13 | 'Naga Morich (aka Dorset Naga)', 14 | 'Trinidad Scorpion CARDI', 15 | 'Bhut Jolokia Chocolate', 16 | 'Bhut Jolokia (aka Ghost Pepper)', 17 | '7 Pot Chili ', 18 | 'Gibraltar (aka Spanish Naga)', 19 | 'Infinity Chili', 20 | 'Naga Viper', 21 | '7 Pod Douglah (aka Chocolate 7 Pot)', 22 | 'Trinidad Scorpion Butch T', 23 | 'Trinidad Moruga Scorpion', 24 | 'Carolina Reaper' 25 | ]; 26 | 27 | describe('DAY 4: Test Arrays', () => { 28 | 29 | it('Array to be instance of Array (literal)', () => { 30 | // use literal notation 31 | let array; 32 | expect(array).toBeInstanceOf(Array); 33 | }); 34 | 35 | it('Array to be instance of Array (constructor)', () => { 36 | // use constructor 37 | let array; 38 | expect(array).toBeInstanceOf(Array); 39 | }); 40 | 41 | it('Array to be instance of Object and Array', () => { 42 | // use any of the previous 43 | let array; 44 | expect(array).toBeInstanceOf(Array); 45 | expect(array).toBeInstanceOf(Object); 46 | }); 47 | 48 | it('Initialize Array with length of 4 (literal)', () => { 49 | // use literal 50 | let array; 51 | expect(array.length).toBe(4); 52 | }); 53 | 54 | it('Initialize Array with length of 4 (constructor)', () => { 55 | // use constructor 56 | let array; 57 | expect(array.length).toBe(4); 58 | }); 59 | 60 | it('Initialize Array with length of 1 (constructor), and first entry value to be 4', () => { 61 | // use constructor 62 | let array; 63 | expect(array.length).toBe(1); 64 | expect(array[0]).toBe(4); 65 | }); 66 | 67 | it('Mutate Array length to be 4', () => { 68 | let array = []; 69 | // use a mutator method to add elements 70 | expect(array.length).toBe(4); 71 | }); 72 | 73 | it('Mutate Array length to be 5', () => { 74 | let array = [42, 42, 42, 42, 42, 42]; 75 | // use a mutator method to remove elements 76 | expect(array.length).toBe(5); 77 | }); 78 | 79 | it('Remove the first element of the array', () => { 80 | let array = ['a', 'b', 'c', 'd']; 81 | // use a method to remove it 82 | expect(array.indexOf('a')).toBe(-1); 83 | }); 84 | 85 | it('Remove the last element of the array', () => { 86 | let array = ['a', 'b', 'c', 'd']; 87 | // use a method to remove it 88 | expect(array.indexOf('d')).toBe(-1); 89 | }); 90 | 91 | it('Remove an element off from inner boundaries of the array', () => { 92 | let array = ['a', 'b', 'c', 'd']; 93 | // use a method to remove it 94 | expect(array.indexOf('b')).toBe(-1); 95 | }); 96 | 97 | it('Create a new array containing the values of 2 different arrays (method)', () => { 98 | let array1 = ['a', 'b', 'c', 'd']; 99 | let array2 = [1, 2, 3, 4, 5]; 100 | // use a method to create it 101 | let array3; 102 | 103 | expect(array3).toEqual([1, 2, 3, 4, 5, 'a', 'b', 'c', 'd']); 104 | }); 105 | 106 | it('Create a new array containing the values of 2 different arrays (operator)', () => { 107 | let array1 = ['a', 'b', 'c', 'd']; 108 | let array2 = [1, 2, 3, 4, 5]; 109 | // use an operator to create it 110 | let array3; 111 | 112 | expect(array3).toEqual(['a', 'b', 'c', 'd', 1, 2, 3, 4, 5]); 113 | }); 114 | 115 | it('Create a string from an array (method)', () => { 116 | let array = ['a', 'b', 'c', 'd']; 117 | // use a method to create it 118 | let string; 119 | 120 | expect(string).toBe('a-b-c-d'); 121 | }); 122 | 123 | it('Create an array from a string (method)', () => { 124 | let string = 'a-b-c-d'; 125 | // use a method to create it 126 | let array; 127 | 128 | expect(array).toEqual(['a', 'b', 'c', 'd']); 129 | }); 130 | 131 | it('Create an array from a string (operator)', () => { 132 | let string = 'abcd'; 133 | // use an operator to create it 134 | let array; 135 | 136 | expect(array).toEqual(['a', 'b', 'c', 'd']); 137 | }); 138 | 139 | it('Reverse the a string using the learned techniques', () => { 140 | let string = 'abcd'; 141 | // use available method for strings an arrays 142 | let reversed; 143 | 144 | expect(reversed).toEqual('dcba'); 145 | }); 146 | 147 | it('Copy the values of array a to array b using an iteration', () => { 148 | let a = [1, 2, 'a', 'b', 'c', [6, 7]]; 149 | let b = []; 150 | 151 | /** 152 | * 153 | * iterate over a ( you can use an iteration statement or an array method ) 154 | * validate each value has been correctly copied 155 | * 156 | */ 157 | 158 | //! add your code here 159 | 160 | // ? why a IS NOT b? explain 161 | expect(a).not.toBe(b); 162 | // ? but IS EQUAL to b? explain 163 | expect(a).toEqual(b); 164 | // ? then why a[5] ACTUALLY IS b[5] 165 | expect(a[5]).toBe(b[5]); 166 | 167 | }); 168 | 169 | it('Find an element by value using an array method', () => { 170 | let array = hotPeppers; 171 | let myFavorite = 'Habanero'; 172 | // use an array method 173 | let found; 174 | 175 | expect(found).toBe(myFavorite); 176 | }); 177 | 178 | }); 179 | -------------------------------------------------------------------------------- /src/day_05/branching.test.js: -------------------------------------------------------------------------------- 1 | 2 | describe('DAY 5: Test Branching - if...else', () => { 3 | 4 | it('b to be true if a is truthy', () => { 5 | let a; 6 | let b; 7 | 8 | if (a) { 9 | // 10 | } else { 11 | // 12 | } 13 | 14 | expect(b).toBe(true); 15 | 16 | }); 17 | 18 | it('b to be false if a is truthy', () => { 19 | let a; 20 | let b; 21 | 22 | if (a) { 23 | // 24 | } else { 25 | // 26 | } 27 | 28 | expect(b).toBe(false); 29 | 30 | }); 31 | 32 | it('b to be 1 if a is truthy ( use postfix unary operator )', () => { 33 | let a; 34 | let b = 0; 35 | 36 | if (a) { 37 | // 38 | } else { 39 | // 40 | } 41 | // are prefix and postfix interchangeable here? 42 | expect(b).toBe(1); 43 | 44 | }); 45 | 46 | it('b to be -1 if a is truthy ( use prefix unary operator )', () => { 47 | let a; 48 | let b = 0; 49 | 50 | if (a) { 51 | // 52 | } else { 53 | // 54 | } 55 | // are prefix and postfix interchangeable here? 56 | expect(b).toBe(-1); 57 | 58 | }); 59 | 60 | }); 61 | 62 | describe('DAY 5: Test Branching - switch/break', () => { 63 | 64 | it('found to be true when number 7 is the first item of array', () => { 65 | let array = []; 66 | let found = false; 67 | 68 | switch (array.indexOf(7)) { 69 | case -1: 70 | break; 71 | case 0: 72 | break; 73 | case 1: 74 | break; 75 | default: 76 | break; 77 | } 78 | 79 | expect(found).toBe(true); 80 | 81 | }); 82 | 83 | it('found to be true when number 7 is not an item of array', () => { 84 | let array = []; 85 | let found = false; 86 | 87 | switch (array.indexOf(7)) { 88 | case -1: 89 | break; 90 | case 0: 91 | break; 92 | case 1: 93 | break; 94 | default: 95 | break; 96 | } 97 | 98 | expect(found).toBe(true); 99 | 100 | }); 101 | 102 | it('found to be true when number 7 is at index 4 of array', () => { 103 | let array = []; 104 | let found = false; 105 | 106 | switch (array.indexOf(7)) { 107 | case -1: 108 | break; 109 | case 0: 110 | break; 111 | case 1: 112 | break; 113 | default: 114 | found = true; 115 | break; 116 | } 117 | 118 | expect(found).toBe(true); 119 | 120 | }); 121 | 122 | it('found to be true when number 7 is at index 2 or 3 or 4 of array ( wanna try Fallthrough? )', () => { 123 | let array = []; 124 | let found = false; 125 | 126 | switch (array.indexOf(7)) { 127 | case -1: 128 | break; 129 | case 0: 130 | break; 131 | case 1: 132 | break; 133 | default: 134 | found = true; 135 | break; 136 | } 137 | 138 | expect(found).toBe(true); 139 | 140 | }); 141 | 142 | }); 143 | 144 | describe('DAY 5: Test Branching - short circuit', () => { 145 | 146 | it('c to be "hell yeah" using logical AND to evaluate a AND b, AND the value assigned to c', () => { 147 | let a; 148 | let b; 149 | let c = a && b && 'hell yeah'; 150 | 151 | expect(c).toBe('hell yeah'); 152 | 153 | }); 154 | 155 | it('c to be "hell yeah" using logical OR to evaluate a OR b, AND the value assigned to c ( find the error and fix it )', () => { 156 | let a = 1; 157 | let b; 158 | let c = a || b && 'hell yeah'; 159 | 160 | expect(c).toBe('hell yeah'); 161 | 162 | }); 163 | 164 | it('c to be true IF a AND b are numbers and > than 42', () => { 165 | // read the test spec carefully before start coding ;) 166 | let a; 167 | let b; 168 | let c = false; 169 | 170 | expect(c).toBe(true); 171 | 172 | }); 173 | }); 174 | 175 | describe('DAY 5: Test Branching - conditional operator ( ternary )', () => { 176 | 177 | it('c to be true IF a AND b are numbers and > than 42, else it should be false', () => { 178 | 179 | let a = null; 180 | let b = null; 181 | let c = null; // use ternary operator during assignment 182 | 183 | expect(c).toBe(true); 184 | 185 | a = null; 186 | b = null; 187 | c = null; // use ternary operator during assignment 188 | 189 | expect(c.toString()).toBe('Error: Not valid values for a and b'); 190 | 191 | }); 192 | 193 | it(`if speed is faster than 140, traffic ticket should be 8000, 194 | else if, it's faster than 130, traffic ticket should be 3000 195 | else, traffic ticket should be 0`, () => { 196 | 197 | let speed; 198 | let trafficTicket; // use ternary operator during assignment 199 | 200 | expect(trafficTicket).toBe(8000); 201 | 202 | // change the values so the test may pass ( use ternary operator for trafficTicket ) 203 | 204 | expect(trafficTicket).toBe(3000); 205 | 206 | // change the values so the test may pass ( use ternary operator for trafficTicket ) 207 | 208 | expect(trafficTicket).toBe(0); 209 | 210 | /** 211 | * it seems we had to do some repetitive work here 212 | * any clue about how to avoid it? 213 | */ 214 | }); 215 | }); 216 | -------------------------------------------------------------------------------- /src/day_05/exceptionHandling.test.js: -------------------------------------------------------------------------------- 1 | describe('DAY 5: Test Exception Handling', () => { 2 | 3 | it('throw explicitly an error and on catch define a as true', () => { 4 | let a; 5 | 6 | expect(a).toBe(true); 7 | 8 | }); 9 | 10 | it('throw explicitly an error and assign the error to a, make the verification of the message', () => { 11 | let a; 12 | 13 | expect(a.toString()).toBe(`Error: I'm an error`); 14 | 15 | }); 16 | 17 | it('throw explicitly an error and assign the error to a, make the verification of type', () => { 18 | let a; 19 | 20 | expect(a).toBeInstanceOf(Error); 21 | 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /src/day_05/grouping.test.js: -------------------------------------------------------------------------------- 1 | describe('DAY 5: Test Grouping', () => { 2 | 3 | it('change the code to make the second expect throw and error', () => { 4 | let a; 5 | let b; 6 | 7 | expect(a).toBe(undefined); 8 | expect(() => b).toThrow(`b is not defined`); 9 | 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /src/day_05/iterableAndIterators.test.js: -------------------------------------------------------------------------------- 1 | 2 | describe('DAY 5: Iterable/Iterator', () => { 3 | 4 | it(`get the iterator function of a String`, () => { 5 | let string = 'hello'; 6 | let theIteratorFunction; 7 | 8 | expect(theIteratorFunction).toBeInstanceOf(Object); 9 | expect(theIteratorFunction).toBeInstanceOf(Function); 10 | 11 | }); 12 | 13 | it(`get the iterator object returned by the iterator function of a String`, () => { 14 | let string = 'hello'; 15 | let theIteratorObject; 16 | 17 | expect(theIteratorObject).toBeInstanceOf(Object); 18 | 19 | }); 20 | 21 | it(`get the string representation 22 | of the iterator object returned by the iterator function of a String`, () => { 23 | let string = 'hello'; 24 | let theIteratorObjectCoercedToString; 25 | 26 | expect(theIteratorObjectCoercedToString).toBe('[object String Iterator]'); 27 | 28 | }); 29 | 30 | it(`get the next method returned by the iterator function of a String`, () => { 31 | let string = 'hello'; 32 | let theIteratorNextMethod; 33 | 34 | expect(theIteratorNextMethod).toBeInstanceOf(Object); 35 | expect(theIteratorNextMethod).toBeInstanceOf(Function); 36 | 37 | }); 38 | 39 | it(`get at least 1 value returned by the next method returned by the iterator function of a String`, () => { 40 | let string = 'hello'; 41 | let theIteratorNextMethodValue; 42 | 43 | expect(theIteratorNextMethodValue).toBe('h'); 44 | 45 | }); 46 | 47 | it(`make your own test to get all values from a String using the iterable protocol`, () => { 48 | // I'm throwing and error to make it fail, remove it and add your code 49 | throw Error('do not cheat 3:) '); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /src/day_05/iteration.test.js: -------------------------------------------------------------------------------- 1 | describe('DAY 5: Test Iteration - While', () => { 2 | 3 | it(`(while loop) 4 | condition: should loop until a is less than 5 5 | body: post increment a on each iteration`, () => { 6 | let a = 0; 7 | 8 | expect(a).toBe(5); 9 | 10 | }); 11 | 12 | it(`(while loop) 13 | condition: pre increment a 14 | body: should break if a is greater than 4`, () => { 15 | let a = 0; 16 | 17 | expect(a).toBe(5); 18 | 19 | }); 20 | }); 21 | 22 | describe('DAY 5: Test Iteration - for', () => { 23 | it(`(for loop) 24 | initialization: declare a to 0 25 | condition: keep looping whilst a is less than 5 26 | final-expression: post increment a 27 | body: operate with a and b to make b be 11 as final result`, () => { 28 | let a; 29 | let b = 1; 30 | 31 | expect(a).toBe(5); 32 | expect(b).toBe(11); 33 | 34 | }); 35 | 36 | it(`(for loop) 37 | initialization: set a to 0 38 | condition: keep looping whilst a is less than 5 39 | final-expression: post increment a 40 | body: operate with a and b to make b a string equals to 01234`, () => { 41 | let b = ''; 42 | 43 | expect(b).toBe('01234'); 44 | 45 | }); 46 | 47 | }); 48 | 49 | describe('DAY 5: Test Iteration - for...in', () => { 50 | 51 | it(`(for..in loop) 52 | for every property in object 53 | multiply the property value per 2`, () => { 54 | 55 | let object = { prop1: 1, prop2: 2, prop3: 3 }; 56 | 57 | expect(object.prop1).toBe(2); 58 | expect(object.prop2).toBe(4); 59 | expect(object.prop3).toBe(6); 60 | 61 | }); 62 | 63 | it(`(for..in loop) 64 | for every property in object 65 | add the property name to the array`, () => { 66 | let array = []; 67 | let object = { prop1: 1, prop2: 2, prop3: 3 }; 68 | 69 | expect(array.indexOf('prop1')).toBe(0); 70 | 71 | }); 72 | }); 73 | 74 | describe('DAY 5: Test Iteration - for...of', () => { 75 | 76 | it(`(for..of loop) 77 | for every char of string 78 | add its uppercase version to string2`, () => { 79 | let string = 'hello'; 80 | let string2 = ''; 81 | 82 | expect(string2).toBe('HELLO'); 83 | 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /src/day_06/closure.test.js: -------------------------------------------------------------------------------- 1 | describe('DAY 6: Test closure', () => { 2 | 3 | it(`function a to change variable b through a closure (side effect)`, () => { 4 | 5 | /** 6 | * 7 | * @returns {undefined} 8 | */ 9 | function a () { 10 | // add the code to operate with the free variable 11 | b++; 12 | } 13 | 14 | let b = 5; 15 | 16 | // add the code to execute the operation on the free variable inside function a 17 | 18 | expect(b).toBe(6); 19 | }); 20 | 21 | it(`function c to change variable a and b through a closure (side effect)`, () => { 22 | 23 | let a = 9; 24 | let b = function () {}; 25 | /** 26 | * 27 | * @returns {undefined} 28 | */ 29 | function c () { 30 | a = function () {}; 31 | b = []; 32 | } 33 | 34 | expect(typeof a).toBe('number'); 35 | expect(b).toBeInstanceOf(Function); 36 | 37 | // add the missing part of the code to complete the test 38 | 39 | expect(typeof a).toBe('function'); 40 | expect(b).toBeInstanceOf(Array); 41 | }); 42 | 43 | }); 44 | -------------------------------------------------------------------------------- /src/day_06/functions.test.js: -------------------------------------------------------------------------------- 1 | describe('DAY 6: Test Functions', () => { 2 | 3 | it(`(function statement) 4 | declare a function named hello`, () => { 5 | 6 | // add your code here 7 | 8 | expect(hello).toBeInstanceOf(Function); 9 | }); 10 | 11 | it(`(anonymous function expression) 12 | write an anonymous function expression with an empty body`, () => { 13 | 14 | // add your code here 15 | 16 | expect(hello).toBeInstanceOf(Function); 17 | expect(hello.toString().replace(/[^a-z0-9_$]/igm, '')).toBe('function'); 18 | }); 19 | 20 | it(`(named function expression) 21 | write a named function expression with an empty body`, () => { 22 | 23 | // add your code here 24 | 25 | expect(hello).toBeInstanceOf(Function); 26 | expect(hello.toString().replace(/[^a-z0-9_$]/igm, '')).toMatch(/^function[a-z0-9_$]+$/); 27 | }); 28 | 29 | it(`(IIFE) 30 | convert function a into an IIFE`, () => { 31 | 32 | let a = 1; 33 | // add your code here 34 | // there's probably no way to verify with a test if it's an IIFE 35 | // use this to learn, not to pass the test :P 36 | /** 37 | * @returns {undefined} 38 | */ 39 | function b () { 40 | a++; 41 | } 42 | 43 | expect(a).toBe(2); 44 | }); 45 | 46 | it(`(Function arity) 47 | get the function's arity and assign it to the arity variable to match the test`, () => { 48 | /** 49 | * 50 | * @param {*} b 51 | * @param {*} c 52 | * @param {*} d 53 | * @param {*} e 54 | * @returns {undefined} 55 | */ 56 | function a (b, c, d, e) {} 57 | 58 | // add your code here 59 | let arity; 60 | 61 | expect(arity).toBe(4); 62 | }); 63 | 64 | it(`(Properties of a function) 65 | get the name of myFunction`, () => { 66 | /** 67 | * 68 | * @returns {undefined} 69 | */ 70 | function myFunction () { } 71 | 72 | // change the test 73 | expect(myFunction).toBe('myFunction'); 74 | }); 75 | 76 | it(`(Side effect) 77 | change to code to avoid function b to have side effects on a`, () => { 78 | let a = 1; 79 | /** 80 | * 81 | * @param {*} b 82 | * @returns {undefined} 83 | */ 84 | function b () { 85 | // add your code here 86 | a = 2; 87 | return ++a; 88 | } 89 | 90 | expect(a).toBe(1); 91 | expect(b()).toBe(3); 92 | // intentional repetition 93 | expect(a).toBe(1); 94 | expect(b()).toBe(3); 95 | }); 96 | 97 | }); 98 | -------------------------------------------------------------------------------- /src/day_06/hoisting.test.js: -------------------------------------------------------------------------------- 1 | describe('DAY 6: Test Hoisting', () => { 2 | 3 | it(`myHoistedVariable should be hoisted as undefined, 4 | NOT to throw a reference error`, () => { 5 | 6 | expect(myHoistedVariable).toBeUndefined(); 7 | 8 | // change the declaration statement to complete the test 9 | let myHoistedVariable = 3; 10 | }); 11 | 12 | it(`myHoistedFunctionExpression should be hoisted as undefined, 13 | NOT to throw a reference error`, () => { 14 | 15 | expect(myHoistedFunctionExpression).toBeUndefined(); 16 | 17 | // change the declaration statement to complete the test 18 | const myHoistedFunctionExpression = function () { 19 | 20 | }; 21 | }); 22 | 23 | it(`myHoistedFunctionDeclaration should be hoisted together with its body, 24 | NOT to throw a reference error`, () => { 25 | 26 | // change the expect clause to complete the test 27 | // @see https://jestjs.io/docs/en/expect documentation for help 28 | expect(myHoistedFunctionDeclaration).toThrow(); 29 | 30 | /** 31 | * @returns {undefined} 32 | */ 33 | function myHoistedFunctionDeclaration () { 34 | 35 | } 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /src/day_06/scope.test.js: -------------------------------------------------------------------------------- 1 | 2 | describe('DAY 6: Test Scope', () => { 3 | 4 | it(`n to be available outside of the block scope`, () => { 5 | 6 | { 7 | // change the declaration statement to accomplish the task 8 | let n = 5; 9 | } 10 | 11 | expect(n).toBe(5); 12 | }); 13 | 14 | it(`outer n to be 5 15 | inner IIFE n var to be 4 (hint: add the missing code)`, () => { 16 | let n = 5; 17 | 18 | (function () { 19 | 20 | expect(n).toBe(4); 21 | 22 | }()); 23 | 24 | expect(n).toBe(5); 25 | }); 26 | 27 | it(`inner most IIFE to have access to the outer most n var (hint: change the expect statement)`, () => { 28 | let n = 5; 29 | 30 | (function () { 31 | 32 | (function () { 33 | 34 | (function () { 35 | 36 | (function () { 37 | 38 | (function () { 39 | 40 | expect(n).not.toBe(5); 41 | 42 | }()); 43 | 44 | }()); 45 | 46 | }()); 47 | 48 | }()); 49 | 50 | }()); 51 | 52 | }); 53 | 54 | }); 55 | -------------------------------------------------------------------------------- /src/day_07/arrowFunctions.test.js: -------------------------------------------------------------------------------- 1 | 2 | describe('DAY 7: arrow functions', () => { 3 | 4 | it(`complete the function code to pass the test`, () => { 5 | 6 | let myArrowFunction = () => { }; 7 | 8 | expect(myArrowFunction(1, 2)).toEqual({ first: 1, second: 2 }); 9 | 10 | }); 11 | 12 | }); 13 | -------------------------------------------------------------------------------- /src/day_07/generators.test.js: -------------------------------------------------------------------------------- 1 | 2 | describe('DAY 7: generators', () => { 3 | 4 | it(`complete the function code to pass the test`, () => { 5 | 6 | var msg = [`don't`, `repeat`, `yourself`]; 7 | 8 | /** 9 | * Modify the function to return a Generator object 10 | * complete the body of the generator using a for...of statement 11 | * iterate over the iterable input and yeild the valuefor...of loop 12 | * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of 13 | * 14 | * @param {array} input 15 | * @returns {Generator} 16 | */ 17 | function gen () { 18 | 19 | } 20 | 21 | let myGen = gen(msg); 22 | 23 | expect(myGen.next()).toEqual({ value: `don't`, done: false }); 24 | expect(myGen.next()).toEqual({ value: `repeat`, done: false }); 25 | expect(myGen.next()).toEqual({ value: `yourself`, done: false }); 26 | expect(myGen.next()).toEqual({ value: undefined, done: true }); 27 | 28 | }); 29 | 30 | }); 31 | -------------------------------------------------------------------------------- /src/day_07/this.test.js: -------------------------------------------------------------------------------- 1 | 2 | describe('DAY 7: this keyword', () => { 3 | 4 | it(`invoke a constructor function and assign the resulting object to "a"`, () => { 5 | 6 | /** 7 | * @returns {undefined|object} 8 | */ 9 | function A () { 10 | 11 | this.b = function b () { 12 | return this.c; 13 | }; 14 | 15 | this.c = [1, 2, 3, 4]; 16 | } 17 | 18 | // complete the code to pass the test 19 | let a; 20 | 21 | expect(a.b()).toBe(a.c); 22 | expect(a).toBeInstanceOf(A); 23 | }); 24 | 25 | it(`create a bound function to make b return a.c value`, () => { 26 | 27 | let a = { 28 | c: [1, 2, 3] 29 | }; 30 | 31 | /** 32 | * @memberof a 33 | * @returns {array} 34 | */ 35 | function b () { 36 | return this.c; 37 | } 38 | 39 | // complete the code to pass the test 40 | let w; 41 | 42 | expect(w).toBe(a.c); 43 | }); 44 | 45 | it(`call function b with a as the belonging object 46 | and provide the required argument values to pass the test`, () => { 47 | 48 | let a = { 49 | c: [1, 2, 3] 50 | }; 51 | 52 | /** 53 | * 54 | * @param {number} x 55 | * @param {number} y 56 | * @memberof a 57 | * @returns {array} 58 | */ 59 | function b (x, y) { 60 | this.x = x; 61 | this.y = y; 62 | return this.c; 63 | } 64 | 65 | // complete the code to pass the test 66 | let w; 67 | 68 | expect(w).toBe(a.c); 69 | expect(typeof a.x).toBe('number'); 70 | expect(typeof a.y).toBe('number'); 71 | }); 72 | 73 | it(`apply a as this for b and pass the required arguments to pass the test`, () => { 74 | 75 | let a = { 76 | c: [1, 2, 3] 77 | }; 78 | 79 | /** 80 | * 81 | * @param {number} x 82 | * @param {number} y 83 | * @memberof a 84 | * @returns {array} 85 | */ 86 | function b (x, y) { 87 | this.x = x; 88 | this.y = y; 89 | return this.c; 90 | } 91 | 92 | // complete the code to pass the test 93 | let w; 94 | 95 | expect(w).toBe(a.c); 96 | expect(typeof a.x).toBe('number'); 97 | expect(typeof a.y).toBe('number'); 98 | }); 99 | 100 | it(`function b should resolve this to object a`, () => { 101 | 102 | /** 103 | * 104 | * @memberof a 105 | * @returns {array} 106 | */ 107 | function b () { 108 | return this.c; 109 | } 110 | 111 | let a = { 112 | // complete the object property to pass the test 113 | c: [1, 2, 3] 114 | }; 115 | 116 | expect(a.b).toBe(b); 117 | expect(a.b()).toBe(a.c); 118 | 119 | }); 120 | 121 | it(`lexical this 122 | can you fix it?`, () => { 123 | 124 | /** 125 | * @returns {undefined|object} 126 | */ 127 | function A () { 128 | 129 | this.b = function () { 130 | // use lexical scope to fix this 131 | return function () { 132 | return this.c; 133 | }; 134 | 135 | }; 136 | 137 | this.c = 'hi'; 138 | } 139 | 140 | let a = new A(); 141 | 142 | let d = { 143 | b: a.b, 144 | c: 'bye', 145 | e: a.b() 146 | }; 147 | 148 | let f = a.b(); 149 | 150 | expect(d.b()()).toBe(d.c); 151 | expect(d.e()).toBe(a.c); 152 | expect(f()).toBe(a.c); 153 | }); 154 | }); 155 | -------------------------------------------------------------------------------- /src/day_08/classes.test.js: -------------------------------------------------------------------------------- 1 | 2 | describe('DAY 8: classes', () => { 3 | 4 | it(`complete the Dog class constructor code to fulfill the test conditions`, () => { 5 | 6 | /** 7 | * 8 | */ 9 | class Dog { 10 | 11 | /** 12 | * 13 | * @returns {Dog} 14 | */ 15 | constructor () { 16 | this.favoriteThing = `food`; 17 | } 18 | 19 | } 20 | 21 | let myDog1 = new Dog('fido'); 22 | 23 | expect(myDog1.name).toBe('fido'); 24 | expect(myDog1.favoriteThing).toBe(`food`); 25 | 26 | let myDog2 = new Dog(); 27 | 28 | expect(myDog2.name).toBe(`lonely dog without a name`); 29 | expect(myDog2.favoriteThing).toBe(`food`); 30 | 31 | }); 32 | 33 | it(`Dog should extend from Mammal`, () => { 34 | 35 | /** 36 | * 37 | */ 38 | class Mammal { 39 | 40 | /** 41 | * @returns { Mammal } 42 | */ 43 | constructor () { 44 | this.hasFur = true; 45 | this.isWarmBlooded = true; 46 | } 47 | } 48 | 49 | /** 50 | * @extends Mammal 51 | */ 52 | class Dog { 53 | 54 | /** 55 | * 56 | * @returns {Dog} 57 | */ 58 | constructor () { 59 | this.favoriteThing = `food`; 60 | } 61 | 62 | } 63 | 64 | let myDog = new Dog(); 65 | 66 | expect(myDog).toBeInstanceOf(Dog); 67 | expect(myDog).toBeInstanceOf(Mammal); 68 | expect(myDog.hasFur).toBe(true); 69 | expect(myDog.favoriteThing).toBe(`food`); 70 | 71 | }); 72 | 73 | it(`Fix the methods of Dog class so that they correctly belong to the "class" or to the "instance"`, () => { 74 | 75 | /** 76 | * 77 | */ 78 | class Dog { 79 | 80 | /** 81 | * @returns {Dog} 82 | */ 83 | constructor () { 84 | this.favoriteThing = `food`; 85 | } 86 | 87 | /** 88 | * @returns {string} 89 | */ 90 | static jump () { 91 | return `jumping`; 92 | } 93 | 94 | /** 95 | * @returns {string} 96 | */ 97 | bark () { 98 | return `barking`; 99 | } 100 | 101 | } 102 | 103 | let myDog = new Dog(); 104 | 105 | expect(myDog.jump()).toBe('jumping'); 106 | expect(() => myDog.bark()).toThrow('myDog.bark is not a function'); 107 | expect(Dog.bark()).toBe('barking'); 108 | 109 | }); 110 | 111 | it(`use the following code as a starting point 112 | change favoriteThing into a "private" property 113 | add the necessary setter and getter 114 | `, () => { 115 | 116 | /** 117 | * 118 | */ 119 | class Dog { 120 | 121 | /** 122 | * @returns {Dog} 123 | */ 124 | constructor () { 125 | this.favoriteThing = `food`; 126 | this[Symbol(`dogName`)] = ''; 127 | } 128 | 129 | /** 130 | * @param {string} name 131 | */ 132 | set name (name) { 133 | let dogNameSymbol = Object.getOwnPropertySymbols(this)[0]; 134 | this[dogNameSymbol] = name; 135 | } 136 | 137 | /** 138 | * @returns {string} 139 | */ 140 | get name () { 141 | let dogNameSymbol = Object.getOwnPropertySymbols(this)[0]; 142 | return this[dogNameSymbol]; 143 | } 144 | 145 | } 146 | 147 | let myDog = new Dog(); 148 | myDog.name = `Copernicus`; 149 | myDog.favoriteThing = `eat Aristarchus' food`; 150 | 151 | expect(myDog.name).toBe('Copernicus'); 152 | expect(myDog.favoriteThing).toBe(`eat Aristarchus' food`); 153 | expect(Object.getOwnPropertyNames(myDog)).toEqual([]); 154 | 155 | }); 156 | }); 157 | -------------------------------------------------------------------------------- /src/day_09/asyncAwait.test.js: -------------------------------------------------------------------------------- 1 | 2 | describe('DAY 9: Async/await', () => { 3 | /** 4 | * @param {string} outcome resolve|reject 5 | * @returns {Promise} 6 | */ 7 | function fetchData (outcome) { 8 | return new Promise((resolve, reject) => { 9 | setTimeout(() => { 10 | switch (outcome) { 11 | case 'resolve': 12 | resolve('data retrieved'); 13 | break; 14 | default: 15 | reject(new Error('no data')); 16 | break; 17 | } 18 | }, 50); 19 | }); 20 | } 21 | 22 | // @see https://jestjs.io/docs/en/asynchronous for a hint 23 | it(`make an async test for fetchData to verify resolution`, () => { 24 | throw new Error('replace the test body'); 25 | }); 26 | 27 | // @see https://jestjs.io/docs/en/asynchronous for a hint 28 | it(`make an async test for fetchData to verify rejection`, () => { 29 | throw new Error('replace the test body'); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /src/day_09/callback.test.js: -------------------------------------------------------------------------------- 1 | 2 | describe('DAY 9: Callback', () => { 3 | 4 | it(`(Synchronous callback) 5 | create a function named caller 6 | deduce the rest of the implementation reading the 2 expects`, () => { 7 | let callback = jest.fn(); 8 | let callbackArgument = Symbol('callbackArgument'); 9 | 10 | /** 11 | * 12 | * @param {function} callback 13 | * @returns {undefined} 14 | */ 15 | let caller = () => {}; 16 | 17 | let result = caller(callback); 18 | 19 | expect(callback).toBeCalledWith(callbackArgument); 20 | expect(result).toBe(callback); 21 | }); 22 | 23 | it(`(Asynchronous callback) 24 | change the function "caller" 25 | deduce the implementation reading the 2 expects`, done => { 26 | 27 | let callback = jest.fn(); 28 | let callbackArgument = Symbol('callbackArgument'); 29 | 30 | // @see https://jestjs.io/docs/en/asynchronous 31 | let caller = () => {}; 32 | 33 | setTimeout(() => expect(callback).toBeCalledWith(callbackArgument), 1000); 34 | 35 | setTimeout(() => caller(callback), 50); 36 | 37 | }, 2000); 38 | }); 39 | -------------------------------------------------------------------------------- /src/day_09/eventLoop.test.js: -------------------------------------------------------------------------------- 1 | 2 | describe('DAY 9: Event Loop', () => { 3 | 4 | it(`modify the initial expression of the for loop to pass the test`, done => { 5 | 6 | var i = 0; 7 | /** 8 | * 9 | * @param {number} i 10 | * @returns {undefined} 11 | */ 12 | function counter (i) { 13 | if (i === 3) { 14 | done(); 15 | } 16 | } 17 | 18 | for (var i = 0; i < 4; i++) { 19 | setTimeout(() => counter(i), 0); 20 | } 21 | 22 | expect(i).toBe(0); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /src/day_09/promise.test.js: -------------------------------------------------------------------------------- 1 | 2 | describe('DAY 9: Promises', () => { 3 | 4 | it(`validString function should return a Promise 5 | the promise should: 6 | resolve with the input value if it's a string 7 | reject with an instance of MySampleTypeError if it's not 8 | the error message should be a "Template literal" (see the catch block for a hint)`, () => { 9 | 10 | /** 11 | * 12 | * @param {*} input 13 | * @returns {Promise} 14 | */ 15 | function validateString (input) { 16 | return new Promise((resolve, reject) => { 17 | 18 | }); 19 | } 20 | 21 | let input1 = `I'm a a string`; 22 | let input2 = 5; 23 | 24 | /** 25 | * this test is not quite good 26 | * we might have false positives 27 | * ? can you tell why? 28 | */ 29 | return validateString(input1).then(resolution => { 30 | expect(resolution).toBe(`I'm a a string`); 31 | }).then(() => { 32 | return validateString(input2); 33 | }).catch((error) => { 34 | expect(error).toBeInstanceOf(TypeError); 35 | expect(error.message).toBe(`${input2} is not a string`); 36 | }); 37 | }); 38 | 39 | it(`validString function should exactly as the previous test 40 | stringToUpper function should return a Promise 41 | and will try to resolve the string to uppercase 42 | or catch the error and reject it 43 | `, () => { 44 | 45 | /** 46 | * 47 | * @param {*} input 48 | * @returns {Promise} 49 | */ 50 | function validateString (input) { 51 | return new Promise((resolve, reject) => { 52 | resolve(input); 53 | }); 54 | } 55 | 56 | /** 57 | * 58 | * @param {*} input 59 | * @returns {Promise} 60 | */ 61 | function stringToUpper (input) { 62 | return new Promise((resolve, reject) => { 63 | resolve('change me'); 64 | }); 65 | } 66 | 67 | let input = 'oo'; 68 | 69 | /** 70 | * this tests has a redundant validation 71 | * ? can you tell why is that? 72 | */ 73 | return validateString(input).then(resolution => { 74 | return stringToUpper(resolution); 75 | }).then(resolution => { 76 | expect(resolution).toBe(input.toUpperCase()); 77 | }); 78 | }); 79 | 80 | }); 81 | --------------------------------------------------------------------------------