{"id":16313425,"url":"https://github.com/alhassy/javascriptcheatsheet","last_synced_at":"2025-05-08T00:32:24.128Z","repository":{"id":60031749,"uuid":"246605253","full_name":"alhassy/JavaScriptCheatSheet","owner":"alhassy","description":"Quick reference to the tremendously accessible high-level language of the web ^_^","archived":false,"fork":false,"pushed_at":"2022-11-24T11:45:33.000Z","size":521,"stargazers_count":215,"open_issues_count":5,"forks_count":24,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-31T15:49:00.534Z","etag":null,"topics":["cheatsheet","javascript","reference"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alhassy.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-03-11T15:15:10.000Z","updated_at":"2025-02-15T20:50:00.000Z","dependencies_parsed_at":"2023-01-22T13:01:03.772Z","dependency_job_id":null,"html_url":"https://github.com/alhassy/JavaScriptCheatSheet","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alhassy%2FJavaScriptCheatSheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alhassy%2FJavaScriptCheatSheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alhassy%2FJavaScriptCheatSheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alhassy%2FJavaScriptCheatSheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alhassy","download_url":"https://codeload.github.com/alhassy/JavaScriptCheatSheet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252978270,"owners_count":21834898,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cheatsheet","javascript","reference"],"created_at":"2024-10-10T21:51:11.520Z","updated_at":"2025-05-08T00:32:24.100Z","avatar_url":"https://github.com/alhassy.png","language":null,"readme":"# Created 2020-03-13 Fri 05:54\n#+OPTIONS: toc:nil d:nil\n#+OPTIONS: toc:nil\n#+OPTIONS: toc:nil d:nil\n#+TITLE: JavaScript CheatSheet\n#+AUTHOR: [[http://www.cas.mcmaster.ca/~alhassm/][Musa Al-hassy]]\n#+export_file_name: README.org\n\nQuick reference to the tremendously accessible high-level language of the web ^_^\n\n#+begin_quote\n*The listing sheet, as PDF, can be found\n [[https://alhassy.github.io/JavaScriptCheatSheet/CheatSheet.pdf][here]]*,\n or as a [[https://alhassy.github.io/JavaScriptCheatSheet/CheatSheet_Portrait.pdf][single column portrait]],\n while below is an unruly html rendition.\n#+end_quote\n\nThis reference sheet is built from a\n[[https://github.com/alhassy/CheatSheet][CheatSheets with Org-mode]]\nsystem.\n\n#+toc: headlines 2\n#+macro: blurb Quick reference to the tremendously accessible high-level language of the web ^_^\n\n#+latex_header: \\usepackage{titling,parskip}\n#+latex_header: \\usepackage{eufrak} % for mathfrak fonts\n#+latex_header: \\usepackage{multicol,xparse,newunicodechar}\n\n#+latex_header: \\usepackage{etoolbox}\n\n#+latex_header: \\newif\\iflandscape\n#+latex_header: \\landscapetrue\n\n#+latex_header_extra: \\iflandscape \\usepackage[landscape, margin=0.5in]{geometry} \\else \\usepackage[margin=0.5in]{geometry} \\fi\n\n#+latex_header: \\def\\cheatsheetcols{2}\n#+latex_header: \\AfterEndPreamble{\\begin{multicols}{\\cheatsheetcols}}\n#+latex_header: \\AtEndDocument{ \\end{multicols} }\n\n#+latex_header: \\let\\multicolmulticols\\multicols\n#+latex_header: \\let\\endmulticolmulticols\\endmulticols\n#+latex_header: \\RenewDocumentEnvironment{multicols}{mO{}}{\\ifnum#1=1 #2 \\def\\columnbreak{} \\else \\multicolmulticols{#1}[#2] \\fi}{\\ifnum#1=1 \\else \\endmulticolmulticols\\fi}\n\n#+latex_header: \\def\\maketitle{}\n#+latex: \\fontsize{9}{10}\\selectfont\n\n#+latex_header: \\def\\cheatsheeturl{}\n\n#+latex_header: \\usepackage[dvipsnames]{xcolor} % named colours\n#+latex: \\definecolor{grey}{rgb}{0.5,0.5,0.5}\n\n#+latex_header: \\usepackage{color}\n#+latex_header: \\definecolor{darkgreen}{rgb}{0.0, 0.3, 0.1}\n#+latex_header: \\definecolor{darkblue}{rgb}{0.0, 0.1, 0.3}\n#+latex_header: \\hypersetup{colorlinks,linkcolor=darkblue,citecolor=darkblue,urlcolor=darkgreen}\n\n#+latex_header: \\setlength{\\parindent}{0pt}\n\n\n#+latex_header: \\def\\cheatsheetitemsep{-0.5em}\n#+latex_header: \\let\\olditem\\item\n#+latex_header_extra: \\def\\item{\\vspace{\\cheatsheetitemsep}\\olditem}\n\n#+latex_header: \\usepackage{CheatSheet/UnicodeSymbols}\n\n#+latex_header: \\makeatletter\n#+latex_header: \\AtBeginEnvironment{minted}{\\dontdofcolorbox}\n#+latex_header: \\def\\dontdofcolorbox{\\renewcommand\\fcolorbox[4][]{##4}}\n#+latex_header: \\makeatother\n\n\n\n#+latex_header: \\RequirePackage{fancyvrb}\n#+latex_header: \\DefineVerbatimEnvironment{verbatim}{Verbatim}{fontsize=\\scriptsize}\n\n\n#+latex_header: \\def\\cheatsheeturl{https://github.com/alhassy/JavaScriptCheatSheet}\n\n#+latex_header: \\def\\cheatsheetcols{2}\n#+latex_header: \\landscapetrue\n#+latex_header: \\def\\cheatsheetitemsep{-0.5em}\n\n#+latex_header: \\newunicodechar{𝑻}{\\ensuremath{T}}\n#+latex_header: \\newunicodechar{⊕}{\\ensuremath{\\oplus}}\n#+latex_header: \\newunicodechar{≈}{\\ensuremath{\\approx}}\n\n#+latex_header: \\newunicodechar{𝓍}{\\ensuremath{x}}\n#+latex_header: \\newunicodechar{𝓎}{\\ensuremath{y}}\n#+latex_header: \\newunicodechar{𝓈}{\\ensuremath{s}}\n#+latex_header: \\newunicodechar{𝓌}{\\ensuremath{w}}\n#+latex_header: \\newunicodechar{𝓋}{\\ensuremath{v}}\n\n#+latex_header: \\newunicodechar{ʸ}{\\ensuremath{^y}}\n#+latex_header: \\newunicodechar{₋}{\\ensuremath{_{-}}}\n#+latex_header: \\newunicodechar{₁}{\\ensuremath{_1}}\n\n#+begin_quote\n- [[#intro][Intro]]\n- [[#types][Types]]\n- [[#variable-bindings][Variable Bindings]]\n- [[#scope-and-statements][Scope and Statements]]\n- [[#arithmetic][Arithmetic]]\n- [[#booleans][Booleans]]\n  - [[#empty-values][Empty Values]]\n- [[#strings][Strings]]\n  - [[#string-methods][String Methods]]\n  - [[#method-names-shared-with-arrays][Method Names Shared with Arrays]]\n  - [[#treating-strings-as-arrays][Treating Strings as Arrays]]\n- [[#arrays][Arrays]]\n  - [[#array-methods][Array methods]]\n- [[#functions][Functions]]\n  - [[#intro-1][Intro]]\n  - [[#default-values][Default Values]]\n  - [[#rest-parameters][Rest Parameters]]\n  - [[#higher-order-functions][Higher-order Functions]]\n- [[#destructuring-and-the-spread-operator][Destructuring and the “spread” Operator]]\n- [[#objects][Objects]]\n  - [[#object-creation][Object Creation]]\n  - [[#getters-and-setters----get-set][Getters and Setters -- ~get, set~]]\n  - [[#dictionries-or-maps][Dictionries or maps]]\n- [[#the-this-keyword][The ~this~ Keyword]]\n  - [[#call][~Call~]]\n  - [[#the-this-of-parent-scopes][The ~this~ of Parent Scopes]]\n- [[#object-oriented-programming][Object-Oriented Programming]]\n  - [[#intro-2][Intro]]\n  - [[#adding-new-methods-or-overriding-methods][Adding New Methods or Overriding Methods]]\n  - [[#inheritance-and-null-parents][Inheritance and Null Parents]]\n  - [[#1-prototype-example][⟨1⟩ Prototype Example]]\n  - [[#2-manual-constructor-functions][⟨2⟩ Manual Constructor Functions]]\n  - [[#3-constructor-functions-with-new][⟨3⟩ Constructor Functions with ~new~]]\n  - [[#4-class-notation][⟨4⟩ ~class~ Notation]]\n- [[#the-iterator-interface][The Iterator Interface]]\n- [[#javascript-and-the-browser][JavaScript and the Browser]]\n  - [[#large-scripts][Large Scripts]]\n- [[#break][Break]]\n- [[#reads][Reads]]\n- [[#some-fun-stuff-_][Some Fun Stuff ^_^]]\n#+end_quote\n\n#+latex: \\vspace{1em}\n\nJavaScript is what everyone calls the language, but that name is [[https://softwareengineering.stackexchange.com/questions/135905/legal-ramifications-of-use-of-the-javascript-trademark][trademarked]] (by\nOracle, which inherited the trademark from Sun). Therefore, the official name of\nJavaScript is ECMAScript. The “ECMA” in “ECMAScript” comes from the organisation\nthat hosts the primary standard, the European Computer Manufacturers\nAssociation.\n\nAs the programming language of browsers, it is remarkably error-tolerant. It\nsimply “fails silently” by giving error values such as ~undefined~ when things\nare not there or ~0 / 0 ≈ NaN~ for nonsensical numeric expressions.\n\nBy accident, there are two (mostly) /interchangeable/ values ~null~ and\n~undefined~ that denote the absence of a meaningful value. Many operations that\ndon't produce meaningful values yield ~undefined~ simply because they have to\nyield /some/ value. [[https://funcall.blogspot.com/2007/11/in-kingdom-of-nouns.html?m=1][Here]] is a neat story about null.\n\n#+latex: \\vspace{-1em}\n* Types\n\nJavaScript considers types only when actually running the program, and even\nthere often tries to implicitly convert values to the type it expects.\n\n- ~typeof~ gives a string value naming the type of its argument.\n- The functions ~Number, String, Boolean~ try to convert values into those\n  types.\n#+begin_src js\n  console.log(typeof 4.5, typeof '4.5', typeof true)\n  // ⇒ number string boolean\n\n  console.log(8 * null // Multiplication needs numbers so null ↦ 0\n               , 'five' * 2 // 'five' is not a number, so 'five' ↦ NaN\n               , '5' - 1    // Subtraction needs numbers so '5' ↦ 5\n               , '5' + 1)   // The first is a string, \n                            // so “+” denotes catenation, so 1 ↦ '1'\n\n  console.log(Number('2.3')   // ⇒ 2.3\n             ,Number('five')  // ⇒ NaN\n             ,Boolean('five') // ⇒ true\n             ,Boolean('')     // ⇒ false\n             ,String(NaN)     // ⇒ 'NaN'\n             ,String(null))  // ⇒ 'null'\n#+end_src\n\n#+results: \n: 2.3 NaN true false NaN null\n#+latex: \\vspace{-1em}\n* Variable Bindings\n\n~let x₀ = v₀, …, xₙ = vₙ;~ introduces 𝓃-new names ~xᵢ~ each having value ~vᵢ~.\n- The ~vᵢ~ are optional, defaulting to ~undefined~.\n- The program crashes if any ~xᵢ~ is already declared.\n- Later we use ~xᵢ = wᵢ;~ to update the name ~xᵢ~ to refer to a new value\n  ~wᵢ~.\n  - Augmented updates: ~x ⊕= y ≡ x = x ⊕ y~\n  - Increment: ~x-- ≡ x += 1~\n  - Decrement: ~y-- ≡ x -= 1~\n\n#+begin_src js\n  let x, y = 1, z;\n  console.log(x, y, z); // ⇒ undefined 1 undefined\n#+end_src\n\n- In the same way, for the same purpose, we may use ~var~ but it has undesirable\n  properties; e.g., its declarations are in the global scope and no error is\n  raised using ~var x = ⋯~ if ~x~ is already declared.\n\n- In the same way, we may use ~const~ to introduce names that are constant: Any\n  attempt to change their values crashes the program.\n\n- A binding name may include dollar signs ($) or underscores (_) but no other\n  punctuation or special characters.\n\n* Scope and Statements\n\nEach binding has a scope, which is the part of the program in which\nthe binding is visible. For bindings defined outside of any function\nor block, the scope is the whole program—you can refer to such\nbindings wherever you want. These are called global.\n\n#+begin_parallel\n#+begin_src js\n  let x = 10;\n\n  { // new local scope\n    let y = 20;\n    var z = 30;\n    console.log(x + y + z); // ⇒ 60\n  }\n\n  // y is not visible here\n  // console.log(y)\n\n  // But z is!\n  console.log(x + z); // ⇒ 40\n#+end_src\n\n#+latex: \\columnbreak\n\n#+latex: \\vspace{2em}\n⊙ /global bindings/ are defined outside of any block and can be referenced anywhere.\n\n#+latex: \\vspace{1em}\n⊙ /local bindings/ are defined within a block and can only be referenced in it.\n\n#+latex: \\vspace{1em}\n⊙ =let, const= declare local bindings;  =var= always makes global ones!\n#+end_parallel\n\n\nBesides the assignment statement, we also have the following statements:\n- Conditionals:\n  ~if (condition) A else B~\n- Blocks:\n  If ~Sᵢ~ are statements, then ~{S₀; …; Sₙ;}~ is a statement.\n- The ~for/of~ syntax applies to arrays, strings, and other iterable structures\n  ---we will define our own later.  \n  #+begin_src js\n    // Print all the elements in the given list.\n    for (let x of ['a', 1, 2.3]) {\n      console.log(`x ≈ ${x}`);\n      }\n  #+end_src\n\nJavaScript is whitespace insensitive.\n\n#+latex: \\vspace{-1em}\n* [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number][Arithmetic]]\n\nIn addition to the standard arithmetic operations, we have ~Math.max(x₀, …, xₙ)~\nthat takes any number of numbers and gives the largest; likewise ~Math.min(⋯)~.\nOther common functions include ~Math.sqrt, Math.ceil, Math.round, Math.abs,~ and\n~Math.random()~ which returns a random number between 0 and 1.\nAlso, use ~%~ for remainder after division.\n\n#+begin_src js\n  // Scientific notation: 𝓍e𝓎 ≈ 𝓍 × 10ʸ\n  console.log(1, 2.998e8, 100 + 4 * 11)\n\n  // Special numbers so that division “never crashes”.\n  console.log(1/0, -1/0, Infinity - 10) // ⇒ Infinity -Infinity Infinity\n  console.log(Infinity - Infinity, 0/0) // ⇒ NaN NaN\n\n  // Random number in range min...Max\n  Math.floor(Math.random() * (max - min) + min)\n#+end_src\n\n~NaN~ stands for “not a number”, it is what you get when a numeric expression\n    has no meaningful value.\n\n- Any ~NaN~ in an arithmetic expressions swallows the whole expression into a ~NaN~.\n\n- ~Number.isNaN(x)~ is true iff ~x~ is ~NaN~.\n\nEverything is equal to itself, except ~NaN~. Why? ~NaN~ denotes the result of\nnonsensical computations, and so is not equal to the result of any other\nnonsensical computation.\n#+begin_src js\n  console.log(NaN == NaN) // ⇒ false\n#+end_src\n\n#+results: \n: false\n\n* [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean][Booleans]]\n\nThe empty string =''=, list =[]=, and ~0, NaN~ are falsey ---all else is truthy.\n- Note: ~(p \u003c q \u003c r) ≈ (p \u003c q) \u003c r~, it is not conjunctive!\n\n#+begin_src js\n  console.log(true, false, 3 \u003e 2, 1 \u003c 2, 1 != 2, 4 \u003c= 2 \u003c 3)\n\n  // Upper case letters come first, then lower case ones.\n  console.log('abc' \u003c 'def', 'Z' \u003c 'a')\n\n  // Equality with coercions, and without.\n  console.log(1.23 == '1.23', 1.23 === '1.23')\n#+end_src\n\n#+results: \n: true false true true true true false\n: true true\n: true false\n\n\n- /Precise Equality/ ~===~ is equality with no type coercions.\n\n- Applying the “not” =!= operator will convert a value to Boolean type before negating\n  it.\n\n- Precedence: Relationals like ~==~ and ~\u003e~ are first, then “and” ~\u0026\u0026~, then “or” ~||~.\n\n- The ternary operator: =condition ? if_true : if_false=\n\n** Empty Values\n\n#+begin_src js\n  console.log(null == undefined) // ⇒ true\n#+end_src\n\n#+results: \n: true\n\n\nOnly the empty values are coerced into being equal, no other value\nis equal to an empty value. As such, ~x != null~ means that ~x~ is not an\nempty value, and is in fact a real meaningful value.\n\nSince ~\u0026\u0026~ and ~||~ are lazy, ~x || y~ means return ~x~ if ~x != false~\nand otherwise return ~y~; i.e., /give me x if it's non-empty, else y/.\n\nLikewise, ~x \u0026\u0026 y~ means /give me y, if x is nonempty, else give me the particular\nempty value x/.\n\n#+begin_src js\n  console.log( 4  == 3   \u0026\u0026 4   // 3 is truthy \n             ,''  == ''  \u0026\u0026 4   // '' is falsey\n             ,'H' == 'H' \u0026\u0026 4   // 'H' is truthy\n             , 0  == 0   \u0026\u0026 4   // 0 is falsey\n             , 4  == 0   || 4   // 0 is falsey\n             )\n#+end_src\n\n#+results: \n* [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String][Strings]]\n\nAny pair of matching single-quotes, backticks, or double-quotes will produce a\nstring literal. However, backticks come with extra support: They can span\nmultiple lines and produce /formatted strings/, where an expression can be\nevaluated if it is enclosed in ~${⋯}~.\n\n#+begin_src js\n  console.log(`half of 100 is ${100 / 2}`) // ⇒ half of 100 is 50\n#+end_src\n\n** String Methods\n\n- ~s.repeat(𝓃)~ ≈ Get a new string by gluing 𝓃-copies of the string 𝓈.\n- Trim removes spaces, newlines, tabs, and other whitespace from the start and end of a string.\n  #+begin_src js\n    console.log(\"  okay \\n \".trim()); // ⇒ okay\n  #+end_src\n- ~s.toUpperCase()~ and ~s.toLowerCase()~ to change case.\n- ~𝓈.padStart(𝓁, 𝓅)~ ≈ Ensure 𝓈 is of length ≥ 𝓁 by padding it with 𝓅 at the start.\n  #+begin_src js\n    console.log(String(6).padStart(3, \"0\")); // ⇒ 006\n  #+end_src\n- ~𝓈.replace(/./g, c =\u003e p(c) ? f(c) : '')~ ≈ Keep only the characters that\n  satisfy predicate ~p~, then transform them via ~f~.\n  #+begin_src js\n    let s = 'abcde'.replace(/./g, c =\u003e 'ace'.includes(c) ? c.toUpperCase() : '')\n    console.log(s); // ⇒ ACE\n  #+end_src\n\n** Method Names Shared with Arrays\n\nThe following methods also apply to arrays.\n- ~s.length~ ⇒ Length of string\n- ~s[𝒾]~ ⇒ Get the 𝒾-th character from the start\n  - Unless ~0 ≤ 𝒾 \u003c s.length~, we have ~s[𝒾] = undefined~.\n- ~s.concat(t)~ ⇒ Glue together two strings into one longer string; i.e., ~s + t~.\n  #+begin_src js\n    console.log(('cat' + 'enation').toUpperCase()) // ⇒ CATENATION\n  #+end_src\n- ~s.includes(t)~ ⇒ Does ~s~ contain ~t~ as a substring?\n- ~s.indexOf(t)~ ⇒ Where does substring ~t~ start in ~s~, or -1 if it's not in ~s~.\n  - To search from the end instead of the start, use ~lastIndexOf~.\n- ~s.slice(𝓂,𝓃)~ ⇒ Get the substring between indices 𝓂 (inclusive) and 𝓃 (exclusive).\n  - 𝓃 is optional, defaulting to ~s.length~.\n  - If 𝓃 is negative, it means start from the end: ~s.slice(-𝓃) ≈ s.slice(s.length - 𝓃)~.\n  - ~s.slice()~ ⇒ Gives a copy of ~s~.\n\n** Treating Strings as Arrays\n\n- There is no character type, instead characters are just strings of length 1.\n- You can “split” a string on every occurrence of another string to get a list\n  of words, and which you can “join” to get a new sentence. ~𝓈.split(𝒹).join(𝒹) ≈ 𝓈~.\n- To treat a string as an array of characters, so we can apply array only methods such\n  as ~f = reverse~, we can use split and join:\n  | ~𝓈.split('').f().join('')~ |\n- Keeping certain characters is best done with regular expressions.\n\n* [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array][Arrays]]\nArray indexing, ~arr[𝒾]~, yields the 𝒾-th element from the start; i.e., the\nnumber of items to skip; whence ~arr[0]~ is the first element.\n\n#+begin_parallel\n#+begin_src js\n  let numbers = [];\n\n  numbers.push(2);\n  numbers.push(5);\n  numbers.push(7);\n\n  // or \n  numbers = [2, 5, 7]\n\n  console.log(numbers[2]); // ⇒ 7\n  let last = numbers.pop() // ⇒ 7\n  console.log(numbers) // ⇒ [ 2, 5 ]\n\n  // ⇒ undefined\n  console.log(numbers[2]);\n\n  // Is an element in the array? No.\n  console.log(numbers.includes(7)) \n\n  numbers  = numbers.concat('ola')\n  console.log(numbers)\n  // ⇒ [ 2, 5, 'ola' ]\n\n  console.log(numbers.reverse()) \n  // ⇒ [ 'ola', 5, 2 ]\n#+end_src\n\n#+results: \n: 7\n: [ 2, 5 ]\n: undefined\n: false\n: [ 2, 5, 'ola' ]\n: [ 'ola', 5, 2 ]\n#+end_parallel\n\n#+latex: \\vspace{-1em}\n(*Stack*) The push method adds values to the end of an array, and the pop method\ndoes the opposite, removing the last value in the array and returning it.\n(*Queue*) The corresponding methods for adding and removing things at the start\nof an array are called ~unshift~ and ~shift~, respectively.\n\nArrays have the following methods, which behave similar to the string ones from earlier.\n| ~length~ | ~concat~ | ~includes~ | ~indexOf~ | ~lastIndexOf~ | ~slice~ |\n\nOne difference is that unlike string's ~indexOf~, which searches for substrings, array's\n~indexOf~ searches for a specific value, a single element.\n\n#+begin_src js\n  console.log([1, 2, 3, 2, 1].indexOf(2));     // ⇒ 1\n  console.log([1, 2, 3, 2, 1].lastIndexOf(2)); // ⇒ 3\n#+end_src\n\nThe ~concat~ method can be used to glue arrays together to create a new array,\nsimilar to what the ~+~ operator does for strings.\n- If you pass ~concat~ an argument that is not an array, that value will be added\n  to the new array as if it were a one-element array. This is a ~push~.\n\n~Array(𝓃).fill(𝓍)~ ≈ Get a new array of 𝓃-copies of element 𝓍.\n** Array methods\n\n#+latex: \\vspace{1em}\n\n- ~xs.forEach(a)~ to loop over the elements in an array and perform action ~a~.\n- ~xs.filter(p)~ returns a new array containing only the elements that pass the predicate ~p~.\n- ~xs.map(f)~  transforms an array by putting each element through the function ~f~.\n- ~xs.reduce(f, e)~ combines all the elements in an array into a single value. \n  - We can omit the starting value ~e~ if the array ~xs~ is non-empty,\n    in which case ~e~ is taken to be the first element ~xs[0]~.\n- ~xs.some(p)~ tests whether any element matches a given predicate function ~p~.\n  - ~xs.every(p)~ tests if every element of ~xs~ satisfies ~p~.\n- ~xs.findIndex(p)~ finds the position of the first element that matches the predicate ~p~.\n\nWith the exception of ~forEach~, the above functions do not modify the array\nthey are given.\n\n#+begin_src js\n  // Print the elements of the given array\n  [`a`, `b`, `c`].forEach(l =\u003e console.log(l));\n\n  // ∃/∀\n  console.log([1, 2, 3].some(e =\u003e e == 2))  // true\n  console.log([1, 2, 3].every(e =\u003e e == 2)) // false\n\n  // Sum the elements of an array\n  console.log([1, 2, 3, 4].reduce((soFar, current) =\u003e soFar + current)); // ⇒ 10\n\n  // flatten an array of arrays\n  let flatten = (xss) =\u003e xss.reduce((sofar, xs) =\u003e sofar.concat(xs), [])\n\n  let arrays = [[1, 2, 3], [4, 5], [6]]; \n  console.log(flatten(arrays)) // ⇒ [ 1, 2, 3, 4, 5, 6 ]\n#+end_src\n\nHigher-order functions start to shine when you need to compose operations.\n\n* [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function][Functions]]\n\nFunction values can do all the things that other values can do; i.e., they can\nbe used in arbitrary expressions; e.g., a binding that holds a function is still\njust a regular binding and can, if not constant, be assigned a new value.\n\n- A ~function~ definition is a regular binding where the value of the binding is a\n  function.\n\n  Functions declared using the top-level ~function~ keyword may be used before\n  their declarations.\n\n#+begin_parallel\n\n\n#+begin_src js\n  const square = function(x) {\n    return x * x;\n  };\n\n  console.log(square(12)); // ⇒ 144\n#+end_src\n\n#+begin_src js\n  // Shorter way to define functions\n  console.log(square2(12));\n  function square2(x) {\n    return x * x;\n  }\n#+end_src\n#+end_parallel\n\n#+latex: \\vspace{-0.5em}\n- A ~return~ keyword without an expression after it will cause the\n  function to return ~undefined~.\n\n- Functions that don’t have a ~return~ statement at all, similarly return\n  ~undefined~.\n\n- Declaring ~function f (⋯) {⋯}~ will not raise a warning if the name ~f~\n  is already in use ---similar to ~var~.\n\n- One may also define functions using “arrow” notation: ~(x₀, …, xₙ) =\u003e ⋯~.\n  - When there is only one parameter name, you can omit the parentheses around\n    the parameter list.\n  - If the body is a single expression, rather than a (multi-line) block in\n    braces, that expression will be returned from the function.\n\n  So, these two definitions of square do the same thing:  \n  #+begin_src js\n    const square1 = (x) =\u003e { return x * x; };\n    const square2 =  x  =\u003e x * x;\n  #+end_src\n\n#+latex: \\vspace{-0.5em}\nAs will be seen, arrow functions are [[https://stackoverflow.com/a/34361380/3550444][not exactly]] the same as declared functions.\n\n*JavaScript is extremely fault-tolerant:* If we give a function more arguments\nthan it needs, the extra arguments are just ignored.\nIf we give it too few arguments, the missing arguments are assigned ~undefined~.\n\n#+begin_src js\n  // Extra arguments are ignored\n  console.log(square(4, true, \"hedgehog\")); // ⇒ 16\n\n  // No longer a function!\n  square = 'g'\n#+end_src\n** Default Values\n\n(*Default Values*)\nIf you write an = operator after a parameter, followed by an expression, the\nvalue of that expression will replace the argument when it is not given.\n\n#+begin_src js\n  let square = (x = 1) =\u003e x * x;\n  console.log(square(3)); // ⇒ 9\n  console.log(square());  // ⇒ 1\n#+end_src\n\n** Rest Parameters\n\n(*Rest Parameters*)\nIt can be useful for a function to accept any number of arguments. For example,\n~Math.max~ computes the maximum of all the arguments it is given. To write such\na function, you put three dots before the function’s last parameter, which is called\n“the rest parameter” and it is treated as an array containing all further arguments.\n\n#+begin_parallel\n#+begin_src js\n  function max(...numbers) {\n    let result = -Infinity;\n    for (let number of numbers) {\n      if (number \u003e result)\n        result = number;\n    }\n    return result;\n  }\n\n  console.log(max(4, 1, 9, -2));  // ⇒ 9\n#+end_src\n#+latex: \\columnbreak\nYou can use a similar three-dot notation to call a function with an array of arguments.\n#+latex: \\vspace{1em}\n#+begin_src js\n  let numbers = [5, 1, 7];\n  console.log(max(...numbers));\n  // ⇒ 7\n#+end_src\n#+end_parallel\n\nThis “spreads” out the array into the function call, passing its elements as\nseparate arguments. It is possible to include an array like that along with\nother arguments, as in ~max(9, ...numbers, 2)~.\n\n** Higher-order Functions\n\n*Higher-order functions* allow us to abstract over actions, not just values.\nThey come in several forms. \n\nFor example, we can have functions that create new functions.\n#+begin_src js\n  let greaterThan   = n =\u003e (m =\u003e m \u003e n);\n  let greaterThan10 = greaterThan(10);\n  console.log(greaterThan10(11)); // ⇒ true\n#+end_src\n\nAnd we can have functions that change other functions. (*Decorators*)\n\n#+begin_src js\n  function noisy(f) {\n    return (...args) =\u003e {\n      let result = f(...args);\n      console.log(`Called: ${f.name}(${args}) ≈ ${result}`);\n      return result;\n    };\n  }\n  noisy(Math.min)(3, 2, 1); // Called: min(3,2,1) ≈ 1\n#+end_src\n\nWe can even write functions that provide new types of control flow.\n\n#+begin_parallel\n#+begin_src js\n  function unless(test, then) {\n    if (!test) then();\n  }\n#+end_src\n#+latex: \\columnbreak\n#+begin_src js\n  let n = 8;\n  unless(n % 2 == 1, () =\u003e {\n      console.log(n, \"is even\");\n    });\n  // ⇒ 8 is even\n#+end_src\n#+end_parallel\n\n#+latex: \\vspace{-2em}\n* Destructuring and the “spread” Operator\n\nIf you know the value you are binding is an array/object, you can use []/{} brackets\nto “look inside” of the value, binding its contents.\n\n#+latex: \\vspace{-0.3em}\nOne of the reasons the ~doit~ function below is awkward to read is that we have\na binding pointing at our array, but we’d much prefer to have bindings for the\nelements of the array, whence the second definition of ~doit~.\n\n#+latex: \\vspace{-0.3em}\n#+begin_src js\n  let xs = [9, 11, 22, 666, 999];\n\n  // The following are the same.\n  function doit(xs){ return xs[0] + xs[1] + xs[2]; }\n  function doit([x, y, z]) {return x + y + z; }\n  //\n  // Only first three items accessed in “doit”; extra args are ignored as usual.\n  console.log(doit(xs)) \n\n  // Destructuring to get first three elements and remaining\n  let x = xs[0], y = xs[1], z = xs[2], ws = xs.slice(3);\n  console.log(x, y, z, ws) // ⇒ 9 11 22 [ 666, 999 ]\n  // Nice! Same thing.\n  let [a, b, c, ...ds] = xs \n  console.log(a, b, c, ds) // ⇒ 9 11 22 [ 666, 999 ]\n\n  // Destructuring to get first and remaining elements\n  let [head, ...tail] = xs\n  console.log(head, tail) // ⇒ 9 [ 11, 22, 666, 999 ]\n\n  // Destructuring on an object to get two properties and the remaining subobject \n  let {name, age, ...more} = {name: \"Musa\", age: 72, x: 1, y: 2}\n  console.log(name, age, more) // ⇒ Musa 72 { x: 1, y: 2 }\n\n  // Destructuring: Simultaneous assignment!\n  var p = 1, q = 2    // ⇒ 1, 2\n  var [p, q] = [q, p] // swap them\n  console.log(p, q)   // ⇒ 2, 1\n\n  // Unpacking: f(...[x₀, …, xₙ]) ≈ f(x₀, …, xₙ)\n  console.log(Math.min(...xs)) // ⇒ 9\n\n  // Unpacking: Merging arrays/objects\n  let ys = [1, ...xs, 2, 3] // ⇒ 1, 9, 11, 22, 666, 999, 2, 3\n  let zs = {w: 0, ...more, z: 3} // ⇒ { w: 0, x: 1, y: 2, z: 3 }\n\n  // Updating a property, a key-value pair\n  zs = {...zs, w: -1} // ⇒ { w: -1, x: 1, y: 2, z: 3 }\n#+end_src\n\nNote that if you try to destructure ~null~ or ~undefined~, you get an error,\nmuch as you would if you directly try to access a property of those values.\n\n#+begin_src js\n     let {x₀, …, xₙ, ...𝓌} = 𝓋                                       \n  ≡ let x₀ = 𝓋.x₀, …, xₙ = 𝓋.xₙ; 𝓌 = 𝓋; delete 𝓌.x₀, …, delete 𝓌.xₙ\n#+end_src\n\nAs usual, in arrow functions, we may destructure according to the shape\nof the elements of the array; e.g., if they are lists of at least length 2\nwe use ~(soFar, [x, y]) =\u003e ⋯~. This may be useful in higher order functions\nsuch as ~map, filter, reduce~.\n\n* [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object][Objects]]\n\nObjects and arrays (which are a specific kind of object) provide ways to group\nseveral values into a single value. Conceptually, this allows us to put a bunch\nof related things in a bag and run around with the bag, instead of wrapping our\narms around all of the individual things and trying to hold on to them\nseparately. These “things” are called /properties/.\n\nArrays are just a kind of object specialised for storing sequences of things.\n\n** Object Creation\n\nValues of the type /object/ are arbitrary collections of properties. One way to\ncreate an object is by using braces as an expression that lists properties as /“name:value”/\npairs.\n\n1. Almost all JavaScript /values/ have properties. The exceptions are ~null~ and\n   ~undefined~. If you try to access a property on one of these nonvalues, you get\n   an error. Properties are accessed using ~value.prop~ or ~value[\"prop\"]~.\n\n2. Whereas ~value.x~ fetches the property of value named /x/, ~value[e]~ tries to\n   evaluate the expression ~e~ and uses the result, converted to a string, as the\n   property name.\n\n3. The dot notation only works with properties whose names look like valid\n   (variable) binding names. So if you want to access a property named ~2~ or ~John\n      Doe~, you must use square brackets: ~value[2]~ or ~value[\"John Doe\"]~.\n\n4. Unless ~value~ contains a property ~x~, we have ~value.x ≈ undefined~.\n   - Hence, out of bounds indexing results in ~undefined~.\n\n5. Notice that the ~this~ keyword allows us to refer to other parts of /this/\n   object literal. Above, ~info~ used the ~person~ object's information, whereas\n   ~speak~ did not. The ~“this”~ keyword is covered in more detail below.\n\n6. Variables names in an object literal, like ~languages~, denote a shorthand\n   for a property with the same and value, but otherwise is no longer related to\n   that binding.\n\n   This is useful if we want multiple objects to have the same binding; e.g.,\n   with ~let x = ⋯, a = {name: 'a', x}, b = {name: 'b', x}~, both objects have\n   a ~x~ property: ~a.x~ and ~b.x~.\n\n7. We cannot dynamically attach new properties to the atomic types String, Number, Boolean;   \n   e.g., ~let x = 2; x.vest = 'purple'; console.log(x.vest);~ prints ~undefined~.\n   We can write it, but they “don't stick”.\n\n8. Below, we could have begun with the empty object then added properties dynamically:\n   ~let person = {}; person.name = `musa`; person.age = 29; …~.\n\n#+latex: \\columnbreak\n#+begin_src js\n  let languages = ['js', 'python', 'lisp']\n  let person = { name: 'musa'\n               , age: 27\n               , 'favourite number': 1\n               , languages // Shorthand for “languages: ['js', 'python', 'lisp']”\n               , age: 29  // Later bindings override earlier ones.\n               // Two ways to attach methods; the second is a shorthand.\n               , speak: () =\u003e `Salamun Alaykum! Hello!`\n               , info () { return `${this.name} is ${this.age} years old!`; }\n               };\n\n  console.log(person.age) // ⇒ 29\n\n  // Trying to access non-existent properties\n  // Reading a property that doesn’t exist will give you the value undefined.\n  console.log(person.height) // ⇒ undefined\n              \n  // Is the property “name” in object “person”?\n  console.log('name' in person); // ⇒ true\n\n  // Updating a (computed) property\n  let prop = 'favourite' + ' ' + 'number'\n  person['favourite number'] = 1792       \n  console.log(person[prop]) // ⇒ 1792\n\n  // Dynamically adding a new property\n  person.vest = 'purple'\n  console.log(person.vest) // ⇒ purple\n\n  // Discard a property\n  delete person['favourite number']\n\n  // Get the list of property names that an object *currently* has.\n  console.log(Object.keys(person)) // ⇒ [ 'name', 'age', 'languages', 'vest' ]\n\n  // Variables can contribute to object definitions, but are otherwise unrelated.\n  languages = ['C#', 'Ruby', 'Prolog']\n  console.log(person.languages) // ⇒ [ 'js', 'python', 'lisp' ]\n\n  // Calling an object's methods\n  console.log(person.speak()) // ⇒ Salamun Alaykum! Hello!\n  console.log(person.info())  // ⇒ musa is 29 years old!\n#+end_src\n\n** Getters and Setters -- ~get, set~\n\nYou can define getters and setters to secretly call methods every time an\nobject’s property is accessed. E.g., below ~num~ lets you read and write\n~value~ as any number, but internally the getter method is called which only\nshows you the value's remainder after division by the modulus property.\n\n#+latex: \\vspace{-1em}\n#+begin_src js\n  let num = { modulus: 10\n            , get value() { return this._secret % this.modulus; }\n            , set value(val) { this._secret = val; } }\n#+end_src\n\n#+begin_parallel\n#+begin_src js\n  num.value = 99\n  console.log(num._secret) // ⇒ 99\n#+end_src\n#+latex: \\columnbreak\n#+begin_src js\n  console.log(num.value) // ⇒ 9\n  num.modulus = 12;\n  console.log(num.value) // ⇒ 3\n#+end_src\n#+end_parallel\n\n#+latex: \\vspace{-1.5em}\n- Exercise: Make an object ~num~ such that ~num.value~ varies, returning\n  a random number less than 100, each time it's accessed.\n\nUsing ~get, set~ is a way to furnish prototypes with well-behaved properties\nthat are readable or writable, or both.\n\n** Dictionries or maps\n\nAn object can also be used as a /“key:value”/ dictionary: When we ‘look-up’ a key,\nwe find a particular value. E.g., with ~ages = {mark: 12, james: 23, larry: 42}~\nwe use ~ages.mark~ to find Mark's age.\n\nSimilarly, objects can be used to simulate /keyword arguments/ in function calls.\n\n#+latex: \\vspace{-1em}\n* The ~this~ Keyword\n\nUsually a method needs to do something with the object it was called on. When a\nfunction is called as a method --- looked up as a property and immediately\ncalled, as in ~object.method()~ —-- the binding called ~this~ in its body\nautomatically points at the object that it was called on.\n\n#+begin_src js\n  function speak(line) {\n    console.log(`The ${this.type} rabbit says '${line}'`);\n  }\n  let whiteRabbit  = {type: \"white\", speak};\n  let hungryRabbit = {type: \"hungry\", speak};\n\n  whiteRabbit.speak(\"Hola!\"); // ⇒ The white rabbit says 'Hola!'\n  hungryRabbit.speak(\"Hey!\")  // ⇒ The hungry rabbit says 'Hey!'\n#+end_src\n\n** ~Call~\nYou can think of ~this~ as an extra parameter that is passed in a different way.\nIf you want to pass it explicitly, you can use a function’s ~call~ method, which\ntakes the ~this~ value as its first argument and treats further arguments as\nnormal parameters.\n\n#+begin_src js\n  speak.call(hungryRabbit, \"Burp!\");\n  // ⇒ The hungry rabbit says 'Burp!'\n#+end_src\n\nWith ~call~, an object can use a method belonging to another object. E.g., below\nwe use ~whiteRabbit~'s speaking method with its ~this~ keywords referring to\n~exoticRabbit~.\n\n#+begin_src js\n  let exoticRabbit = {type: 'exotic'}\n\n  whiteRabbit.speak.call(exoticRabbit, `Jambo!`) \n  // ⇒ The exotic rabbit says 'Jambo!'\n#+end_src\n\n#+results: \n\n** The ~this~ of Parent Scopes\nSince each function has its own ~this~ binding, whose value depends on the way it\nis called, you cannot refer to the ~this~ of the wrapping scope in a regular\nfunction defined with the function keyword.\n\nArrow functions are different ---they do not bind their own ~this~ but can see the\n~this~ binding of the scope around them. Thus, you can do something like the\nfollowing code, which references ~this~ from inside a local function:\n#+begin_src js\n  function normalise() {\n    console.log(this.coords.map(n =\u003e n / this.length));\n  }\n  normalise.call({coords: [0, 2, 3], length: 5}); // ⇒ [0, 0.4, 0.6]\n#+end_src\n\nIf we had written the argument to ~map~ using the ~function~ keyword, the code wouldn’t work.\n\n* Object-Oriented Programming\n\nIn English, /prototype/ means a preliminary model of something from which\nother forms are developed or /copied/. As such, a /prototypical/ object\nis an object denoting the original or typical form of something.\n\nIn addition to their properties, JavaScript objects also have prototype ---i.e.,\nanother object that is used as a source of additional properties. When an object\ngets a request for a property that it does not have, its prototype will be\nsearched for the property, then the prototype’s prototype, and so on.\n\n- ~Object.getPrototypeOf(x)~ returns the prototype of an object ~x~.\n\nFor example, arrays are derived from ~Array.prototype~ which is derived from\n~Object.prototype~ ---which is the great ancestral prototype, the entity behind\nalmost all object. ~Object.prototype~ provides a few methods that show up in all\nobjects, such as ~toString~, which converts an object to a string representation.\n\n- We can use the ~Object.getOwnPropertyNames(x)~ to get all the property names\n  linked to object ~x~.\n\nIt is occasionally useful to know whether an object was derived from a specific\nclass. For this, JavaScript provides a binary operator called ~instanceof~.\nAlmost every object is an instance of Object.\n\n- ~𝓍 instanceof 𝓎  ≈  Object.getPrototypeOf(𝓍) == 𝓎.prototype~\n\n#+begin_src js\n   // “Object” includes “toString”, and some other technical utilities.\n   console.log(Object.getOwnPropertyNames(Object.prototype))\n\n  // Some true facts\n  console.log( {}       instanceof Object\n             , []       instanceof Array\n             , Math.max instanceof Function\n             , Math.max instanceof Object) // Since Function derives from Object\n\n  // “Object” has no parent prototype.\n  console.log(Object.getPrototypeOf(Object.prototype)); // ⇒ null\n#+end_src\n** Adding New Methods or Overriding Methods\n\n(*Extension Methods / Open Classes*) To attach a new property to a ‘kind’ of\nobject, we simply need to attach it to the prototype ---since all those ‘kinds’\nof objects use the prototype's properties.\nLet's attach a new method that can be used with /any/ array.   \n\n#+latex: \\vspace{-0.5em}\n#+begin_src js\n  Array.prototype.max = function () { \n     console.log('ola'); return Math.max(...this)\n     }\n\n  console.log([3,1,5].max()); // ⇒ Prints “ola”, returns 5\n\n  console.log(Object.getOwnPropertyNames(Array.prototype))\n  // ⇒ Includes length, slice, …, and our new “max” from above\n#+end_src\n\nWhen you call the ~String~ function (which converts a value to a string) on an\nobject, it will call the ~toString~ method on that object to try to create a\nmeaningful string from it.\n\n#+latex: \\vspace{-0.5em}\n#+begin_src js\n  Array.prototype.toString = function() { return this.join(' and '); };\n  console.log(String([1, 2, 3])) // ⇒ 1 and 2 and 3\n#+end_src\n\n(*Overriding*)\nWhen you add a property to an object, whether it is present in the prototype or\nnot, the property is added to the object itself. If there was already a property\nwith the same name in the prototype, this property will no longer affect the\nobject, as it is now hidden behind the object’s own property.\n#+latex: \\vspace{-0.5em}\n\n#+begin_parallel\n#+begin_src js\n  Array.prototype.colour = 'purple'\n\n  let xs = [1, 2, 3]\n  console.log(xs.colour) // ⇒ purple\n#+end_src\n#+latex: \\columnbreak\n#+begin_src js\n  xs.colour = 'green'\n  console.log(xs.colour) // ⇒ green\n\n  console.log(Array.prototype.colour)\n  // ⇒ purple \n#+end_src\n#+end_parallel\n\n#+latex: \\vspace{-1em}\n\n** Inheritance and Null Parents\n\nYou can use ~Object.create~ to create an object with a specific prototype.\nThe default prototype is ~Object.prototype~. For the most part,\n~Object.create(someObject) ≈ { ...someObject }~; i.e., we /copy/ the properties\nof ~someObject~ into an empty object, thereby treating ~someObject~ as a prototype\nfrom which we will build more sophisticated objects.\n\nUnlike other object-oriented languages where ~Object~ sits as the ancestor of /all/\nobjects, in JavaScript it is possible to create objects with no prototype parent!\n\n#+begin_src js\n  // Empty object that *does* derive from “Object”\n  let basic = {}\n  console.log( basic instanceof Object // ⇒ true\n             , \"toString\" in basic)    // ⇒ true\n\n  // Empty object that does not derive from “Object”\n  let maximal = Object.create(null);\n  console.log( maximal instanceof Object // ⇒ false\n             , \"toString\" in maximal)    // ⇒ false\n#+end_src\n\n** ⟨1⟩ Prototype Example                                            :classes:\n\nPrototypes let us define properties that are the same for all instances,\nbut properties that differ per instance are stored directly in the objects themselves.\nE.g., the prototypical person acts as a container for the properties that are shared\nby all people. An individual person object, like ~kathy~ below, contains properties\nthat apply only to itself, such as its name, and derives shared properties from\nits prototype.\n\n#+latex: \\vspace{-0.5em}\n#+begin_src js\n  // An example object prototype\n  let prototypicalPerson    = {};\n  prototypicalPerson._world = 0;\n  prototypicalPerson.speak  = function () {\n    console.log(`I am ${this.name}, a ${this.job}, in a world of `\n                 + `${prototypicalPerson._world} people.`) }\n  prototypicalPerson.job = `farmer`;\n  \n  // Example use: Manually ensure the necessary properties are setup\n  // and then manually increment the number of people in the world.\n  let person = Object.create(prototypicalPerson);\n  person.name = `jasim`;\n  prototypicalPerson._world++;\n  person.speak() // ⇒ I am jasim, a farmer, in a world of 1 people.\n\n  // Another person requires just as much setup\n  let kathy = { ...prototypicalPerson }; // Same as “Object.create(⋯)”\n  kathy.name = `kathy`;\n  prototypicalPerson._world++;\n  kathy.speak() // ⇒ I am kathy, a farmer, in a world of 2 people.\n#+end_src\n** ⟨2⟩ Manual Constructor Functions                                 :classes:\n\n#+latex: \\vspace{0.5em}\n| /Classes are prototypes along with constructor functions!/ |\n\nA /class/ defines the shape of a kind of object; i.e., what properties it has;\ne.g., a Person can ~speak~, as all people can, but should have its own ~name~\nproperty to speak of. This idea is realised as a prototype along with a\n/constructor/ function that ensures an instance object not only derives from the\nproper prototype but also ensures it, itself, has the properties that instances\nof the class are supposed to have.\n\n#+begin_src js\n  let prototypicalPerson    = {};\n  prototypicalPerson._world = 0;\n  prototypicalPerson.speak  = function () {\n    console.log(`I am ${this.name}, a ${this.job}, in a world of `\n                 + `${prototypicalPerson._world} people.`) }\n\n  function makePerson(name, job = `farmer`) {\n    let person  = Object.create(prototypicalPerson);\n    person.name = name;\n    person.job  = job;\n    prototypicalPerson._world++;\n    return person;\n  }\n\n  // Example use\n  let jasim = makePerson(`jasim`);\n  jasim.speak() // I am jasim, a farmer, in a world of 1 people.\n  makePerson(`kathy`).speak() // I am kathy, a farmer, in a world of 2 people.\n#+end_src\n\n#+results: \n: I am jasim, a farmer, in a world of 1 people.\n: I am kathy, a farmer, in a world of 2 people.\n\n** ⟨3⟩ Constructor Functions with ~new~                             :classes:\nWe can fuse these under one name by making the prototype a part of the constructor.\n- By convention, the names of constructors are capitalised so that they can\n  easily be distinguished from other functions.\n#+begin_src js\n  function Person(name, job = `farmer`) {\n   this.name = name;\n   this.job  = job;\n   Person.prototype._world++;\n  }\n\n  Person.prototype._world = 0;\n  Person.prototype.speak = function () {\n    console.log(`I am ${this.name}, a ${this.job}, in a world of `\n                 + `${Person.prototype._world} people.`) }\n\n  // Example use\n  let jasim = Object.create(Person.prototype)\n  Person.call(jasim, `jasim`)\n  jasim.speak() // ⇒ I am jasim, a farmer, in a world of 1 people.\n\n  // Example using shorthand\n  let kasim = new Person (`kathy`)\n  kasim.speak()  // ⇒ I am kathy, a farmer, in a world of 2 people.\n#+end_src\n\n#+results: \n: I am jasim, a farmer, in a world of 1 people.\n: I am kathy, a farmer, in a world of 2 people.\n\n\nIf you put the keyword ~new~ in front of a function call, the function is\ntreated as a constructor. This means that an object with the right prototype is\nautomatically created, bound to ~this~ in the function, and returned at the end\nof the function.\n\n\n#+begin_src js\n    new f(args)                                                                   \n  ≈ (_ =\u003e let THIS = Object.create(f.prototype);\n          f.call(THIS, args); return THIS;) ()\n#+end_src\n\nAll functions automatically get a property named ~prototype~, which by default\nholds a plain, empty object that derives from ~Object.prototype~. You can\noverwrite it with a new object if you want. Or you can add properties to the\nexisting object, as the example does.\n\nNotice that the ~Person~ object /derives/ from ~Function.prototype~,\nbut also has a /property/ named ~prototype~ which is used for instances\ncreated through it.\n#+begin_src js\n  console.log( Object.getPrototypeOf(Person) == Function.prototype\n             , Person instanceof Function\n             , jasim  instanceof Person\n             , Object.getPrototypeOf(jasim) == Person.prototype)\n#+end_src\n\nHence, we can update our motto:\n| /Classes are constructor functions with a prototype property!/ |\n\n** ⟨4⟩ ~class~ Notation                                             :classes:\nRather than declaring a constructor, /then/ attaching properties to its prototype,\nwe may perform both steps together using ~class~ notation shorthand.\n#+begin_src js\n  class Person {\n    static #world = 0\n    constructor(name, job = `farmer`) { \n      this.name = name;\n      this.job  = job;\n      Person.#world++;\n    }\n    speak() {\n      console.log(`I am ${this.name}, a ${this.job}, in a world of `\n                 + `${Person.#world} people.`) \n    }               \n  }\n\n  // Example use\n\n  let jasim = new Person(`jasim`)\n  jasim.speak()               \n  // ⇒ I am jasim, a farmer, in a world of 1 people.\n\n  new Person(`kathy`).speak()\n  // ⇒ I am kathy, a farmer, in a world of 2 people.\n#+end_src\n\n#+results: \n: I am jasim, a farmer, in a world of 1 people.\n: I am kathy, a farmer, in a world of 2 people.\n\n\nNotice that there is a special function named ~constructor~ which is \nbound to the class name, ~Person~, outside the class. The remainder of the\nclass declarations are bound to the constructor's prototype.\nThus, the earlier class declaration is equivalent to the constructor\ndefinition from the previous section. It just looks nicer.\n- Actually, this is even better: The ~static #world = 0~ declaration makes the\n  property ~world~ /private/, completely inaccessible from the outside the\n  class. The ~static~ keyword attaches the name not to particular instances\n  (~this~) but rather to the constructor/class name (~Person~).\n- Indeed, in the previous examples we could have accidentally messed-up our world count.\n  Now, we get an error if we write ~Person.#world~ outside of the class.\n\n* The Iterator Interface\n\nThe object given to a ~for/of~ loop is expected to be iterable. This means it\nhas a method named ~Symbol.iterator~. When called, that method should return an\nobject that provides a second interface, the iterator. This is the actual thing\nthat iterates. It has a ~next~ method that returns the next result. That result\nshould be an object with a ~value~ property that provides the next value, if\nthere is one, and a ~done~ property, which should be true when there are no more\nresults and false otherwise.\n\nLet's make an iterable to traverse expression trees.\n#+begin_src js\n  class Expr { // [0] Our type of expression trees\n    static Constant(x) { \n       let e = new Expr();\n       e.tag = 'constant', e.constant = x; \n       return e; \n       }\n\n    static Plus(l, r) { \n       let e = new Expr();\n       e.tag = 'plus', e.left = l, e.right = r;\n       return e; \n       }\n  }\n\n  // [1] The class tracks the progress of iterating over an expression tree\n  class ExprIterator {\n    constructor(expr) { this.expr = expr; this.unvisited = [{expr, depth: 0}]; }\n    next () {\n     if(this.unvisited.length == 0) return {done: true};\n     let {expr , depth} = this.unvisited.pop();\n     if (expr.tag == 'constant') return {value: {num: expr.constant, depth}}\n     if (expr.tag == 'plus') {\n       // pre-order traversal\n       this.unvisited.push({expr: expr.right, depth: depth + 1})\n       this.unvisited.push({expr: expr.left, depth: depth + 1})\n       }\n     return this.next()\n    }\n  }\n\n  // [2] We can add the iterator after-the-fact rather than within the Expr class.\n  Expr.prototype[Symbol.iterator] = function () { return new ExprIterator(this) }\n\n  // [3] Here's some helpers and an example.\n  let num = (i) =\u003e Expr.Constant(i)\n  let sum = (l, r) =\u003e Expr.Plus(l, r)\n  // test ≈ 1 +  (2 + (3 + 4))\n  let test = sum( num(1), sum( num(2), sum(num(3), num(4))))\n  // console.log(test) // ⇒ Nice looking tree ^_^\n\n  // [4] We now loop over an expression with for/of\n  for (let {num, depth} of test)\n    console.log(`${num} is ${depth} deep in the expression`)\n#+end_src\n\nRecall that inside a class declaration, methods that have ~static~ written\nbefore their name are *stored on* the constructor. It appears that static\nproperties are shared by all instances, because the constructor /object/ has\nthese as properties rather than particular instance objects.\n#+latex: \\vspace{-1em}\n* JavaScript and the Browser\n\nBrowsers run JavaScript programs, which may be dangerous and so browsers limit\nwhat a program may do ---e.g., it cannot look at your files.\n\nAn HTML document is a nested sequence of tagged items, which may be interpreted\nas a living data-structure ---with the screen reflecting any modifications.\n- The most important HTML tag is ~\u003cscript\u003e~. This tag allows us to include a\n  piece of JavaScript in a document.\n\nThe data-structure is called the *Document Object Model*, or /DOM/, and it is\naccessed with the variable ~document~.\n- The DOM interface wasn't designed for just JavaScript; e.g., it can be used with XML.\nCall the following snippet ~test.html~, then open it in your favourite browser.\n#+begin_src html :tangle ~/Downloads/testing2.html\n  \u003ctitle\u003e Ola! \u003c/title\u003e\n\n  \u003ch3 id=\"myHeader\"\u003e\u003c/h3\u003e\n\n  \u003cscript\u003e\n  alert(`Welcome to my webapge!`);\n\n  let count = 0;\n  function modifyThePage(){\n    document.title = `New zany title ~ ${Math.random()}`;\n    myHeader.innerText = `New zany heading ~ ${count}`;\n    count += Math.floor(Math.random() * 10);\n  }\n  \u003c/script\u003e\n\n  \u003cbutton onclick=\"modifyThePage();\"\u003eChange the title and header \u003c/button\u003e\n#+end_src\n\nSuch a script will run as soon as its ~\u003cscript\u003e~ tag is encountered while the\nbrowser reads the HTML. This page will pop up a dialog when opened to show a\nmessage.\n\nSome attributes can also contain a JavaScript program. The ~\u003cbutton\u003e~ tag shows\nup as a button and has an ~onclick~ attribute whose value (function) will be run\nwhenever the button is clicked.\n\nNotice that by providing ID's to tags, we may refer to them in our JavaScript code.\n\n** Large Scripts\n\nIncluding large programs directly in HTML documents is often impractical. The\n~\u003cscript\u003e~ tag can be given a ~src~ attribute to fetch a script file (a text file\ncontaining a JavaScript program) from a URL.\n\n#+begin_src html\n  \u003ch1\u003eTesting alert\u003c/h1\u003e\n  \u003cscript src=\"code/hello.js\"\u003e\u003c/script\u003e\n#+end_src\n\nThe ~code/hello.js~ file included here contains the simple program ~alert(\"hello!\")~.\n\n#+latex: \\columnbreak\n* Reads\n\n- https://eloquentjavascript.net/\n\n  /This is a book about JavaScript, programming, and the wonders of the digital./\n\n  Many of the examples in this cheatsheet were taken from this excellent read!\n\n- https://exploringjs.com/index.html\n\n  /Exploring JS: Free JavaScript books for programmers/\n  ---E.g., “JavaScript for impatient programmers”\n\n- https://www.w3schools.com/js/\n\n  /This tutorial will teach you JavaScript from basic to advanced./\n\n  Other bite-sized lessions can be found at: https://masteringjs.io/fundamentals\n\n- https://learnxinyminutes.com/docs/javascript/\n\n  /Take a whirlwind tour of your next favorite language. Community-driven!/\n\n- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference\n\n  /The JavaScript reference serves as a repository of facts about the JavaScript\n  language. The entire language is described here in detail./\n\n- https://github.com/you-dont-need/You-Dont-Need-Loops\n\n  /Avoid The One-off Problem, Infinite Loops, Statefulness and Hidden intent./\n\n* Some Fun Stuff ^_^\n#+begin_src js\n  // A “quine” is a program that prints itself, such as this one:\n  f = _ =\u003e console.log(`f = ${f};f()`); f()\n  // Prints:\n  // f = _ =\u003e console.log(`f = ${f};f()`);f()\n\n  // Range of numbers. Including start, excluding end.\n  let range = (start, end) =\u003e [...Array(end - start).keys()].map(x =\u003e x + start)\n  console.log(range(3, 8)) // ⇒ [ 3, 4, 5, 6, 7 ]\n\n  // Flatten an array\n  let xss     = [[1, 2, 3], [4, 5, 6]]\n  let flatten = xss =\u003e [].concat(...xss)\n  console.log(flatten(xss)) // ⇒ [ 1, 2, 3, 4, 5, 6 ]\n\n  // Randomise the elements of an array\n  let shuffle = (arr) =\u003e arr.slice().sort(() =\u003e Math.random() - 0.5)\n  let xs = [1, 2, 3, 4, 5, 6] \n  console.log(shuffle(xs)) // ⇒ [ 5, 1, 4, 6, 2, 3 ]\n#+end_src\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falhassy%2Fjavascriptcheatsheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falhassy%2Fjavascriptcheatsheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falhassy%2Fjavascriptcheatsheet/lists"}