JavaScript Notes For Professionals2
JavaScript Notes For Professionals2
JavaScript
Notes for Professionals Contents
®
About ................................................................................................................................................................................... 1
Chapter 1: Getting started with JavaScript ..................................................................................................... 2
Section 1.1: Using [Link]() ..................................................................................................................................... 2
400+ pages Section 7.1: Basic Info and String Concatenation ..................................................................................................... 37
Section 7.2: Reverse String ......................................................................................................................................... 38
Section 7.3: Comparing Strings Lexicographically ................................................................................................... 39
of professional hints and tricks Section 7.4: Access character at index in string ....................................................................................................... 40
Section 7.5: Escaping quotes ...................................................................................................................................... 40
Section 7.6: Word Counter .......................................................................................................................................... 41
Disclaimer
[Link] This is an unocial free book created for educational purposes and is
not aliated with ocial JavaScript® group(s) or company(s).
Free Programming Books All trademarks and registered trademarks are
the property of their respective owners
Section 7.7: Trim whitespace ...................................................................................................................................... 41 Section 12.4: Filtering Object Arrays .......................................................................................................................... 84
Section 7.8: Splitting a string into an array .............................................................................................................. 41 Section 12.5: Sorting Arrays ........................................................................................................................................ 86
Section 7.9: Strings are unicode ................................................................................................................................. 42 Section 12.6: Iteration .................................................................................................................................................. 88
Section 7.10: Detecting a string .................................................................................................................................. 42 Section 12.7: Destructuring an array ......................................................................................................................... 92
Section 7.11: Substrings with slice ............................................................................................................................... 43 Section 12.8: Removing duplicate elements ............................................................................................................. 93
Section 7.12: Character code ...................................................................................................................................... 43 Section 12.9: Array comparison ................................................................................................................................. 93
Section 7.13: String Representations of Numbers .................................................................................................... 43 Section 12.10: Reversing arrays .................................................................................................................................. 94
Section 7.14: String Find and Replace Functions ...................................................................................................... 44 Section 12.11: Shallow cloning an array ..................................................................................................................... 95
Section 7.15: Find the index of a substring inside a string ....................................................................................... 45 Section 12.12: Concatenating Arrays ......................................................................................................................... 95
Section 7.16: String to Upper Case ............................................................................................................................. 45 Section 12.13: Merge two array as key value pair .................................................................................................... 97
Section 7.17: String to Lower Case ............................................................................................................................. 46 Section 12.14: Array spread / rest .............................................................................................................................. 97
Section 7.18: Repeat a String ...................................................................................................................................... 46 Section 12.15: Filtering values ..................................................................................................................................... 98
Chapter 8: Date ........................................................................................................................................................... 47 Section 12.16: Searching an Array .............................................................................................................................. 99
Section 8.1: Create a new Date object ....................................................................................................................... 47 Section 12.17: Convert a String to an Array ............................................................................................................ 100
Section 8.2: Convert to a string format .................................................................................................................... 49 Section 12.18: Removing items from an array ........................................................................................................ 100
Section 8.3: Creating a Date from UTC ..................................................................................................................... 50 Section 12.19: Removing all elements ...................................................................................................................... 101
Section 8.4: Formatting a JavaScript date ............................................................................................................... 53 Section 12.20: Finding the minimum or maximum element .................................................................................. 102
Section 8.5: Get the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC ................................. 55 Section 12.21: Standard array initialization ............................................................................................................. 103
Section 8.6: Get the current time and date ............................................................................................................... 55 Section 12.22: Joining array elements in a string .................................................................................................. 104
Section 8.7: Increment a Date Object ....................................................................................................................... 56 Section 12.23: Removing/Adding elements using splice() .................................................................................... 105
Section 8.8: Convert to JSON ..................................................................................................................................... 57 Section 12.24: The entries() method ........................................................................................................................ 105
Section 12.25: Remove value from array ................................................................................................................ 105
Chapter 9: Date Comparison ................................................................................................................................ 58
Section 12.26: Flattening Arrays .............................................................................................................................. 106
Section 9.1: Comparing Date values .......................................................................................................................... 58
Section 12.27: Append / Prepend items to Array ................................................................................................... 107
Section 9.2: Date Dierence Calculation .................................................................................................................. 59
Section 12.28: Object keys and values to array ..................................................................................................... 107
Chapter 10: Comparison Operations ................................................................................................................ 60
Section 12.29: Logical connective of values ........................................................................................................... 108
Section 10.1: Abstract equality / inequality and type conversion ........................................................................... 60
Section 12.30: Checking if an object is an Array .................................................................................................... 108
Section 10.2: NaN Property of the Global Object ..................................................................................................... 61
Section 12.31: Insert an item into an array at a specific index .............................................................................. 109
Section 10.3: Short-circuiting in boolean operators ................................................................................................. 63
Section 12.32: Sorting multidimensional array ....................................................................................................... 109
Section 10.4: Null and Undefined ............................................................................................................................... 65
Section 12.33: Test all array items for equality ...................................................................................................... 110
Section 10.5: Abstract Equality (==) ........................................................................................................................... 65
Section 12.34: Copy part of an Array ...................................................................................................................... 110
Section 10.6: Logic Operators with Booleans ........................................................................................................... 66
Chapter 13: Objects .................................................................................................................................................. 112
Section 10.7: Automatic Type Conversions ............................................................................................................... 67
Section 13.1: Shallow cloning ..................................................................................................................................... 112
Section 10.8: Logic Operators with Non-boolean values (boolean coercion) ....................................................... 67
Section 13.2: [Link] ........................................................................................................................................ 112
Section 10.9: Empty Array ........................................................................................................................................... 68
Section 13.3: Object cloning ...................................................................................................................................... 113
Section 10.10: Equality comparison operations ........................................................................................................ 68
Section 13.4: Object properties iteration ................................................................................................................. 114
Section 10.11: Relational operators (<, <=, >, >=) ........................................................................................................ 70
Section 13.5: [Link] ........................................................................................................................................ 115
Section 10.12: Inequality .............................................................................................................................................. 71
Section 13.6: Object rest/spread (...) ........................................................................................................................ 116
Section 10.13: List of Comparison Operators ............................................................................................................ 72
Section 13.7: [Link]fineProperty ......................................................................................................................... 116
Section 10.14: Grouping multiple logic statements ................................................................................................... 72
Section 13.8: Accesor properties (get and set) ....................................................................................................... 117
Section 10.15: Bit fields to optimise comparison of multi state data ...................................................................... 72
Section 13.9: Dynamic / variable property names ................................................................................................ 117
Chapter 11: Conditions .............................................................................................................................................. 74
Section 13.10: Arrays are Objects ............................................................................................................................. 118
Section 11.1: Ternary operators .................................................................................................................................. 74
Section 13.11: [Link] ........................................................................................................................................... 119
Section 11.2: Switch statement .................................................................................................................................... 75
Section 13.12: Convert object's values to array ...................................................................................................... 120
Section 11.3: If / Else If / Else Control ......................................................................................................................... 77
Section 13.13: Retrieving properties from an object ............................................................................................... 120
Section 11.4: Strategy ................................................................................................................................................... 78
Section 13.14: Read-Only property ........................................................................................................................... 123
Section 11.5: Using || and && short circuiting ............................................................................................................. 79
Section 13.15: Non enumerable property ................................................................................................................ 123
Chapter 12: Arrays ...................................................................................................................................................... 80 Section 13.16: Lock property description ................................................................................................................. 123
Section 12.1: Converting Array-like Objects to Arrays ............................................................................................. 80 Section 13.17: [Link] ................................................................................................... 124
Section 12.2: Reducing values .................................................................................................................................... 82 Section 13.18: Descriptors and Named Properties ................................................................................................. 124
Section 12.3: Mapping values ..................................................................................................................................... 84 Section 13.19: [Link] ......................................................................................................................................... 126
Section 13.20: Properties with special characters or reserved words .................................................................. 126 Section 18.7: "do ... while" loop .................................................................................................................................. 161
Section 13.21: Creating an Iterable object ............................................................................................................... 127 Section 18.8: Break and continue labels ................................................................................................................. 161
Section 13.22: Iterating over Object entries - [Link]() .............................................................................. 127 Chapter 19: Functions ............................................................................................................................................. 163
Section 13.23: [Link]() ................................................................................................................................... 128 Section 19.1: Function Scoping .................................................................................................................................. 163
Chapter 14: Arithmetic (Math) ........................................................................................................................... 129 Section 19.2: Currying ................................................................................................................................................ 164
Section 14.1: Constants .............................................................................................................................................. 129 Section 19.3: Immediately Invoked Function Expressions ..................................................................................... 165
Section 14.2: Remainder / Modulus (%) .................................................................................................................. 129 Section 19.4: Named Functions ................................................................................................................................ 166
Section 14.3: Rounding .............................................................................................................................................. 130 Section 19.5: Binding `this` and arguments ............................................................................................................. 169
Section 14.4: Trigonometry ....................................................................................................................................... 132 Section 19.6: Functions with an Unknown Number of Arguments (variadic functions) ..................................... 171
Section 14.5: Bitwise operators ................................................................................................................................ 133 Section 19.7: Anonymous Function .......................................................................................................................... 172
Section 14.6: Incrementing (++) ................................................................................................................................ 135 Section 19.8: Default parameters ............................................................................................................................ 174
Section 14.7: Exponentiation ([Link]() or **) ..................................................................................................... 135 Section 19.9: Call and apply ...................................................................................................................................... 176
Section 14.8: Random Integers and Floats ............................................................................................................. 136 Section 19.10: Partial Application .............................................................................................................................. 177
Section 14.9: Addition (+) .......................................................................................................................................... 137 Section 19.11: Passing arguments by reference or value ....................................................................................... 178
Section 14.10: Little / Big endian for typed arrays when using bitwise operators .............................................. 137 Section 19.12: Function Arguments, "arguments" object, rest and spread parameters .................................... 179
Section 14.11: Get Random Between Two Numbers ............................................................................................... 138 Section 19.13: Function Composition ........................................................................................................................ 179
Section 14.12: Simulating events with dierent probabilities ................................................................................. 139 Section 19.14: Get the name of a function object ................................................................................................... 180
Section 14.13: Subtraction (-) .................................................................................................................................... 140 Section 19.15: Recursive Function ............................................................................................................................. 180
Section 14.14: Multiplication (*) ................................................................................................................................. 140 Section 19.16: Using the Return Statement ............................................................................................................. 181
Section 14.15: Getting maximum and minimum ..................................................................................................... 140 Section 19.17: Functions as a variable ..................................................................................................................... 182
Section 14.16: Restrict Number to Min/Max Range ................................................................................................ 141 Chapter 20: Functional JavaScript .................................................................................................................. 185
Section 14.17: Ceiling and Floor ................................................................................................................................ 141 Section 20.1: Higher-Order Functions ...................................................................................................................... 185
Section 14.18: Getting roots of a number ................................................................................................................ 142 Section 20.2: Identity Monad ................................................................................................................................... 185
Section 14.19: Random with gaussian distribution ................................................................................................. 142 Section 20.3: Pure Functions .................................................................................................................................... 187
Section 14.20: Math.atan2 to find direction ............................................................................................................ 143 Section 20.4: Accepting Functions as Arguments ................................................................................................. 188
Section 14.21: Sin & Cos to create a vector given direction & distance ............................................................... 143
Chapter 21: Prototypes, objects ........................................................................................................................ 190
Section 14.22: [Link] ......................................................................................................................................... 144
Section 21.1: Creation and initialising Prototype ..................................................................................................... 190
Section 14.23: Periodic functions using [Link] .................................................................................................... 145
Chapter 22: Classes ................................................................................................................................................. 192
Section 14.24: Division (/) ......................................................................................................................................... 146
Section 22.1: Class Constructor ................................................................................................................................ 192
Section 14.25: Decrementing (--) ............................................................................................................................. 146
Section 22.2: Class Inheritance ................................................................................................................................ 192
Chapter 15: Bitwise operators ............................................................................................................................ 148
Section 22.3: Static Methods .................................................................................................................................... 193
Section 15.1: Bitwise operators ................................................................................................................................. 148
Section 22.4: Getters and Setters ............................................................................................................................ 193
Section 15.2: Shift Operators .................................................................................................................................... 150
Section 22.5: Private Members ................................................................................................................................ 194
Chapter 16: Constructor functions ................................................................................................................... 151 Section 22.6: Methods ............................................................................................................................................... 195
Section 16.1: Declaring a constructor function ........................................................................................................ 151 Section 22.7: Dynamic Method Names ................................................................................................................... 195
Chapter 17: Declarations and Assignments ................................................................................................ 152 Section 22.8: Managing Private Data with Classes ............................................................................................... 196
Section 17.1: Modifying constants ............................................................................................................................ 152 Section 22.9: Class Name binding ........................................................................................................................... 198
Section 17.2: Declaring and initializing constants .................................................................................................. 152 Chapter 23: Namespacing .................................................................................................................................... 199
Section 17.3: Declaration ........................................................................................................................................... 152 Section 23.1: Namespace by direct assignment .................................................................................................... 199
Section 17.4: Undefined ............................................................................................................................................. 153 Section 23.2: Nested Namespaces .......................................................................................................................... 199
Section 17.5: Data Types ........................................................................................................................................... 153
Chapter 24: Context (this) .................................................................................................................................... 200
Section 17.6: Mathematic operations and assignment .......................................................................................... 153
Section 24.1: this with simple objects ....................................................................................................................... 200
Section 17.7: Assignment ........................................................................................................................................... 155
Section 24.2: Saving this for use in nested functions / objects ............................................................................ 200
Chapter 18: Loops ..................................................................................................................................................... 156 Section 24.3: Binding function context .................................................................................................................... 201
Section 18.1: Standard "for" loops ............................................................................................................................ 156 Section 24.4: this in constructor functions .............................................................................................................. 202
Section 18.2: "for ... of" loop ...................................................................................................................................... 157
Chapter 25: Setters and Getters ...................................................................................................................... 203
Section 18.3: "for ... in" loop ....................................................................................................................................... 159
Section 25.1: Defining a Setter/Getter Using [Link]fineProperty ................................................................... 203
Section 18.4: "while" Loops ....................................................................................................................................... 159
Section 25.2: Defining an Setter/Getter in a Newly Created Object ................................................................... 203
Section 18.5: "continue" a loop ................................................................................................................................. 160
Section 25.3: Defining getters and setters in ES6 class ......................................................................................... 203
Section 18.6: Break specific nested loops ............................................................................................................... 161
Chapter 26: Events ................................................................................................................................................... 205 Section 34.1: Accessing data attributes ................................................................................................................... 233
Section 26.1: Page, DOM and Browser loading ...................................................................................................... 205 Chapter 35: JSON ..................................................................................................................................................... 234
Chapter 27: Inheritance ......................................................................................................................................... 206 Section 35.1: JSON versus JavaScript literals ......................................................................................................... 234
Section 27.1: Standard function prototype ............................................................................................................. 206 Section 35.2: Parsing with a reviver function ......................................................................................................... 235
Section 27.2: Dierence between [Link] and [Link] ............................................................ 206 Section 35.3: Serializing a value ............................................................................................................................... 236
Section 27.3: Prototypal inheritance ....................................................................................................................... 206 Section 35.4: Serializing and restoring class instances ......................................................................................... 237
Section 27.4: Pseudo-classical inheritance ............................................................................................................. 207 Section 35.5: Serializing with a replacer function .................................................................................................. 238
Section 27.5: Setting an Object's prototype ........................................................................................................... 208 Section 35.6: Parsing a simple JSON string ............................................................................................................ 239
Section 35.7: Cyclic object values ............................................................................................................................ 239
Chapter 28: Method Chaining ............................................................................................................................. 210
Section 28.1: Chainable object design and chaining .............................................................................................. 210 Chapter 36: AJAX ...................................................................................................................................................... 240
Section 28.2: Method Chaining ................................................................................................................................ 212 Section 36.1: Sending and Receiving JSON Data via POST .................................................................................. 240
Section 36.2: Add an AJAX preloader ..................................................................................................................... 240
Chapter 29: Callbacks ............................................................................................................................................. 213
Section 36.3: Displaying the top JavaScript questions of the month from Stack Overflow's API .................... 241
Section 29.1: Simple Callback Usage Examples ..................................................................................................... 213
Section 36.4: Using GET with parameters ............................................................................................................... 242
Section 29.2: Continuation (synchronous and asynchronous) ............................................................................ 214
Section 36.5: Check if a file exists via a HEAD request .......................................................................................... 243
Section 29.3: What is a callback? ............................................................................................................................ 215
Section 36.6: Using GET and no parameters .......................................................................................................... 243
Section 29.4: Callbacks and `this` ............................................................................................................................ 216
Section 36.7: Listening to AJAX events at a global level ....................................................................................... 243
Section 29.5: Callback using Arrow function .......................................................................................................... 217
Section 29.6: Error handling and control-flow branching ..................................................................................... 218 Chapter 37: Enumerations ................................................................................................................................... 244
Section 37.1: Enum definition using [Link]() ............................................................................................... 244
Chapter 30: Intervals and Timeouts ............................................................................................................... 219
Section 37.2: Alternate definition ............................................................................................................................. 244
Section 30.1: Recursive setTimeout ......................................................................................................................... 219
Section 37.3: Printing an enum variable ................................................................................................................. 244
Section 30.2: Intervals ............................................................................................................................................... 219
Section 37.4: Implementing Enums Using Symbols ............................................................................................... 245
Section 30.3: Intervals ............................................................................................................................................... 219
Section 37.5: Automatic Enumeration Value .......................................................................................................... 245
Section 30.4: Removing intervals ............................................................................................................................ 220
Section 30.5: Removing timeouts ............................................................................................................................ 220 Chapter 38: Map ........................................................................................................................................................ 247
Section 30.6: setTimeout, order of operations, clearTimeout .............................................................................. 220 Section 38.1: Creating a Map .................................................................................................................................... 247
Section 38.2: Clearing a Map ................................................................................................................................... 247
Chapter 31: Regular expressions ....................................................................................................................... 222
Section 38.3: Removing an element from a Map .................................................................................................. 247
Section 31.1: Creating a RegExp Object ................................................................................................................... 222
Section 38.4: Checking if a key exists in a Map ...................................................................................................... 248
Section 31.2: RegExp Flags ....................................................................................................................................... 222
Section 38.5: Iterating Maps ..................................................................................................................................... 248
Section 31.3: Check if string contains pattern using .test() .................................................................................... 223
Section 38.6: Getting and setting elements ............................................................................................................ 248
Section 31.4: Matching With .exec() ......................................................................................................................... 223
Section 38.7: Getting the number of elements of a Map ...................................................................................... 249
Section 31.5: Using RegExp With Strings ................................................................................................................. 223
Section 31.6: RegExp Groups .................................................................................................................................... 224 Chapter 39: Timestamps ....................................................................................................................................... 250
Section 31.7: Replacing string match with a callback function ............................................................................. 225 Section 39.1: High-resolution timestamps ............................................................................................................... 250
Section 31.8: Using [Link]() with parentheses regex to extract matches of a string ................................ 226 Section 39.2: Get Timestamp in Seconds ................................................................................................................ 250
Section 39.3: Low-resolution timestamps ............................................................................................................... 250
Chapter 32: Cookies ................................................................................................................................................. 228
Section 39.4: Support for legacy browsers ............................................................................................................. 250
Section 32.1: Test if cookies are enabled ................................................................................................................ 228
Section 32.2: Adding and Setting Cookies .............................................................................................................. 228 Chapter 40: Unary Operators ........................................................................................................................... 251
Section 32.3: Reading cookies ................................................................................................................................. 228 Section 40.1: Overview .............................................................................................................................................. 251
Section 32.4: Removing cookies .............................................................................................................................. 228 Section 40.2: The typeof operator .......................................................................................................................... 251
Section 40.3: The delete operator ........................................................................................................................... 252
Chapter 33: Web Storage ..................................................................................................................................... 229
Section 40.4: The unary plus operator (+) .............................................................................................................. 253
Section 33.1: Using localStorage .............................................................................................................................. 229
Section 40.5: The void operator .............................................................................................................................. 254
Section 33.2: Simpler way of handling Storage ..................................................................................................... 229
Section 40.6: The unary negation operator (-) ...................................................................................................... 255
Section 33.3: Storage events .................................................................................................................................... 230
Section 40.7: The bitwise NOT operator (~) ............................................................................................................ 255
Section 33.4: sessionStorage .................................................................................................................................... 231
Section 40.8: The logical NOT operator (!) ............................................................................................................. 256
Section 33.5: localStorage length ............................................................................................................................ 232
Section 33.6: Error conditions ................................................................................................................................... 232 Chapter 41: Generators ......................................................................................................................................... 258
Section 33.7: Clearing storage ................................................................................................................................. 232 Section 41.1: Generator Functions ............................................................................................................................ 258
Section 33.8: Remove Storage Item ........................................................................................................................ 232 Section 41.2: Sending Values to Generator ............................................................................................................. 259
Section 41.3: Delegating to other Generator .......................................................................................................... 259
Chapter 34: Data attributes ............................................................................................................................... 233
Section 41.4: Iteration ................................................................................................................................................ 259 Chapter 49: The Event Loop ............................................................................................................................... 292
Section 41.5: Async flow with generators ................................................................................................................ 260 Section 49.1: The event loop in a web browser ...................................................................................................... 292
Section 41.6: Iterator-Observer interface ................................................................................................................ 261 Section 49.2: Asynchronous operations and the event loop ................................................................................ 293
Chapter 42: Promises ............................................................................................................................................. 263 Chapter 50: Strict mode ....................................................................................................................................... 294
Section 42.1: Introduction .......................................................................................................................................... 263 Section 50.1: For entire scripts ................................................................................................................................. 294
Section 42.2: Promise chaining ................................................................................................................................ 264 Section 50.2: For functions ....................................................................................................................................... 294
Section 42.3: Waiting for multiple concurrent promises ....................................................................................... 265 Section 50.3: Changes to properties ....................................................................................................................... 294
Section 42.4: Reduce an array to chained promises ............................................................................................ 266 Section 50.4: Changes to global properties ........................................................................................................... 295
Section 42.5: Waiting for the first of multiple concurrent promises .................................................................... 267 Section 50.5: Duplicate Parameters ........................................................................................................................ 296
Section 42.6: "Promisifying" functions with callbacks ........................................................................................... 268 Section 50.6: Function scoping in strict mode ........................................................................................................ 296
Section 42.7: Error Handling .................................................................................................................................... 268 Section 50.7: Behaviour of a function's arguments list ......................................................................................... 296
Section 42.8: Reconciling synchronous and asynchronous operations .............................................................. 272 Section 50.8: Non-Simple parameter lists .............................................................................................................. 297
Section 42.9: Delay function call .............................................................................................................................. 273
Chapter 51: Custom Elements ............................................................................................................................ 299
Section 42.10: "Promisifying" values ........................................................................................................................ 273
Section 51.1: Extending Native Elements ................................................................................................................. 299
Section 42.11: Using ES2017 async/await ................................................................................................................ 274
Section 51.2: Registering New Elements ................................................................................................................. 299
Section 42.12: Performing cleanup with finally() .................................................................................................... 274
Chapter 52: Data Manipulation ......................................................................................................................... 300
Section 42.13: forEach with promises ...................................................................................................................... 275
Section 52.1: Format numbers as money ............................................................................................................... 300
Section 42.14: Asynchronous API request ............................................................................................................... 275
Section 52.2: Extract extension from file name ..................................................................................................... 300
Chapter 43: Set .......................................................................................................................................................... 277
Section 52.3: Set object property given its string name ....................................................................................... 301
Section 43.1: Creating a Set ...................................................................................................................................... 277
Chapter 53: Binary Data ....................................................................................................................................... 302
Section 43.2: Adding a value to a Set ..................................................................................................................... 277
Section 53.1: Getting binary representation of an image file ............................................................................... 302
Section 43.3: Removing value from a set ............................................................................................................... 277
Section 53.2: Converting between Blobs and ArrayBuers ................................................................................. 302
Section 43.4: Checking if a value exist in a set ....................................................................................................... 278
Section 53.3: Manipulating ArrayBuers with DataViews ..................................................................................... 303
Section 43.5: Clearing a Set ...................................................................................................................................... 278
Section 53.4: Creating a TypedArray from a Base64 string ................................................................................. 303
Section 43.6: Getting set length ............................................................................................................................... 278
Section 53.5: Using TypedArrays ............................................................................................................................. 304
Section 43.7: Converting Sets to arrays .................................................................................................................. 278
Section 53.6: Iterating through an arrayBuer ...................................................................................................... 304
Section 43.8: Intersection and dierence in Sets ................................................................................................... 279
Section 43.9: Iterating Sets ....................................................................................................................................... 279 Chapter 54: Template Literals .......................................................................................................................... 306
Section 54.1: Basic interpolation and multiline strings ........................................................................................... 306
Chapter 44: Modals - Prompts .......................................................................................................................... 280
Section 54.2: Tagged strings ................................................................................................................................... 306
Section 44.1: About User Prompts ........................................................................................................................... 280
Section 54.3: Raw strings .......................................................................................................................................... 307
Section 44.2: Persistent Prompt Modal ................................................................................................................... 280
Section 54.4: Templating HTML With Template Strings ....................................................................................... 307
Section 44.3: Confirm to Delete element ................................................................................................................ 281
Section 54.5: Introduction ......................................................................................................................................... 308
Section 44.4: Usage of alert() .................................................................................................................................. 281
Section 44.5: Usage of prompt() ............................................................................................................................. 282 Chapter 55: Fetch ..................................................................................................................................................... 309
Section 55.1: Getting JSON data .............................................................................................................................. 309
Chapter 45: execCommand and contenteditable ................................................................................... 283
Section 55.2: Set Request Headers ......................................................................................................................... 309
Section 45.1: Listening to Changes of contenteditable .......................................................................................... 284
Section 55.3: POST Data ........................................................................................................................................... 309
Section 45.2: Getting started .................................................................................................................................... 284
Section 55.4: Send cookies ....................................................................................................................................... 310
Section 45.3: Copy to clipboard from textarea using execCommand("copy") .................................................. 285
Section 55.5: GlobalFetch ......................................................................................................................................... 310
Section 45.4: Formatting .......................................................................................................................................... 285
Section 55.6: Using Fetch to Display Questions from the Stack Overflow API ................................................... 310
Chapter 46: History ................................................................................................................................................. 287
Chapter 56: Scope .................................................................................................................................................... 311
Section 46.1: [Link]() .............................................................................................................................. 287
Section 56.1: Closures ................................................................................................................................................ 311
Section 46.2: [Link]() ........................................................................................................................ 287
Section 56.2: Hoisting ................................................................................................................................................ 312
Section 46.3: Load a specific URL from the history list ......................................................................................... 287
Section 56.3: Dierence between var and let ........................................................................................................ 315
Chapter 47: Navigator Object ........................................................................................................................... 289
Section 56.4: Apply and Call syntax and invocation ............................................................................................. 317
Section 47.1: Get some basic browser data and return it as a JSON object ...................................................... 289
Section 56.5: Arrow function invocation ................................................................................................................. 318
Chapter 48: BOM (Browser Object Model) .................................................................................................. 290 Section 56.6: Bound invocation ................................................................................................................................ 319
Section 48.1: Introduction .......................................................................................................................................... 290 Section 56.7: Method invocation .............................................................................................................................. 319
Section 48.2: Window Object Properties ................................................................................................................. 290 Section 56.8: Anonymous invocation ...................................................................................................................... 320
Section 48.3: Window Object Methods .................................................................................................................... 291 Section 56.9: Constructor invocation ...................................................................................................................... 320
Section 56.10: Using let in loops instead of var (click handlers example) ........................................................... 320 Chapter 63: Workers ............................................................................................................................................... 340
Chapter 57: Modules ............................................................................................................................................... 322 Section 63.1: Web Worker ......................................................................................................................................... 340
Section 57.1: Defining a module ............................................................................................................................... 322 Section 63.2: A simple service worker ..................................................................................................................... 340
Section 57.2: Default exports ................................................................................................................................... 322 Section 63.3: Register a service worker .................................................................................................................. 341
Section 57.3: Importing named members from another module ........................................................................ 323 Section 63.4: Communicating with a Web Worker ................................................................................................ 341
Section 57.4: Importing an entire module .............................................................................................................. 323 Section 63.5: Terminate a worker ............................................................................................................................ 342
Section 57.5: Importing named members with aliases ......................................................................................... 324 Section 63.6: Populating your cache ....................................................................................................................... 343
Section 57.6: Importing with side eects ................................................................................................................ 324 Section 63.7: Dedicated Workers and Shared Workers ........................................................................................ 343
Section 57.7: Exporting multiple named members ................................................................................................ 324 Chapter 64: requestAnimationFrame ............................................................................................................ 345
Chapter 58: Screen .................................................................................................................................................. 325 Section 64.1: Use requestAnimationFrame to fade in element ............................................................................ 345
Section 58.1: Getting the screen resolution ............................................................................................................. 325 Section 64.2: Keeping Compatibility ....................................................................................................................... 346
Section 58.2: Getting the “available” area of the screen ...................................................................................... 325 Section 64.3: Cancelling an Animation .................................................................................................................... 346
Section 58.3: Page width and height ....................................................................................................................... 325 Chapter 65: Creational Design Patterns ....................................................................................................... 348
Section 58.4: Window innerWidth and innerHeight Properties ............................................................................ 325 Section 65.1: Factory Functions ................................................................................................................................ 348
Section 58.5: Getting color information about the screen .................................................................................... 325 Section 65.2: Factory with Composition .................................................................................................................. 349
Chapter 59: Variable coercion/conversion ................................................................................................. 326 Section 65.3: Module and Revealing Module Patterns .......................................................................................... 350
Section 59.1: Double Negation (!!x) .......................................................................................................................... 326 Section 65.4: Prototype Pattern ............................................................................................................................... 352
Section 59.2: Implicit conversion ............................................................................................................................. 326 Section 65.5: Singleton Pattern ................................................................................................................................ 353
Section 59.3: Converting to boolean ....................................................................................................................... 326 Section 65.6: Abstract Factory Pattern ................................................................................................................... 354
Section 59.4: Converting a string to a number ...................................................................................................... 327 Chapter 66: Detecting browser ......................................................................................................................... 355
Section 59.5: Converting a number to a string ...................................................................................................... 328 Section 66.1: Feature Detection Method ................................................................................................................. 355
Section 59.6: Primitive to Primitive conversion table ............................................................................................. 328 Section 66.2: User Agent Detection ......................................................................................................................... 355
Section 59.7: Convert an array to a string ............................................................................................................. 328 Section 66.3: Library Method ................................................................................................................................... 356
Section 59.8: Array to String using array methods ............................................................................................... 329
Chapter 67: Symbols ............................................................................................................................................... 357
Section 59.9: Converting a number to a boolean .................................................................................................. 329
Section 67.1: Basics of symbol primitive type ......................................................................................................... 357
Section 59.10: Converting a string to a boolean .................................................................................................... 329
Section 67.2: Using [Link]() to create global, shared symbols .................................................................... 357
Section 59.11: Integer to Float ................................................................................................................................... 329
Section 67.3: Converting a symbol into a string .................................................................................................... 357
Section 59.12: Float to Integer .................................................................................................................................. 330
Chapter 68: Transpiling ......................................................................................................................................... 359
Section 59.13: Convert string to float ....................................................................................................................... 330
Section 68.1: Introduction to Transpiling ................................................................................................................. 359
Chapter 60: Destructuring assignment ......................................................................................................... 331
Section 68.2: Start using ES6/7 with Babel ............................................................................................................. 360
Section 60.1: Destructuring Objects ......................................................................................................................... 331
Chapter 69: Automatic Semicolon Insertion - ASI .................................................................................... 361
Section 60.2: Destructuring function arguments ................................................................................................... 332
Section 69.1: Avoid semicolon insertion on return statements ............................................................................. 361
Section 60.3: Nested Destructuring ......................................................................................................................... 332
Section 69.2: Rules of Automatic Semicolon Insertion .......................................................................................... 361
Section 60.4: Destructuring Arrays .......................................................................................................................... 333
Section 69.3: Statements aected by automatic semicolon insertion ................................................................ 362
Section 60.5: Destructuring inside variables .......................................................................................................... 333
Section 60.6: Default Value While Destructuring ................................................................................................... 334 Chapter 70: Localization ....................................................................................................................................... 364
Section 60.7: Renaming Variables While Destructuring ........................................................................................ 334 Section 70.1: Number formatting ............................................................................................................................. 364
Section 70.2: Currency formatting .......................................................................................................................... 364
Chapter 61: WebSockets ....................................................................................................................................... 335
Section 70.3: Date and time formatting .................................................................................................................. 364
Section 61.1: Working with string messages ........................................................................................................... 335
Section 61.2: Establish a web socket connection ................................................................................................... 335 Chapter 71: Geolocation ........................................................................................................................................ 365
Section 61.3: Working with binary messages ......................................................................................................... 335 Section 71.1: Get updates when a user's location changes ................................................................................... 365
Section 61.4: Making a secure web socket connection ......................................................................................... 336 Section 71.2: Get a user's latitude and longitude ................................................................................................... 365
Section 71.3: More descriptive error codes ............................................................................................................. 365
Chapter 62: Arrow Functions .............................................................................................................................. 337
Section 62.1: Introduction .......................................................................................................................................... 337 Chapter 72: IndexedDB .......................................................................................................................................... 367
Section 62.2: Lexical Scoping & Binding (Value of "this") ..................................................................................... 337 Section 72.1: Opening a database ........................................................................................................................... 367
Section 62.3: Arguments Object .............................................................................................................................. 338 Section 72.2: Adding objects .................................................................................................................................... 367
Section 62.4: Implicit Return ..................................................................................................................................... 338 Section 72.3: Retrieving data ................................................................................................................................... 368
Section 62.5: Arrow functions as a constructor ..................................................................................................... 339 Section 72.4: Testing for IndexedDB availability .................................................................................................... 369
Section 62.6: Explicit Return ..................................................................................................................................... 339 Chapter 73: Modularization Techniques ....................................................................................................... 370
Section 73.1: ES6 Modules ......................................................................................................................................... 370
Section 73.2: Universal Module Definition (UMD) .................................................................................................. 370 Chapter 85: Bitwise Operators - Real World Examples (snippets) ................................................. 401
Section 73.3: Immediately invoked function expressions (IIFE) ............................................................................ 371 Section 85.1: Swapping Two Integers with Bitwise XOR (without additional memory allocation) .................... 401
Section 73.4: Asynchronous Module Definition (AMD) .......................................................................................... 371 Section 85.2: Faster multiplication or division by powers of 2 ............................................................................. 401
Section 73.5: CommonJS - [Link] .......................................................................................................................... 372 Section 85.3: Number's Parity Detection with Bitwise AND .................................................................................. 401
Chapter 74: Proxy .................................................................................................................................................... 374 Chapter 86: Tilde ~ ................................................................................................................................................... 403
Section 74.1: Proxying property lookup .................................................................................................................. 374 Section 86.1: ~ Integer ............................................................................................................................................... 403
Section 74.2: Very simple proxy (using the set trap) ............................................................................................ 374 Section 86.2: ~~ Operator ......................................................................................................................................... 403
Chapter 75: .postMessage() and MessageEvent ...................................................................................... 376 Section 86.3: Converting Non-numeric values to Numbers .................................................................................. 404
Section 75.1: Getting Started .................................................................................................................................... 376 Section 86.4: Shorthands .......................................................................................................................................... 404
Chapter 76: WeakMap ............................................................................................................................................ 379 Section 86.5: ~ Decimal ............................................................................................................................................. 404
Section 76.1: Creating a WeakMap object .............................................................................................................. 379 Chapter 87: Using JavaScript to get/set CSS custom variables ..................................................... 406
Section 76.2: Getting a value associated to the key .............................................................................................. 379 Section 87.1: How to get and set CSS variable property values ........................................................................... 406
Section 76.3: Assigning a value to the key ............................................................................................................. 379 Chapter 88: Selection API ..................................................................................................................................... 407
Section 76.4: Checking if an element with the key exists ...................................................................................... 379 Section 88.1: Get the text of the selection ............................................................................................................... 407
Section 76.5: Removing an element with the key .................................................................................................. 380 Section 88.2: Deselect everything that is selected ................................................................................................ 407
Section 76.6: Weak reference demo ....................................................................................................................... 380 Section 88.3: Select the contents of an element .................................................................................................... 407
Chapter 77: WeakSet .............................................................................................................................................. 382 Chapter 89: File API, Blobs and FileReaders ............................................................................................... 408
Section 77.1: Creating a WeakSet object ................................................................................................................ 382 Section 89.1: Read file as string ............................................................................................................................... 408
Section 77.2: Adding a value .................................................................................................................................... 382 Section 89.2: Read file as dataURL ......................................................................................................................... 408
Section 77.3: Checking if a value exists ................................................................................................................... 382 Section 89.3: Slice a file ............................................................................................................................................. 409
Section 77.4: Removing a value ............................................................................................................................... 382 Section 89.4: Get the properties of the file ............................................................................................................. 409
Chapter 78: Escape Sequences ......................................................................................................................... 383 Section 89.5: Selecting multiple files and restricting file types ............................................................................. 410
Section 78.1: Entering special characters in strings and regular expressions .................................................... 383 Section 89.6: Client side csv download using Blob ................................................................................................ 410
Section 78.2: Escape sequence types ..................................................................................................................... 383 Chapter 90: Notifications API ............................................................................................................................. 411
Chapter 79: Behavioral Design Patterns ...................................................................................................... 386 Section 90.1: Requesting Permission to send notifications ................................................................................... 411
Section 79.1: Observer pattern ................................................................................................................................. 386 Section 90.2: Sending Notifications ......................................................................................................................... 411
Section 79.2: Mediator Pattern ................................................................................................................................ 387 Section 90.3: Closing a notification ......................................................................................................................... 411
Section 79.3: Command ............................................................................................................................................ 388 Section 90.4: Notification events ............................................................................................................................. 412
Section 79.4: Iterator ................................................................................................................................................. 389 Chapter 91: Vibration API ...................................................................................................................................... 413
Chapter 80: Server-sent events ........................................................................................................................ 391 Section 91.1: Single vibration ..................................................................................................................................... 413
Section 80.1: Setting up a basic event stream to the server ................................................................................. 391 Section 91.2: Check for support ............................................................................................................................... 413
Section 80.2: Closing an event stream ................................................................................................................... 391 Section 91.3: Vibration patterns ............................................................................................................................... 413
Section 80.3: Binding event listeners to EventSource ........................................................................................... 391 Chapter 92: Battery Status API ......................................................................................................................... 414
Chapter 81: Async functions (async/await) ................................................................................................ 393 Section 92.1: Battery Events ..................................................................................................................................... 414
Section 81.1: Introduction .......................................................................................................................................... 393 Section 92.2: Getting current battery level ............................................................................................................. 414
Section 81.2: Await and operator precedence ....................................................................................................... 393 Section 92.3: Is battery charging? ........................................................................................................................... 414
Section 81.3: Async functions compared to Promises ........................................................................................... 394 Section 92.4: Get time left until battery is empty ................................................................................................... 414
Section 81.4: Looping with async await ................................................................................................................... 395 Section 92.5: Get time left until battery is fully charged ....................................................................................... 414
Section 81.5: Less indentation .................................................................................................................................. 396 Chapter 93: Fluent API ............................................................................................................................................ 415
Section 81.6: Simultaneous async (parallel) operations ........................................................................................ 397 Section 93.1: Fluent API capturing construction of HTML articles with JS ........................................................... 415
Chapter 82: Async Iterators ................................................................................................................................ 398 Chapter 94: Web Cryptography API ............................................................................................................... 417
Section 82.1: Basics ................................................................................................................................................... 398 Section 94.1: Creating digests (e.g. SHA-256) ......................................................................................................... 417
Chapter 83: How to make iterator usable inside async callback function ................................. 399 Section 94.2: Cryptographically random data ....................................................................................................... 417
Section 83.1: Erroneous code, can you spot why this usage of key will lead to bugs? ...................................... 399 Section 94.3: Generating RSA key pair and converting to PEM format .............................................................. 418
Section 83.2: Correct Writing ................................................................................................................................... 399 Section 94.4: Converting PEM key pair to CryptoKey ........................................................................................... 419
Chapter 84: Tail Call Optimization .................................................................................................................. 400 Chapter 95: Security issues ................................................................................................................................. 421
Section 84.1: What is Tail Call Optimization (TCO) ................................................................................................ 400 Section 95.1: Reflected Cross-site scripting (XSS) .................................................................................................. 421
Section 84.2: Recursive loops .................................................................................................................................. 400 Section 95.2: Persistent Cross-site scripting (XSS) ................................................................................................ 422
Section 95.3: Persistent Cross-site scripting from JavaScript string literals ....................................................... 423
Section 95.4: Why scripts from other people can harm your website and its visitors ...................................... 423 Credits ............................................................................................................................................................................ 463
Section 95.5: Evaled JSON injection ........................................................................................................................ 424
You may also like ...................................................................................................................................................... 474
Chapter 96: Same Origin Policy & Cross-Origin Communication ..................................................... 426
Section 96.1: Safe cross-origin communication with messages ........................................................................... 426
Section 96.2: Ways to circumvent Same-Origin Policy ......................................................................................... 427
Chapter 97: Error Handling ................................................................................................................................. 429
Section 97.1: Error objects ........................................................................................................................................ 429
Section 97.2: Interaction with Promises .................................................................................................................. 429
Section 97.3: Error types ........................................................................................................................................... 430
Section 97.4: Order of operations plus advanced thoughts ................................................................................. 430
Chapter 98: Global error handling in browsers ........................................................................................ 433
Section 98.1: Handling [Link] to report all errors back to the server-side ......................................... 433
Chapter 99: Debugging .......................................................................................................................................... 435
Section 99.1: Interactive interpreter variables ........................................................................................................ 435
Section 99.2: Breakpoints ......................................................................................................................................... 435
Section 99.3: Using setters and getters to find what changed a property ......................................................... 436
Section 99.4: Using the console ............................................................................................................................... 437
Section 99.5: Automatically pausing execution ..................................................................................................... 438
Section 99.6: Elements inspector ............................................................................................................................. 438
Section 99.7: Break when a function is called ........................................................................................................ 438
Section 99.8: Stepping through code ...................................................................................................................... 439
Chapter 100: Unit Testing JavaScript ............................................................................................................ 440
Section 100.1: Unit Testing Promises with Mocha, Sinon, Chai and Proxyquire ................................................... 440
Section 100.2: Basic Assertion .................................................................................................................................. 442
Chapter 101: Evaluating JavaScript ................................................................................................................ 444
Section 101.1: Evaluate a string of JavaScript statements .................................................................................... 444
Section 101.2: Introduction ........................................................................................................................................ 444
Section 101.3: Evaluation and Math .......................................................................................................................... 444
Chapter 102: Linters - Ensuring code quality ............................................................................................. 445
Section 102.1: JSHint .................................................................................................................................................. 445
Section 102.2: ESLint / JSCS ..................................................................................................................................... 446
Section 102.3: JSLint .................................................................................................................................................. 446
Chapter 103: Anti-patterns .................................................................................................................................. 447
Section 103.1: Chaining assignments in var declarations ...................................................................................... 447
Chapter 104: Performance Tips ........................................................................................................................ 448
Section 104.1: Avoid try/catch in performance-critical functions ......................................................................... 448
Section 104.2: Limit DOM Updates ........................................................................................................................... 448
Section 104.3: Benchmarking your code - measuring execution time ................................................................ 449
Section 104.4: Use a memoizer for heavy-computing functions ......................................................................... 451
Section 104.5: Initializing object properties with null .............................................................................................. 453
Section 104.6: Reuse objects rather than recreate ................................................................................................ 454
Section 104.7: Prefer local variables to globals, attributes, and indexed values ................................................ 455
Section 104.8: Be consistent in use of Numbers ..................................................................................................... 456
Chapter 105: Memory eciency ....................................................................................................................... 458
Section 105.1: Drawback of creating true private method .................................................................................... 458
Appendix A: Reserved Keywords ...................................................................................................................... 459
Section A.1: Reserved Keywords .............................................................................................................................. 459
Section A.2: Identifiers & Identifier Names ............................................................................................................. 461
About Chapter 1: Getting started with JavaScript
Version Release Date
1 1997-06-01
2 1998-06-01
3 1998-12-01
E4X 2004-06-01
5 2009-12-01
5.1 2011-06-01
Please feel free to share this PDF with anyone for free, 6 2015-06-01
latest version of this book can be downloaded from: 7 2016-06-14
[Link] 8 2017-06-27
This JavaScript® Notes for Professionals book is compiled from Stack Overflow
Section 1.1: Using [Link]()
Documentation, the content is written by the beautiful people at Stack Overflow. Introduction
Text content is released under Creative Commons BY-SA, see credits at the end
of this book whom contributed to the various chapters. Images may be copyright All modern web browsers, [Link] as well as almost every other JavaScript environments support writing messages
of their respective owners unless otherwise specified to a console using a suite of logging methods. The most common of these methods is [Link]().
This is an unofficial free book created for educational purposes and is not In a browser environment, the [Link]() function is predominantly used for debugging purposes.
affiliated with official JavaScript® group(s) or company(s) nor Stack Overflow. All
trademarks and registered trademarks are the property of their respective
company owners Getting Started
The information presented in this book is not guaranteed to be correct nor Open up the JavaScript Console in your browser, type the following, and press Enter :
accurate, use at your own risk
[Link]("Hello, World!");
Please send feedback and corrections to web@[Link]
This will log the following to the console:
In the example above, the [Link]() function prints Hello, World! to the console and returns undefined
(shown above in the console output window). This is because [Link]() has no explicit return value.
Logging variables
[Link]() can be used to log variables of any kind; not only strings. Just pass in the variable that you want to
be displayed in the console, for example:
[Link] – JavaScript® Notes for Professionals 1 [Link] – JavaScript® Notes for Professionals 2
'Title': 'user2'
});
If you want to log two or more values, simply separate them with commas. Spaces will be automatically added
between each argument during concatenation:
This will log the following to the console: Logging HTML elements
You have the ability to log any element which exists within the DOM. In this case we log the body element:
[Link]([Link]);
Placeholders
End Note
For more information on the capabilities of the console, see the Console topic.
Setting the textContent property of an Element is one way to output text on a web page.
[Link]({
'Email': '',
For example, consider the following HTML tag:
'Groups': {},
'Id': 33,
'IsHiddenInUI': false, <p id="paragraph"></p>
'IsSiteAdmin': false,
'LoginName': 'i:0#.w|virtualdomain\\user2', To change its textContent property, we can run the following JavaScript:
'PrincipalType': 1,
[Link] – JavaScript® Notes for Professionals 3 [Link] – JavaScript® Notes for Professionals 4
[Link]("paragraph").textContent = "Hello, World"; In Chrome, that would produce a pop-up like this:
This will select the element that with the id paragraph and set its text content to "Hello, World":
You can also use JavaScript to create a new HTML element programmatically. For example, consider an HTML
document with the following body:
<body>
<h1>Adding an element</h1>
</body>
Notes
In our JavaScript, we create a new <p> tag with a textContent property of and add it at the end of the html body:
The alert method is technically a property of window object, but since all window properties are
var element = [Link]('p');
automatically global variables, we can use alert as a global variable instead of as a property of window -
[Link] = "Hello, World";
[Link](element); //add the newly created element to the DOM meaning you can directly use alert() instead of [Link]().
That will change your HTML body to the following: Unlike using [Link], alert acts as a modal prompt meaning that the code calling alert will pause until the
prompt is answered. Traditionally this means that no other JavaScript code will execute until the alert is dismissed:
<body>
<h1>Adding an element</h1>
alert('Pause!');
<p>Hello, World</p>
[Link]('Alert was dismissed');
</body>
Note that in order to manipulate elements in the DOM using JavaScript, the JavaScript code must be run after the However the specification actually allows other event-triggered code to continue to execute even though a modal
relevant element has been created in the document. This can be achieved by putting the JavaScript <script> tags dialog is still being shown. In such implementations, it is possible for other code to run while the modal dialog is
after all of your other <body> content. Alternatively, you can also use an event listener to listen to eg. window's being shown.
onload event, adding your code to that event listener will delay running your code until after the whole content on
More information about usage of the alert method can be found in the modals prompts topic.
your page has been loaded.
The use of alerts is usually discouraged in favour of other methods that do not block users from interacting with the
A third way to make sure all your DOM has been loaded, is to wrap the DOM manipulation code with a timeout
page - in order to create a better user experience. Nevertheless, it can be useful for debugging.
function of 0 ms. This way, this JavaScript code is re-queued at the end of the execution queue, which gives the
browser a chance to finish doing some non-JavaScript things that have been waiting to finish before attending to Starting with Chrome 46.0, [Link]() is blocked inside an <iframe> unless its sandbox attribute has the value
this new piece of JavaScript. allow-modal.
Because window is the global object, you can call also use the following shorthand: text: The text displayed in the prompt box.
default: A default value for the input field (optional).
alert(message);
Examples
So what does [Link]() do? Well, let's take the following example: var age = prompt("How old are you?");
[Link](age); // Prints the value inserted by the user
alert('hello, world');
[Link] – JavaScript® Notes for Professionals 5 [Link] – JavaScript® Notes for Professionals 6
var deleteConfirm = [Link]("Are you sure you want to delete this?");
Notes
Now, let's take the following example: Then select a context for the canvas, in this case two-dimensional:
Here, message is the optional string to be displayed in the dialog and result is a boolean value indicating whether Then set properties related to the text:
OK or Cancel was selected (true means OK).
[Link] = '30px Cursive';
[Link]() is typically used to ask for user confirmation before doing a dangerous operation like deleting [Link]("Hello world!", 50, 50);
something in a Control Panel:
Then insert the canvas element into the page to take effect:
if([Link]("Are you sure you want to delete this?")) {
deleteItem(itemId); [Link](canvas);
}
Using SVG
The output of that code would look like this in the browser:
SVG is for building scalable vector-based graphics and can be used within HTML.
Then build a text element with the desired positioning and font characteristics:
If you need it for later use, you can simply store the result of the user's interaction in a variable:
var text = [Link]('[Link] 'text');
[Link]('x', '0');
[Link] – JavaScript® Notes for Professionals 7 [Link] – JavaScript® Notes for Professionals 8
[Link]('y', '50');
[Link] = 'Times New Roman';
[Link] = '50';
Chapter 2: JavaScript Variables
variable_name {Required} The name of the variable: used when calling it.
Then add the actual text to display to the textelement: = [Optional] Assignment (defining the variable)
value {Required when using Assignment} The value of a variable [default: undefined]
[Link] = 'Hello world!';
Variables are what make up most of JavaScript. These variables make up things from numbers to objects, which are
Finally add the text element to our svg container and add the svg container element to the HTML document:
all over JavaScript to make one's life much easier.
[Link](text);
[Link](svg); Section 2.1: Defining a Variable
Image file var myVariable = "This is a variable!";
If you already have an image file containing the desired text and have it placed on a server, you can add the URL of This is an example of defining variables. This variable is called a "string" because it has ASCII characters (A-Z, 0-9,
the image and then add the image to the document as follows: !@#$, etc.)
Here, we defined a number called "number1" which was equal to 5. However, on the second line, we changed the
value to 3. To show the value of a variable, we log it to the console or use [Link]():
[Link](number1); // 3
[Link](number1); // 3
number1 = number1 + 5; // 3 + 5 = 8
number1 = number1 - 6; // 8 - 6 = 2
var number2 = number1 * 10; // 2 (times) 10 = 20
var number3 = number2 / number1; // 20 (divided by) 2 = 10;
We can also add strings which will concatenate them, or put them together. For example:
[Link] – JavaScript® Notes for Professionals 9 [Link] – JavaScript® Notes for Professionals 10
var myNull = null; // null
// etc... Chapter 3: Built-in Constants
Section 2.4: Arrays and Objects Section 3.1: null
var myArray = []; // empty array null is used for representing the intentional absence of an object value and is a primitive value. Unlike undefined,
it is not a property of the global object.
An array is a set of variables. For example:
It is equal to undefined but not identical to it.
var favoriteFruits = ["apple", "orange", "strawberry"];
var carsInParkingLot = ["Toyota", "Ferrari", "Lexus"]; null == undefined; // true
var employees = ["Billy", "Bob", "Joe"]; null === undefined; // false
var primeNumbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31];
var randomVariables = [2, "any type works", undefined, null, true, 2.51]; CAREFUL: The typeof null is 'object'.
myObject = {};
Section 3.2: Testing for NaN using isNaN()
john = {firstname: "John", lastname: "Doe", fullname: "John Doe"}; [Link]()
billy = {
firstname: "Billy", The global function isNaN() can be used to check if a certain value or expression evaluates to NaN. This function (in
lastname: undefined,
short) first checks if the value is a number, if not tries to convert it (*), and then checks if the resulting value is NaN.
fullname: "Billy"
}; For this reason, this testing method may cause confusion.
[Link]([Link]); // John Doe
[Link]([Link]); // Billy (*) The "conversion" method is not that simple, see ECMA-262 18.2.3 for a detailed explanation of the algorithm.
Rather than making an array ["John Doe", "Billy"] and calling myArray[0], we can just call [Link] and These examples will help you better understand the isNaN() behavior:
[Link].
isNaN(NaN); // true
isNaN(1); // false: 1 is a number
isNaN(-2e-4); // false: -2e-4 is a number (-0.0002) in scientific notation
isNaN(Infinity); // false: Infinity is a number
isNaN(true); // false: converted to 1, which is a number
isNaN(false); // false: converted to 0, which is a number
isNaN(null); // false: converted to 0, which is a number
isNaN(""); // false: converted to 0, which is a number
isNaN(" "); // false: converted to 0, which is a number
isNaN("45.3"); // false: string representing a number, converted to 45.3
isNaN("1.2e3"); // false: string representing a number, converted to 1.2e3
isNaN("Infinity"); // false: string representing a number, converted to Infinity
isNaN(new Date); // false: Date object, converted to milliseconds since epoch
isNaN("10$"); // true : conversion fails, the dollar sign is not a digit
isNaN("hello"); // true : conversion fails, no digits at all
isNaN(undefined); // true : converted to NaN
isNaN(); // true : converted to NaN (implicitly undefined)
isNaN(function(){}); // true : conversion fails
isNaN({}); // true : conversion fails
isNaN([1, 2]); // true : converted to "1, 2", which can't be converted to a number
This last one is a bit tricky: checking if an Array is NaN. To do this, the Number() constructor first converts the array
[Link] – JavaScript® Notes for Professionals 11 [Link] – JavaScript® Notes for Professionals 12
to a string, then to a number; this is the reason why isNaN([]) and isNaN([34]) both return false, but isNaN([1, It is a property of the global object, and a reference to [Link]
2]) and isNaN([true]) both return true: because they get converted to "", "34", "1,2" and "true" respectively. In
general, an array is considered NaN by isNaN() unless it only holds one element whose string representation [Link]('NaN'); // true
NaN; // NaN
can be converted to a valid number.
Some examples: undefined is a global value that represents the absence of an assigned value.
typeof undefined === 'undefined'
// The one and only
null is an object that indicates that a variable has been explicitly assigned "no value".
[Link](NaN); // true
typeof null === 'object'
// Numbers
[Link](1); // false Setting a variable to undefined means the variable effectively does not exist. Some processes, such as JSON
[Link](-2e-4); // false serialization, may strip undefined properties from objects. In contrast, null properties indicate will be preserved so
[Link](Infinity); // false you can explicitly convey the concept of an "empty" property.
[Link] – JavaScript® Notes for Professionals 13 [Link] – JavaScript® Notes for Professionals 14
undefined is also a property of the global window object. Number.MIN_VALUE; // 5e-324
Number.MIN_SAFE_INTEGER; // -9007199254740991
// Only in browsers
[Link]; // 0.0000000000000002220446049250313
[Link]([Link]); // undefined
[Link]('undefined'); // true
Number.POSITIVE_INFINITY; // Infinity
Version < 5
Number.NEGATIVE_INFINITY; // -Infinity
Before ECMAScript 5 you could actually change the value of the [Link] property to any other value [Link]; // NaN
potentially breaking everything.
In many cases the various operators in JavaScript will break with values outside the range of
(Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)
Section 3.5: Infinity and -Infinity
Note that [Link] represents the different between one and the smallest Number greater than one, and
1 / 0; // Infinity thus the smallest possible difference between two different Number values. One reason to use this is due to the
// Wait! WHAAAT?
nature of how numbers are stored by JavaScript see Check the equality of two numbers
Infinity is a property of the global object (therefore a global variable) that represents mathematical infinity. It is a
reference to Number.POSITIVE_INFINITY
Section 3.7: Operations that return NaN
Mathematical operations on values other than numbers return NaN.
It is greater than any other value, and you can get it by dividing by 0 or by evaluating the expression of a number
that's so big that overflows. This actually means there is no division by 0 errors in JavaScript, there is Infinity!
"b" * 3
"cde" - "e"
There is also -Infinity which is mathematical negative infinity, and it's lower than any other value.
[1, 2, 3] * 2
[Link](-1)
Section 3.6: Number constants
The Number constructor has some built in constants that can be useful
Number.MAX_VALUE; // 1.7976931348623157e+308
Number.MAX_SAFE_INTEGER; // 9007199254740991
[Link] – JavaScript® Notes for Professionals 15 [Link] – JavaScript® Notes for Professionals 16
Chapter 4: Comments </script>
An HTML closing comment can also be used in JavaScript (independent of an opening comment) at the beginning of
Section 4.1: Using Comments a line (optionally preceded by whitespace) in which case it too causes the rest of the line to be ignored:
To add annotations, hints, or exclude some code from being executed JavaScript provides two ways of commenting --> Unreachable JS code
code lines
These facts have also been exploited to allow a page to call itself first as HTML and secondly as JavaScript. For
Single line Comment // example:
Everything after the // until the end of the line is excluded from execution. <!--
[Link]('reached JS "file"');
function elementAt( event ) { /*
// Gets the element from Event coordinates -->
return [Link]([Link], [Link]); <!DOCTYPE html>
} <script>
// TODO: write more cool stuff! var w1 = new Worker('#1');
[Link] = function (e) {
Multi-line Comment /**/
[Link]([Link]); // 'reached JS "file"
};
Everything between the opening /* and the closing */ is excluded from execution, even if the opening and closing
</script>
are on different lines. <!--
*/
/* -->
Gets the element from Event coordinates.
Use like: When run a HTML, all the multiline text between the <!-- and --> comments are ignored, so the JavaScript
var clickedEl = [Link]("click", elementAt, false);
contained therein is ignored when run as HTML.
*/
function elementAt( event ) {
return [Link]([Link], [Link]); As JavaScript, however, while the lines beginning with <!-- and --> are ignored, their effect is not to escape over
} multiple lines, so the lines following them (e.g., [Link](...) will not be ignored when run as JavaScript,
/* TODO: write more useful comments! */ at least until they reach a JavaScript comment, marked by /* and */. Such JavaScript comments are used in the
above example to ignore the remaining HTML text (until the --> which is also ignored as JavaScript).
Section 4.2: Using HTML comments in JavaScript (Bad
practice)
HTML comments (optionally preceded by whitespace) will cause code (on the same line) to be ignored by the
browser also, though this is considered bad practice.
Note: the JavaScript interpreter ignores the closing characters of HTML comments (-->) here.
This technique can be observed in legacy code to hide JavaScript from browsers that didn't support it:
[Link] – JavaScript® Notes for Professionals 17 [Link] – JavaScript® Notes for Professionals 18
Chapter 5: Console Opening the “Console” panel in Firefox’s Developer Tools:
In most current browsers, the JavaScript Console has been integrated as a tab within Developer Tools. The shortcut
keys listed below will open Developer Tools, it might be necessary to switch to the right tab after that.
Chrome
Ctrl + Shift + J
Ctrl + Shift + I , then click on the “Web Console” tab or press ESC to toggle the console
on and off
F12 , then click on the “Console” tab or press ESC to toggle the console on and off
Firefox
[Link] – JavaScript® Notes for Professionals 19 [Link] – JavaScript® Notes for Professionals 20
of your references and prevent exceptions.
if (![Link])
{
console = {log: function() {}};
}
Note this second example will stop all console logs even if the developer window has been opened.
Using this second example will preclude use of other functions such as [Link](obj) unless that is specifically
added.
A browser's debugging console or web console is generally used by developers to identify errors, understand flow
of execution, log data and for many other purpose at runtime. This information is accessed through the console
object.
Calling [Link]([label]) starts a new timer. When [Link]([label]) is called, the elapsed time, in
milliseconds, since the original .time() call is calculated and logged. Because of this behavior, you can call
.timeEnd() multiple times with the same label to log the elapsed time since the original .time() call was made.
Example 1:
[Link]('response in');
alert('Click to continue');
[Link]('response in');
When using or emulating Internet Explorer 8 or earlier versions (e.g. through Compatibility View / Enterprise Mode) for (var i = 0; i < 5000; i++) {
the console will only be defined when the Developer Tools are active, so [Link]() statements can cause an for (var j = 0, length = [Link]; j < length; j++) {
exception and prevent code from executing. To mitigate this, you can check to see if the console is available before // nothing to do ...
}
you log:
}
[Link] – JavaScript® Notes for Professionals 21 [Link] – JavaScript® Notes for Professionals 22
Section 5.2: Formatting console output Using groups to indent output
Many of the console's print methods can also handle C-like string formatting, using % tokens: Output can be indented and enclosed in a collapsible group in the debugging console with the following methods:
[Link](): creates a collapsed group of entries that can be expanded through the
[Link]('%s has %d points', 'Sam', 100);
disclosure button in order to reveal all the entries performed after this method is invoked;
Displays Sam has 100 points. [Link](): creates an expanded group of entries that can be collapsed in order to hide the entries
after this method is invoked.
The full list of format specifiers in JavaScript is:
The indentation can be removed for posterior entries by using the following method:
Specifier Output
%s Formats the value as a string [Link](): exits the current group, allowing newer entries to be printed in the parent group after
%i or %d Formats the value as an integer this method is invoked.
Advanced styling
When the CSS format specifier (%c) is placed at the left side of the string, the print method will accept a second
parameter with CSS rules which allow fine-grained control over the formatting of that string:
Displays:
The log method will display the following in the debugging console:
[Link] – JavaScript® Notes for Professionals 23 [Link] – JavaScript® Notes for Professionals 24
['string'] 1 Object { test: 1 } Window { /* truncated */ } }
function first() {
[Link]();
Beside plain strings, [Link]() can handle other types, like arrays, objects, dates, functions, etc.: }
sec();
[Link]([0, 3, 32, 'a string']);
[Link]({ key1: 'value', key2: 'another value'});
Displays:
Displays: first
sec
Array [0, 3, 32, 'a string'] (anonymous function)
Object { key1: 'value', key2: 'another value'}
Displays:
[Link]('msg'); Note: Where available it's also useful to know that the same stack trace is accessible as a property of the Error
object. This can be useful for post-processing and gathering automated feedback.
Displays:
var e = new Error('foo');
[Link]([Link]);
00:00:00.001 msg
[Link] – outputs the current stack trace or displays the same output as the log method if invoked in Section 5.5: Tabulating values - [Link]()
the global scope.
In most environments, [Link]() can be used to display objects and arrays in a tabular format.
function sec() {
first();
For example:
[Link] – JavaScript® Notes for Professionals 25 [Link] – JavaScript® Notes for Professionals 26
[Link](['Hello', 'world']);
displays like:
(index) value
0 "Hello"
1 "world"
[Link]({foo: 'bar', bar: 'baz'});
displays like:
(index) value
"foo" "bar"
"bar" "baz"
var personArr = [
{
"personId": 123,
"name": "Jhon",
"city": "Melbourne",
"phoneNo": "1234567890"
},
{
"personId": 124,
"name": "Amelia", Section 5.6: Counting - [Link]()
"city": "Sydney",
"phoneNo": "1234567890"
[Link]([obj]) places a counter on the object's value provided as argument. Each time this method is
},
{
invoked, the counter is increased (with the exception of the empty string ''). A label together with a number is
"personId": 125, displayed in the debugging console according to the following format:
"name": "Emily",
"city": "Perth", [label]: X
"phoneNo": "1234567890"
},
label represents the value of the object passed as argument and X represents the counter's value.
{
"personId": 126,
"name": "Abraham",
An object's value is always considered, even if variables are provided as arguments:
"city": "Perth",
"phoneNo": "1234567890" var o1 = 1, o2 = '2', o3 = "";
} [Link](o1);
]; [Link](o2);
[Link](personArr, ['name', 'personId']); [Link](o3);
[Link](1);
displays like:
[Link]('2');
[Link]('');
Displays:
1: 1
2: 1
: 1
1: 2
2: 2
: 1
[Link](42.3);
[Link] – JavaScript® Notes for Professionals 27 [Link] – JavaScript® Notes for Professionals 28
[Link](Number('42.3')); [object Object]: 2
[Link]('42.3'); [object Object]: 3
[object Object]: 4
[object Object]: 5
Displays:
null: 1
Displays:
Section 5.7: Clearing the console - [Link]()
You can clear the console window using the [Link]() method. This removes all previously printed
[object Function]: 1
messages in the console and may print a message like "Console was cleared" in some environments.
[object Function]: 2
[object Function]: 3
[object Function]: 4 Section 5.8: Displaying objects and XML interactively -
[object Function]: 5 [Link](), [Link]()
Certain objects get specific counters associated to the type of object they refer to: [Link](object) displays an interactive list of the properties of the specified JavaScript object. The output is
presented as a hierarchical listing with disclosure triangles that let you see the contents of child objects.
[Link](undefined);
[Link]([Link]); var myObject = {
var obj; "foo":{
[Link](obj); "bar":"data"
[Link](Number(undefined)); }
[Link](NaN); };
[Link](NaN+3);
[Link](1/0); [Link](myObject);
[Link](String(1/0));
[Link](window);
[Link](document); displays:
[Link](console);
[Link](console.__proto__);
[Link]([Link]);
[Link](console.__proto__.[Link]);
[Link]([Link](console));
[Link](null);
Displays:
undefined: 1
undefined: 2
undefined: 3
NaN: 1
NaN: 2
NaN: 3
Infinity: 1
Infinity: 2
[object Window]: 1 [Link](object) prints an XML representation of the descendant elements of object if possible, or the
[object HTMLDocument]: 1 JavaScript representation if not. Calling [Link]() on HTML and XML elements is equivalent to calling
[object Object]: 1 [Link]().
[Link] – JavaScript® Notes for Professionals 29 [Link] – JavaScript® Notes for Professionals 30
Example 1:
[Link](document)
displays:
Multiple arguments can be provided after the assertion–these can be strings or other objects–that will only be
printed if the assertion is false:
Example 3:
var myObject = {
"foo":{
"bar":"data"
} [Link] does not throw an AssertionError (except in [Link]), meaning that this method is incompatible
};
with most testing frameworks and that code execution will not break on a failed assertion.
[Link](myObject);
displays:
[Link] – JavaScript® Notes for Professionals 31 [Link] – JavaScript® Notes for Professionals 32
Chapter 6: Datatypes in JavaScript Section 6.2: Finding an object's class
To find whether an object was constructed by a certain constructor or one inheriting from it, you can use the
Section 6.1: typeof instanceof command:
typeof is the 'official' function that one uses to get the type in JavaScript, however in certain cases it might yield //We want this function to take the sum of the numbers passed to it
some unexpected results ... //It can be called as sum(1, 2, 3) or sum([1, 2, 3]) and should give 6
function sum(...arguments) {
1. Strings if ([Link] === 1) {
const [firstArg] = arguments
typeof "String" or if (firstArg instanceof Array) { //firstArg is something like [1, 2, 3]
return sum(...firstArg) //calls sum(1, 2, 3)
typeof Date(2011,01,01)
}
}
return [Link]((a, b) => a + b)
"string"
}
Note that primitive values are not considered instances of any class:
"number"
[Link](2 instanceof Number) //false
[Link]('abc' instanceof String) //false
3. Bool [Link](true instanceof Boolean) //false
[Link](Symbol() instanceof Symbol) //false
typeof true (valid values true and false)
Every value in JavaScript besides null and undefined also has a constructor property storing the function that was
used to construct it. This even works with primitives.
"boolean"
5. Function
Section 6.3: Getting object type by constructor name
typeof function(){}
When one with typeof operator one gets type object it falls into somewhat wast category...
"function" In practice you might need to narrow it down to what sort of 'object' it actually is and one way to do it is to use
object constructor name to get what flavour of object it actually is: [Link](yourObject)
6. Undefined 1. String
[Link] – JavaScript® Notes for Professionals 33 [Link] – JavaScript® Notes for Professionals 34
2. Number "[object Null]"
[Link](42)
10. Undefined
[Link](true)
11. Error
[Link](Object()) or
[Link]({})
"[object Object]"
5. Function
[Link](function(){})
"[object Function]"
6. Date
[Link](new Date(2015,10,21))
"[object Date]"
7. Regex
[Link](new RegExp()) or
[Link](/foo/);
"[object RegExp]"
8. Array
[Link]([]);
"[object Array]"
9. Null
[Link](null);
[Link] – JavaScript® Notes for Professionals 35 [Link] – JavaScript® Notes for Professionals 36
Chapter 7: Strings
Version ≥ 6
Section 7.1: Basic Info and String Concatenation var greeting = `Hello`;
Strings in JavaScript can be enclosed in Single quotes 'hello', Double quotes "Hello" and (from ES2015, ES6) in
With template literals, you can do string interpolation using ${variable} inside template literals:
Template Literals (backticks) `hello`.
Strings can be created from other types using the String() function.
You can use [Link] to get backslashes to be in the string without modification.
Or, toString() can be used to convert Numbers, Booleans or Objects to Strings. Section 7.2: Reverse String
var intString = (5232).toString(); // "5232" The most "popular" way of reversing a string in JavaScript is the following code fragment, which is quite common:
var booleanString = (false).toString(); // "false"
var objString = ({}).toString(); // "[object Object]" function reverseString(str) {
return [Link]('').reverse().join('');
Strings also can be created by using [Link] method. }
reverseString('string'); // "gnirts"
[Link](104,101,108,108,111) //"hello"
However, this will work only so long as the string being reversed does not contain surrogate pairs. Astral symbols,
Creating a String object using new keyword is allowed, but is not recommended as it behaves like Objects unlike
i.e. characters outside of the basic multilingual plane, may be represented by two code units, and will lead this
primitive strings.
naive technique to produce wrong results. Moreover, characters with combining marks (e.g. diaeresis) will appear
var objectString = new String("Yes, I am a String object");
on the logical "next" character instead of the original one it was combined with.
typeof objectString;//"object"
typeof [Link]();//"string" '?????.'.split('').reverse().join(''); //fails
Concatenating Strings
While the method will work fine for most languages, a truly accurate, encoding respecting algorithm for string
String concatenation can be done with the + concatenation operator, or with the built-in concat() method on the reversal is slightly more involved. One such implementation is a tiny library called Esrever, which uses regular
String object prototype. expressions for matching combining marks and surrogate pairs in order to perform the reversing perfectly.
[Link] – JavaScript® Notes for Professionals 37 [Link] – JavaScript® Notes for Professionals 38
function reverseString(str) { });
return [...String(str)].reverse().join(''); [Link](arr); // [ "apples", "bananas", "cranberries" ]
}
[Link](reverseString('stackoverflow')); // "wolfrevokcats"
Section 7.4: Access character at index in string
[Link](reverseString(1337)); // "7331"
[Link](reverseString([1, 2, 3])); // "3,2,1" Use charAt() to get a character at the specified index in the string.
function reverse(string) {
var strRev = ""; Alternatively, because strings can be treated like arrays, use the index via bracket notation.
for (var i = [Link] - 1; i >= 0; i--) {
strRev += string[i]; var string = "Hello, World!";
} [Link]( string[4] ); // "o"
return strRev;
} To get the character code of the character at a specified index, use charCodeAt().
reverse("zebra"); // "arbez"
var string = "Hello, World!";
[Link]( [Link](4) ); // 111
Section 7.3: Comparing Strings Lexicographically
Note that these methods are all getter methods (return a value). Strings in JavaScript are immutable. In other
To compare strings alphabetically, use localeCompare(). This returns a negative value if the reference string is words, none of them can be used to set a character at a position in the string.
lexicographically (alphabetically) before the compared string (the parameter), a positive value if it comes
afterwards, and a value of 0 if they are equal. Section 7.5: Escaping quotes
var a = "hello"; If your string is enclosed (i.e.) in single quotes you need to escape the inner literal quote with backslash \
var b = "world";
The > and < operators can also be used to compare strings lexicographically, but they cannot return a value of zero
Same goes for double quotes:
(this can be tested with the == equality operator). As a result, a form of the localeCompare() function can be
written like so: var text = "I feel \"high\"";
function strcmp(a, b) {
Special attention must be given to escaping quotes if you're storing HTML representations within a String, since
if(a === b) {
return 0;
HTML strings make large use of quotations i.e. in attributes:
}
var content = "<p class=\"special\">Hello World!</p>"; // valid String
if (a > b) { var hello = '<p class="special">I\'d like to say "Hi"</p>'; // valid String
return 1;
} Quotes in HTML strings can also be represented using ' (or ') as a single quote and " ( or ") as
double quotes.
return -1;
}
var hi = "<p class='special'>I'd like to say "Hi"</p>"; // valid String
[Link](strcmp("hello", "world")); // -1 var hello = '<p class="special">I'd like to say "Hi"</p>'; // valid String
[Link](strcmp("hello", "hello")); // 0
[Link](strcmp("world", "hello")); // 1 Note: The use of ' and " will not overwrite double quotes that browsers can automatically place on
attribute quotes. For example <p class=special> being made to <p class="special">, using " can lead to
This is especially useful when using a sorting function that compares based on the sign of the return value (such as <p class=""special""> where \" will be <p class="special">.
sort).
Version ≥ 6
[Link] – JavaScript® Notes for Professionals 39 [Link] – JavaScript® Notes for Professionals 40
var x = `"Escaping " and ' can become very annoying`; Section 7.9: Strings are unicode
Section 7.6: Word Counter All JavaScript strings are unicode!
Say you have a <textarea> and you want to retrieve info about the number of: var s = "some ∆≈ƒ unicode ¡™£¢¢¢";
[Link](5); // 8710
Characters (total)
Characters (no spaces) There are no raw byte or binary strings in JavaScript. To effectively handle binary data, use Typed Arrays.
Words
Lines Section 7.10: Detecting a string
function wordCount( val ){ To detect whether a parameter is a primitive string, use typeof:
var wom = [Link](/\S+/g);
return { var aString = "my string";
charactersNoSpaces : [Link](/\s+/g, '').length, var anInt = 5;
characters : [Link], var anObj = {};
words : wom ? [Link] : 0, typeof aString === "string"; // true
lines : [Link](/\r*\n/).length typeof anInt === "string"; // false
}; typeof anObj === "string"; // false
}
If you ever have a String object, via new String("somestr"), then the above will not work. In this instance, we can
// Use like: use instanceof:
wordCount( someMultilineText ).words; // (Number of words)
var aStringObj = new String("my string");
jsFiddle example aStringObj instanceof String; // true
Section 7.7: Trim whitespace To cover both instances, we can write a simple helper function:
To trim whitespace from the edges of a string, use [Link]: var isString = function(value) {
return typeof value === "string" || value instanceof String;
};
" some whitespaced string ".trim(); // "some whitespaced string"
var aString = "Primitive String";
Many JavaScript engines, but not Internet Explorer, have implemented non-standard trimLeft and trimRight var aStringObj = new String("String Object");
methods. There is a proposal, currently at Stage 1 of the process, for standardised trimStart and trimEnd isString(aString); // true
isString(aStringObj); // true
methods, aliased to trimLeft and trimRight for compatibility.
isString({}); // false
isString(5); // false
// Stage 1 proposal
" this is me ".trimStart(); // "this is me "
" this is me ".trimEnd(); // " this is me" Or we can make use of toString function of Object. This can be useful if we have to check for other types as well
say in a switch statement, as this method supports other datatypes as well just like typeof.
// Non-standard methods, but currently implemented by most engines
" this is me ".trimLeft(); // "this is me " var pString = "Primitive String";
" this is me ".trimRight(); // " this is me" var oString = new String("Object Form of String");
[Link](pString);//"[object String]"
A more robust solution is to not detect a string at all, rather only check for what functionality is required. For
Use .split to go from strings to an array of the split substrings:
example:
var s = "one, two, three, four, five"
[Link](", "); // ["one", "two", "three", "four", "five"] var aString = "Primitive String";
// Generic check for a substring method
if([Link]) {
Use the array method .join to go back to a string:
}
[Link](", ").join("--"); // "one--two--three--four--five" // Explicit check for the String substring prototype method
[Link] – JavaScript® Notes for Professionals 41 [Link] – JavaScript® Notes for Professionals 42
if([Link] === [Link]) { // base 16 String representation
[Link](0, ); var b16 = 'c';
}
// base 10 Number
Use .slice() to extract substrings given two indices: To convert an arbitrary number (i.e. non-integer) from its String representation into a Number, the operation must be
split into two parts; the integer part and the fraction part.
var s = "0123456789abcdefg";
Version ≥ 6
[Link](0, 5); // "01234"
[Link](5, 6); // "5" let b16 = '3.243f3e0370cdc';
// Split into integer and fraction parts
let [i16, f16] = [Link]('.');
Given one index, it will take from that index to the end of the string:
// Calculate base 10 integer part
[Link](10); // "abcdefg" let i10 = parseInt(i16, 16); // 3
The method charCodeAt retrieves the Unicode character code of a single character: // Put the base 10 parts together to find the Number
let b10 = i10 + f10; // 3.14159
var charCode = "µ".charCodeAt(); // The character code of the letter µ is 181
Note 1: Be careful as small errors may be in the result due to differences in what is possible to be represented in
To get the character code of a character in a string, the 0-based position of the character is passed as a parameter different bases. It may be desirable to perform some kind of rounding afterwards.
to charCodeAt: Note 2: Very long representations of numbers may also result in errors due to the accuracy and maximum values
of Numbers of the environment the conversions are happening in.
var charCode = "ABCDE".charCodeAt(3); // The character code of "D" is 68
Version ≥ 6
Section 7.14: String Find and Replace Functions
Some Unicode symbols don't fit in a single character, and instead require two UTF-16 surrogate pairs to encode.
To search for a string inside a string, there are several functions:
This is the case of character codes beyond 216 - 1 or 63553. These extended character codes or code point values
can be retrieved with codePointAt: indexOf( searchString ) and lastIndexOf( searchString )
// The Grinning Face Emoji has code point 128512 or 0x1F600 indexOf() will return the index of the first occurrence of searchString in the string. If searchString is not found,
var codePoint = "????".codePointAt(); then -1 is returned.
The most common representation after decimal (base 10) is hexadecimal (base 16), but the contents of this section Similarly, lastIndexOf() will return the index of the last occurrence of searchstring or -1 if not found.
work for all bases in the range.
var string = "Hello, World!";
In order to convert a Number from decimal (base 10) to its hexadecimal (base 16) String representation the toString [Link]( [Link]("o") ); // 8
[Link]( [Link]("foo") ); // -1
method can be used with radix 16.
[Link] – JavaScript® Notes for Professionals 43 [Link] – JavaScript® Notes for Professionals 44
replace( regexp|substring, replacement|replaceFunction )
Section 7.17: String to Lower Case
replace() will return a string that has all occurrences of substrings matching the RegExp regexp or string
[Link]()
substring with a string replacement or the returned value of replaceFunction.
[Link]('QWERTY'.toLowerCase()); // 'qwerty'
Note that this does not modify the string in place, but returns the string with replacements.
string = [Link]( /W.{3}d/g, "Universe" ); This can be done using the .repeat() method:
[Link]( string ); // "Bye, Universe!"
"abc".repeat(3); // Returns "abcabcabc"
replaceFunction can be used for conditional replacements for regular expression objects (i.e., with use with "abc".repeat(0); // Returns ""
"abc".repeat(-1); // Throws a RangeError
regexp). The parameters are in the following order:
Version < 6
Parameter Meaning
In the general case, this should be done using a correct polyfill for the ES6 [Link]() method.
match the substring that matches the entire regular expressiong
Otherwise, the idiom new Array(n + 1).join(myString) can repeat n times the string myString:
g1, g2, g3, ... the matching groups in the regular expression
offset the offset of the match in the entire string var myString = "abc";
string the entire string var n = 3;
Note that all parameters are optional. new Array(n + 1).join(myString); // Returns "abcabcabc"
'Hellow World'.indexOf('Wor'); // 7
.indexOf also accepts an additional numeric argument that indicates on what index should the function start
looking
'Hellow World'.indexOf('WOR'); // -1
[Link]():
[Link]('qwerty'.toUpperCase()); // 'QWERTY'
[Link] – JavaScript® Notes for Professionals 45 [Link] – JavaScript® Notes for Professionals 46
Chapter 8: Date to show the date and time in UTC (the Z in the formatted string denotes UTC).
// Creates a Date object with the current date and time from the
Parameter Details // user's browser
value The number of milliseconds since 1 January 1970 00:00:00.000 UTC (Unix epoch) var now = new Date();
[Link]() === 'Mon Apr 11 2016 16:10:41 GMT-0500 (Central Daylight Time)'
dateAsString A date formatted as a string (see examples for more information)
// true
The year value of the date. Note that month must also be provided, or the value will be interpreted // well, at the time of this writing, anyway
year as a number of milliseconds. Also note that values between 0 and 99 have special meaning. See the
examples. // Creates a Date object at the Unix Epoch (i.e., '1970-01-01T00:00:00.000Z')
The month, in the range 0-11. Note that using values outside the specified range for this and the var epoch = new Date(0);
month following parameters will not result in an error, but rather cause the resulting date to "roll over" to [Link]() === '1970-01-01T00:00:00.000Z' // true
the next value. See the examples.
// Creates a Date object with the date and time 2,012 milliseconds
day Optional: The date, in the range 1-31.
// after the Unix Epoch (i.e., '1970-01-01T00:00:02.012Z').
hour Optional: The hour, in the range 0-23. var ms = new Date(2012);
minute Optional: The minute, in the range 0-59. [Link]() === '1970-01-01T00:00:02.012Z' // true
second Optional: The second, in the range 0-59. // Creates a Date object with the first day of February of the year 2012
millisecond Optional: The millisecond, in the range 0-999. // in the local timezone.
var Date(2012, 1);
[Link]() === 'Wed Feb 01 2012 00:00:00 GMT-0600 (Central Standard Time)'
Section 8.1: Create a new Date object // true
To create a new Date object use the Date() constructor: // Creates a Date object with the first day of the year 2012 in the local
// timezone.
with no arguments // (Months are zero-based)
var zero = new Date(2012, 0);
[Link]() === 'Sun Jan 01 2012 00:00:00 GMT-0600 (Central Standard Time)'
Date() creates a Date instance containing the current time (up to milliseconds) and date. // true
// Creates a Date object with the first day of the year 2012, in UTC.
with one integer argument var utc = new Date([Link](2012, 0));
[Link]() === 'Sat Dec 31 2011 18:00:00 GMT-0600 (Central Standard Time)'
// true
Date(m) creates a Date instance containing the time and date corresponding to the Epoch time (1 January, [Link]() === '2012-01-01T00:00:00.000Z'
1970 UTC) plus m milliseconds. Example: new Date(749019369738) gives the date Sun, 26 Sep 1993 04:56:09 // true
GMT.
// Parses a string into a Date object (ISO 8601 format added in ECMAScript 5.1)
// Implementations should assumed UTC because of ISO 8601 format and Z designation
var iso = new Date('2012-01-01T00:00:00.000Z');
with a string argument [Link]() === '2012-01-01T00:00:00.000Z' // true
[Link] – JavaScript® Notes for Professionals 47 [Link] – JavaScript® Notes for Professionals 48
// Special dates for years in the range 0-99 Convert to GMT String
var special1 = new Date(12, 0);
var date1 = new Date();
[Link]() === 'Mon Jan 01 1912 00:00:00 GMT-0600 (Central Standard Time)`
[Link]();
// true
// If you actually wanted to set the year to the year 12 CE, you'd need to use the
// setFullYear() method: Returns: "Thu, 14 Apr 2016 23:49:08 GMT"
[Link](12);
[Link]() === 'Sun Jan 01 12 00:00:00 GMT-0600 (Central Standard Time)`
// true This function has been marked as deprecated so some browsers may not support it in the future. It is suggested to
use toUTCString() instead.
Returns: "4/14/2016"
Returns: "Fri Apr 15 2016 07:48:48 GMT-0400 (Eastern Daylight Time)"
This function returns a locale sensitive date string based upon the user's location by default.
[Link](["zh", "en-US"]);
Returns: "07:48:48 GMT-0400 (Eastern Daylight Time)"
would attempt to print the string in the Chinese locale using United States English as a fallback. The options
parameter can be used to provide specific formatting. For example:
Convert to Date String
var date1 = new Date(); var options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
[Link](); [Link]([], options);
would result in
Returns: "Thu Apr 14 2016"
[Link] – JavaScript® Notes for Professionals 49 [Link] – JavaScript® Notes for Professionals 50
function formatDate(dayOfWeek, day, month, year) { [Link]("Foo was born on: " + formatDate([Link](), [Link](),
var daysOfWeek = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]; [Link](), [Link]()));
var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
return daysOfWeek[dayOfWeek] + " " + months[month] + " " + day + " " + year;
} Sample output:
//Foo lives in a country with timezone GMT + 1 Foo was born on: Sat Jan 1 2000
var birthday = new Date(2000,0,1);
[Link]("Foo was born on: " + formatDate([Link](), [Link](),
[Link](), [Link]()));
Creating a Date from UTC
sendToBar([Link]());
If one wants to create a Date object based on UTC or GMT, the [Link](...) method can be used. It uses the
same arguments as the longest Date constructor. This method will return a number representing the time that has
Sample output: passed since January 1, 1970, 00:00:00 UTC.
Sample output:
Sample output:
Foo was born on: Fri Dec 31 1999
Mon Jan 31 2000 13:00:00 GMT+0100 (West-Europa (standaardtijd))
And thus, Bar would always believe Foo was born on the last day of 1999.
Unsurprisingly, the difference between UTC time and local time is, in fact, the timezone offset converted to
Correct approach
milliseconds.
function formatDate(dayOfWeek, day, month, year) {
var daysOfWeek = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
var utcDate = new Date([Link](2000,0,31,12));
var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
var localDate = new Date(2000,0,31,12);
return daysOfWeek[dayOfWeek] + " " + months[month] + " " + day + " " + year;
}
[Link](localDate - utcDate === [Link]() * 60 * 1000);
All Date object modifiers, such as setDate(...) and setFullYear(...) have an equivalent takes an argument in
Sample output: UTC time rather than in local time.
Foo was born on: Sat Jan 1 2000 var date = new Date();
[Link](2000,0,31);
[Link](12,0,0,0);
[Link](date);
//Meanwhile somewhere else...
[Link] – JavaScript® Notes for Professionals 51 [Link] – JavaScript® Notes for Professionals 52
Mon Jan 31 2000 13:00:00 GMT+0100 (West-Europa (standaardtijd)) zone
hour12 :possible values are true and false; the default is locale dependent
formatMatcher : possible values are "basic" and "best fit"; the default is "best fit"
The other UTC-specific modifiers are .setUTCMonth(), .setUTCDate() (for the day of the month), weekday : possible values are "narrow", "short" & "long"
.setUTCMinutes(), .setUTCSeconds() and .setUTCMilliseconds(). era : possible values are "narrow", "short" & "long"
year : possible values are "numeric" & "2-digit"
Avoiding ambiguity with getTime() and setTime()
month : possible values are "numeric", "2-digit", "narrow", "short" & "long"
Where the methods above are required to differentiate between ambiguity in dates, it is usually easier to day : possible values are "numeric" & "2-digit"
communicate a date as the amount of time that has passed since January 1, 1970, 00:00:00 UTC. This single number hour : possible values are "numeric" & "2-digit"
represents a single point in time, and can be converted to local time whenever necessary. minute : possible values are "numeric" & "2-digit"
second : possible values are "numeric" & "2-digit"
var date = new Date([Link](2000,0,31,12)); timeZoneName : possible values are "short" & "long"
var timestamp = [Link]();
//Alternatively
var timestamp2 = [Link](2000,0,31,12); How to use
[Link](timestamp === timestamp2);
var today = new Date().toLocaleDateString('en-GB', {
day : 'numeric',
month : 'short',
Sample output: true year : 'numeric'
});
If [Link]() isn't flexible enough to fulfill whatever need you may have, you might
want to consider creating a custom Date object that looks like this:
Sample output:
[Link] – JavaScript® Notes for Professionals 53 [Link] – JavaScript® Notes for Professionals 54
} Get the current month
};
var month = (new Date()).getMonth();
return date;
[Link](month);
})();
// Sample output: 0
If you included that code and executed new DateObject() on January 20 ʰ, 2019, it would produce an object with
Please note that 0 = January. This is because months range from 0 to 11, so it is often desirable to add +1 to the
the following properties:
index.
day: 20
Get the current day
dayPadded: "20"
month: 1 var day = (new Date()).getDate();
monthPadded: "01" [Link](day);
monthName: "January" // Sample output: 31
year: 2019 Get the current hour
var hours = (new Date()).getHours();
To get a formatted string, you could do something like this: [Link](hours);
// Sample output: 10
new DateObject().get(['dayPadded', 'monthPadded', 'year']);
Get the current minutes
var minutes = (new Date()).getMinutes();
That would produce the following output:
[Link](minutes);
// Sample output: 39
20-01-2016 Get the current seconds
var seconds = (new Date()).getSeconds();
[Link](second);
(*) According to the MDN, "modern browsers" means Chrome 24+, Firefox 29+, IE11, Edge12+, Opera 15+ & Safari
// Sample output: 48
nightly build
Get the current milliseconds
Section 8.5: Get the number of milliseconds elapsed since 1 To get the milliseconds (ranging from 0 to 999) of an instance of a Date object, use its getMilliseconds method.
January 1970 00:00:00 UTC
var milliseconds = (new Date()).getMilliseconds();
The static method [Link] returns the number of milliseconds that have elapsed since 1 January 1970 00:00:00 [Link](milliseconds);
UTC. To get the number of milliseconds that have elapsed since that time using an instance of a Date object, use its // Output: milliseconds right now
getTime method. Convert the current time and date to a human-readable string
var now = new Date();
// get milliseconds using static method now of Date // convert date to a string in UTC timezone format:
[Link]([Link]()); [Link]([Link]());
// Output: Wed, 21 Jun 2017 09:13:01 GMT
// get milliseconds using method getTime of Date instance
[Link]((new Date()).getTime());
The static method [Link]() returns the number of milliseconds that have elapsed since 1 January 1970 00:00:00
UTC. To get the number of milliseconds that have elapsed since that time using an instance of a Date object, use its
Section 8.6: Get the current time and date getTime method.
Use new Date() to generate a new Date object containing the current date and time. // get milliseconds using static method now of Date
[Link]([Link]());
Note that Date() called without arguments is equivalent to new Date([Link]()).
// get milliseconds using method getTime of Date instance
Once you have a date object, you can apply any of the several available methods to extract its properties (e.g. [Link]((new Date()).getTime());
getFullYear() to get the 4-digits year).
Below are some common date methods. Section 8.7: Increment a Date Object
Get the current year To increment date objects in JavaScript, we can usually do this:
[Link] – JavaScript® Notes for Professionals 55 [Link] – JavaScript® Notes for Professionals 56
[Link](checkoutDate); // Fri Jul 22 2016 10:05:13 GMT-0400 (EDT)
Chapter 9: Date Comparison
It is possible to use setDate to change the date to a day in the following month by using a value larger than the
number of days in the current month - Section 9.1: Comparing Date values
var checkoutDate = new Date(); // Thu Jul 21 2016 10:05:13 GMT-0400 (EDT) To check the equality of Date values:
[Link]( [Link]() + 12 );
[Link](checkoutDate); // Tue Aug 02 2016 10:05:13 GMT-0400 (EDT) var date1 = new Date();
var date2 = new Date([Link]() + 10);
The same applies to other methods such as getHours(), getMonth(),etc. [Link]([Link]() === [Link]());
[Link] – JavaScript® Notes for Professionals 57 [Link] – JavaScript® Notes for Professionals 58
Section 9.2: Date Dierence Calculation Chapter 10: Comparison Operations
To compare the difference of two dates, we can do the comparison based on the timestamp.
Section 10.1: Abstract equality / inequality and type
var date1 = new Date(); conversion
var date2 = new Date([Link]() + 5000);
The Problem
var dateDiff = [Link]() - [Link]();
var dateDiffInYears = dateDiff/1000/60/60/24/365; //convert milliseconds into years
The abstract equality and inequality operators (== and !=) convert their operands if the operand types do not
[Link]("Date difference in years : " + dateDiffInYears); match. This type coercion is a common source of confusion about the results of these operators, in particular, these
operators aren't always transitive as one would expect.
"" == 0; // true A
0 == "0"; // true A
"" == "0"; // false B
false == 0; // true
false == "0"; // true
"" != 0; // false A
0 != "0"; // false A
"" != "0"; // true B
false != 0; // false
false != "0"; // false
The results start to make sense if you consider how JavaScript converts empty strings to numbers.
Number(""); // 0
Number("0"); // 0
Number(false); // 0
The Solution
In the statement false B, both the operands are strings ("" and "0"), hence there will be no type conversion and
since "" and "0" are not the same value, "" == "0" is false as expected.
One way to eliminate unexpected behavior here is making sure that you always compare operands of the same
type. For example, if you want the results of numerical comparison use explicit conversion:
Side-note: Number("0") and new Number("0") isn't the same thing! While the former performs a type conversion,
the latter will create a new object. Objects are compared by reference and not by value which explains the results
below.
[Link] – JavaScript® Notes for Professionals 59 [Link] – JavaScript® Notes for Professionals 60
new Number("0") == new Number("0"); // false [Link]({}); // false
Version < 6
Finally, you have the option to use strict equality and inequality operators which will not perform any implicit type
conversions. You can check if a value is NaN by comparing it with itself:
"" === 0; // false value !== value; // true for NaN, false for any other value
0 === "0"; // false
"" === "0"; // false You can use the following polyfill for [Link]():
Further reference to this topic can be found here: [Link] = [Link] || function(value) {
return value !== value;
Which equals operator (== vs ===) should be used in JavaScript comparisons?. }
Abstract Equality (==) By contrast, the global function isNaN() returns true not only for NaN, but also for any value or expression that
cannot be coerced into a number:
Section 10.2: NaN Property of the Global Object
isNaN(NaN); // true
NaN ("Not a Number") is a special value defined by the IEEE Standard for Floating-Point Arithmetic, which is used when isNaN(0 / 0); // true
isNaN('str' - 12); // true
a non-numeric value is provided but a number is expected (1 * "two"), or when a calculation doesn't have a valid
number result ([Link](-1)). isNaN(24); // false
isNaN('24'); // false
Any equality or relational comparisons with NaN returns false, even comparing it with itself. Because, NaN is isNaN(Infinity); // false
supposed to denote the result of a nonsensical computation, and as such, it isn’t equal to the result of any other
nonsensical computations. isNaN('str'); // true
isNaN(undefined); // true
isNaN({}); // true
(1 * "two") === NaN //false
NaN === 0; // false ECMAScript defines a “sameness” algorithm called SameValue which, since ECMAScript 6, can be invoked with
NaN === NaN; // false [Link]. Unlike the == and === comparison, using [Link]() will treat NaN as identical with itself (and -0 as not
[Link] === NaN; // false identical with +0):
[Link] – JavaScript® Notes for Professionals 61 [Link] – JavaScript® Notes for Professionals 62
typeof(NaN) === "number"; //true F() || T(); // true
The and-operator (&&) and the or-operator (||) employ short-circuiting to prevent unnecessary work if the outcome
'F'
of the operation does not change with the extra work.
'T'
In x && y, y will not be evaluated if x evaluates to false, because the whole expression is guaranteed to be false.
Short-circuiting to prevent errors
In x || y, y will not be evaluated if x evaluated to true, because the whole expression is guaranteed to be true.
var obj; // object has value of undefined
Example with functions if([Link]){ }// TypeError: Cannot read property 'property' of undefined
if([Link] && obj !== undefined){}// Line A TypeError: Cannot read property 'property' of
Take the following two functions: undefined
function T() { // True Line A: if you reverse the order the first conditional statement will prevent the error on the second by not executing
[Link]("T");
it if it would throw the error
return true;
}
if(obj !== undefined && [Link]){}; // no error thrown
function F() { // False
[Link]("F"); But should only be used if you expect undefined
return false;
}
if(typeof obj === "object" && [Link]){}; // safe option but slower
Example 1
Short-circuiting to provide a default value
T() && F(); // false The || operator can be used to select either a "truthy" value, or the default value.
Output: For example, this can be used to ensure that a nullable value is converted to a non-nullable value:
[Link] – JavaScript® Notes for Professionals 63 [Link] – JavaScript® Notes for Professionals 64
// To this conversion happens is based on the specification of the operator:
cb && cb();
} Specification for the == operator:
Of course, the test above does not validate that cb is in fact a function and not just an
Object/Array/String/Number. 7.2.13 Abstract Equality Comparison
The comparison x == y, where x and y are values, produces true or false. Such a comparison is
Section 10.4: Null and Undefined performed as follows:
The differences between null and undefined 1. If Type(x) is the same as Type(y), then:
undefined is a property of the global Object, usually immutable in the global scope. This means anywhere you
Examples:
can define an identifier other than in the global namespace could hide undefined from that scope (although
1 == 1; // true
things can still be undefined)
1 == true; // true (operand converted to number: true => 1)
null is a word literal, so it's meaning can never be changed and attempting to do so will throw an Error. 1 == '1'; // true (operand converted to number: '1' => 1 )
1 == '1.00'; // true
The similarities between null and undefined 1 == '1.00000000001'; // false
1 == '1.00000000000000001'; // true (true due to precision loss)
null and undefined are both falsy. null == undefined; // true (spec #2)
1 == 2; // false
if (null) [Link]("won't be logged"); 0 == false; // true
if (undefined) [Link]("won't be logged"); 0 == undefined; // false
0 == ""; // true
Using undefined
AND
If the current scope can't be trusted, use something which evaluates to undefined, for example void 0;.
If undefined is shadowed by another value, it's just as bad as shadowing Array or Number. This operator will return true if both of the expressions evaluate to true. This boolean operator will employ short-
Avoid setting something as undefined. If you want to remove a property bar from an Object foo, delete circuiting and will not evaluate y if x evaluates to false.
[Link]; instead.
x && y;
Existence testing identifier foo against undefined could throw a Reference Error, use typeof foo against
"undefined" instead.
This will return false, because y is false.
Operands of the abstract equality operator are compared after being converted to a common type. How this This operator will return true if one of the two expressions evaluate to true. This boolean operator will employ
[Link] – JavaScript® Notes for Professionals 65 [Link] – JavaScript® Notes for Professionals 66
short-circuiting and y will not be evaluated if x evaluates to true. var a = 'hello' && ''; // a = ''
var b = '' && []; // b = ''
x || y; var c = undefined && 0; // c = undefined
var d = 1 && 5; // d = 5
var e = 0 && {}; // e = 0
This will return true, because x is true.
var f = 'hi' && [] && 'done'; // f = 'done'
var g = 'bye' && undefined && 'adios'; // g = undefined
NOT
This trick can be used, for example, to set a default value to a function argument (prior to ES6).
This operator will return false if the expression on the right evaluates to true, and return true if the expression on
the right evaluates to false.
var foo = function(val) {
// if val evaluates to falsey, 'default' will be returned instead.
!x; return val || 'default';
}
This will return false, because x is true.
[Link]( foo('burger') ); // burger
JavaScript is loosely typed. A variable can contain different data types, and a variable can change its data type:
Just keep in mind that for arguments, 0 and (to a lesser extent) the empty string are also often valid values that
should be able to be explicitly passed and override a default, which, with this pattern, they won’t (because they are
var x = "Hello"; // typeof x is a string
x = 5; // changes typeof x to a number falsy).
When doing mathematical operations, JavaScript can convert numbers to strings: Section 10.9: Empty Array
var x = 5 + 7; // [Link]() is 12, typeof x is a number /* ToNumber(ToPrimitive([])) == ToNumber(false) */
var x = 5 + "7"; // [Link]() is 57, typeof x is a string [] == false; // true
var x = "5" + 7; // [Link]() is 57, typeof x is a string
var x = 5 - 7; // [Link]() is -2, typeof x is a number When [].toString() is executed it calls [].join() if it exists, or [Link]() otherwise. This
var x = 5 - "7"; // [Link]() is -2, typeof x is a number
comparison is returning true because [].join() returns '' which, coerced into 0, is equal to false ToNumber.
var x = "5" - 7; // [Link]() is -2, typeof x is a number
var x = 5 - "x"; // [Link]() is NaN, typeof x is a number
Beware though, all objects are truthy and Array is an instance of Object:
Subtracting a string from a string, does not generate an error but returns NaN (Not a Number):
// Internally this is evaluated as ToBoolean([]) === true ? 'truthy' : 'falsy'
[] ? 'truthy' : 'falsy'; // 'truthy'
"Hello" - "Dolly" // returns NaN
Logical OR (||), reading left to right, will evaluate to the first truthy value. If no truthy value is found, the last value is SameValue
returned.
It returns true if both operands belong to the same Type and are the same value.
var a = 'hello' || ''; // a = 'hello'
var b = '' || []; // b = [] Note: the value of an object is a reference.
var c = '' || undefined; // c = undefined
var d = 1 || 5; // d = 1 You can use this comparison algorithm via [Link] (ECMAScript 6).
var e = 0 || {}; // e = {}
var f = 0 || '' || 5; // f = 5 Examples:
var g = '' || 'yay' || 'boo'; // g = 'yay'
[Link](1, 1); // true
Logical AND (&&), reading left to right, will evaluate to the first falsy value. If no falsey value is found, the last value is [Link](+0, -0); // false
returned. [Link](NaN, NaN); // true
[Link](true, "true"); // false
[Link](false, 0); // false
[Link] – JavaScript® Notes for Professionals 67 [Link] – JavaScript® Notes for Professionals 68
[Link](null, undefined); // false Symmetry: x === y is true if, and only if, y === xistrue, for any valuesxandy`.
[Link](1, "1"); // false
Transitivity: If x === y and y === z are true, then x === z is also true, for any values x, y and z.
[Link]([], []); // false
It behaves like SameValue, but considers +0 and -0 to be equal. undefined and null are considered to be equal
When comparing a number with a string, the string is coerced to a number
You can use this comparison algorithm via [Link] (ECMAScript 7). When comparing a boolean with something else, the boolean is coerced to a number
When comparing an object with a number, string or symbol, the object is coerced to a primitive
Examples:
If there was a coercion, the coerced values are compared recursively. Otherwise the algorithm returns false.
[1].includes(1); // true
[+0].includes(-0); // true You can use this comparison algorithm via the == operator (ECMAScript 1).
[NaN].includes(NaN); // true
[true].includes("true"); // false There is also the != operator (ECMAScript 1), which negates the result of ==.
[false].includes(0); // false
[1].includes("1"); // false
Examples:
[null].includes(undefined); // false
[[]].includes([]); // false
1 == 1; // true
+0 == -0; // true
This algorithm still has the properties of an equivalence relation: NaN == NaN; // false
true == "true"; // false
Reflexivity: [x].includes(x) is true, for any value x false == 0; // true
Symmetry: [x].includes(y) is true if, and only if, [y].includes(x) is true, for any values x and y. 1 == "1"; // true
Transitivity: If [x].includes(y) and [y].includes(z) are true, then [x].includes(z) is also true, for any null == undefined; // true
[] == []; // false
values x, y and z.
It behaves like SameValue, but Symmetry: x == y is true if, and only if, y == x is true, for any values x and y.
There is also the !== operator (ECMAScript 3), which negates the result of ===. Section 10.11: Relational operators (<, <=, >, >=)
Examples: When both operands are numeric, they are compared normally:
1 === 1; // true
1 < 2 // true
+0 === -0; // true
2 <= 2 // true
NaN === NaN; // false
3 >= 5 // false
true === "true"; // false
true < false // false (implicitly converted to numbers, 1 > 0)
false === 0; // false
1 === "1"; // false
null === undefined; // false When both operands are strings, they are compared lexicographically (according to alphabetical order):
[] === []; // false
'a' < 'b' // true
This algorithm has the following properties: '1' < '2' // true
[Link] – JavaScript® Notes for Professionals 69 [Link] – JavaScript® Notes for Professionals 70
'100' > '12' // false ('100' is less than '12' lexicographically!)
Section 10.13: List of Comparison Operators
When one operand is a string and the other is a number, the string is converted to a number before comparison: Operator Comparison Example
== Equal i == 0
'1' < 2 // true === Equal Value and Type i === "5"
'3' > 2 // true
true > '2' // false (true implicitly converted to number, 1 < 2) != Not Equal i != 5
!== Not Equal Value or Type i !== 5
When the string is non-numeric, numeric conversion returns NaN (not-a-number). Comparing with NaN always > Greater than i > 5
returns false: < Less than i < 5
>= Greater than or equal i >= 5
1 < 'abc' // false
1 > 'abc' // false
<= Less than or equal i <= 5
But be careful when comparing a numeric value with null, undefined or empty strings: Section 10.14: Grouping multiple logic statements
1 > '' // true You can group multiple boolean logic statements within parenthesis in order to create a more complex logic
1 < '' // false evaluation, especially useful in if statements.
1 > null // true
1 < null // false
if ((age >= 18 && height >= 5.11) || (status === 'royalty' && hasInvitation)) {
1 > undefined // false
[Link]('You can enter our club');
1 < undefined // false
}
When one operand is a object and the other is a number, the object is converted to a number before
We could also move the grouped logic to variables to make the statement a bit shorter and descriptive:
[Link] null is particular case because Number(null);//0
var isLegal = age >= 18;
new Date(2015)< 1479480185280 // true var tall = height >= 5.11;
null > -1 //true var suitable = isLegal && tall;
({toString:function(){return 123}}) > 122 //true var isRoyalty = status === 'royalty';
var specialCase = isRoyalty && hasInvitation;
Sample:
Section 10.15: Bit fields to optimise comparison of multi state
1 != '1' // false data
1 != 2 // true
A bit field is a variable that holds various boolean states as individual bits. A bit on would represent true, and off
In the sample above, 1 != '1' is false because, a primitive number type is being compared to a char value. would be false. In the past bit fields were routinely used as they saved memory and reduced processing load.
Therefore, the JavaScript engine doesn't care about the datatype of the R.H.S value. Though the need to use bit field is no longer so important they do offer some benefits that can simplify many
processing tasks.
Operator: !== is the inverse of the === operator. Will return true if the operands are not equal or if their types do
not match. For example user input. When getting input from a keyboard's direction keys up, down, left, right you can encode
the various keys into a single variable with each direction assigned a bit.
Example:
Example reading keyboard via bitfield
1 !== '1' // true
1 !== 2 // true var bitField = 0; // the value to hold the bits
1 !== 1 // false const KEY_BITS = [4,1,8,2]; // left up right down
const KEY_MASKS = [0b1011,0b1110,0b0111,0b1101]; // left up right down
[Link] = [Link] = function (e) {
if([Link] >= 37 && [Link] <41){
[Link] – JavaScript® Notes for Professionals 71 [Link] – JavaScript® Notes for Professionals 72
if([Link] === "keydown"){
bitField |= KEY_BITS[[Link] - 37];
}else{
Chapter 11: Conditions
bitField &= KEY_MASKS[[Link] - 37];
Conditional expressions, involving keywords such as if and else, provide JavaScript programs with the ability to
}
} perform different actions depending on a Boolean condition: true or false. This section covers the use of JavaScript
} conditionals, Boolean logic, and ternary statements.
You may say the above example seems a lot more complex than assigning the various key states to an array. Yes, it Compare this to what the code would like with if/else conditions.
is a little more complex to set but the advantage comes when interrogating the state.
var animal = 'kitty';
If you want to test if all keys are up. var result = '';
if (animal === 'kitty') {
// as bit field result = 'cute';
if(!bitfield) // no keys are on } else {
result = 'still nice';
// as array test each item in array }
if(!(directionState[0] && directionState[1] && directionState[2] && directionState[3])){
The if or else conditions may have several operations. In this case the operator returns the result of the last
You can set some constants to make things easier expression.
[Link] – JavaScript® Notes for Professionals 73 [Link] – JavaScript® Notes for Professionals 74
Ternaries can be nested to encapsulate additional logic. For example The break statement "breaks" out of the switch statement and ensures no more code within the switch statement
is executed. This is how sections are defined and allows the user to make "fall through" cases.
foo ? bar ? 1 : 2 : 3
// To be clear, this is evaluated left to right Warning: lack of a break or return statement for each case means the program will continue to evaluate
// and can be more explicitly expressed as: the next case, even if the case criteria is unmet!
foo ? (bar ? 1 : 2) : 3
switch (value) {
This is the same as the following if/else case 1:
[Link]('I will only run if value === 1');
if (foo) { // Here, the code "falls through" and will run the code under case 2
if (bar) { case 2:
1 [Link]('I will run if value === 1 or value === 2');
} else { break;
2 case 3:
} [Link]('I will only run if value === 3');
} else { break;
3 }
}
The last case is the default case. This one will run if no other matches were made.
Stylistically this should only be used with short variable names, as multi-line ternaries can drastically decrease
readability. var animal = 'Lion';
switch (animal) {
The only statements which cannot be used in ternaries are control statements. For example, you cannot use return case 'Dog':
[Link]('I will not run since animal !== "Dog"');
or break with ternaries. The following expression will be invalid.
break;
case 'Cat':
var animal = 'kitty'; [Link]('I will not run since animal !== "Cat"');
for (var i = 0; i < 5; ++i) { break;
(animal === 'kitty') ? break:[Link](i); default:
} [Link]('I will run since animal does not match any other case');
}
For return statements, the following would also be invalid:
It should be noted that a case expression can be any kind of expression. This means you can use comparisons,
var animal = 'kitty'; function calls, etc. as case values.
(animal === 'kitty') ? return 'meow' : return 'woof';
function john() {
To do the above properly, you would return the ternary as follows: return 'John';
}
var animal = 'kitty';
return (animal === 'kitty') ? 'meow' : 'woof'; function jacob() {
return 'Jacob';
}
Section 11.2: Switch statement
switch (name) {
Switch statements compare the value of an expression against 1 or more values and executes different sections of case john(): // Compare name with the return value of john() (name == "John")
[Link]('I will run if name === "John"');
code based on that comparison.
break;
case 'Ja' + 'ne': // Concatenate the strings together then compare (name == "Jane")
var value = 1; [Link]('I will run if name === "Jane"');
switch (value) { break;
case 1: case john() + ' ' + jacob() + ' Jingleheimer Schmidt':
[Link]('I will always run'); [Link]('His name is equal to name too!');
break; break;
case 2: }
[Link]('I will never run');
break; Multiple Inclusive Criteria for Cases
}
Since cases "fall through" without a break or return statement, you can use this to create multiple inclusive criteria:
[Link] – JavaScript® Notes for Professionals 75 [Link] – JavaScript® Notes for Professionals 76
var x = "c" }
switch (x) {
case "a": Some important footnotes about the above examples:
case "b":
case "c": If any one condition evaluated to true, no other condition in that chain of blocks will be evaluated, and all
[Link]("Either a, b, or c was selected.");
corresponding blocks (including the else block) will not be executed.
break;
case "d": The number of else if parts is practically unlimited. The last example above only contains one, but you can
[Link]("Only d was selected.");
have as many as you like.
break;
default: The condition inside an if statement can be anything that can be coerced to a boolean value, see the topic on
[Link]("No case was matched.");
boolean logic for more details;
break; // precautionary break if case order changes
}
The if-else-if ladder exits at the first success. That is, in the example above, if the value of i is 0.5 then the
first branch is executed. If the conditions overlap, the first criteria occurring in the flow of execution is
Section 11.3: If / Else If / Else Control executed. The other condition, which could also be true is ignored.
In its most simple form, an if condition can be used like this: If you have only one statement, the braces around that statement are technically optional, e.g this is fine:
if (i < 1) {
And this will work as well:
[Link]("i is smaller than 1");
}
if (i < 1)
[Link]("i is smaller than 1");
The condition i < 1 is evaluated, and if it evaluates to true the block that follows is executed. If it evaluates to
false, the block is skipped.
If you want to execute multiple statements inside an if block, then the curly braces around them are
mandatory. Only using indentation isn't enough. For example, the following code:
An if condition can be expanded with an else block. The condition is checked once as above, and if it evaluates to
false a secondary block will be executed (which would be skipped if the condition were true). An example:
if (i < 1)
[Link]("i is smaller than 1");
if (i < 1) { [Link]("this will run REGARDLESS of the condition"); // Warning, see text!
[Link]("i is smaller than 1");
} else {
[Link]("i was not smaller than 1"); is equivalent to:
}
if (i < 1) {
[Link]("i is smaller than 1");
Supposing the else block contains nothing but another if block (with optionally an else block) like this:
}
[Link]("this will run REGARDLESS of the condition");
if (i < 1) {
[Link]("i is smaller than 1");
} else {
if (i < 2) { Section 11.4: Strategy
[Link]("i is smaller than 2");
} else { A strategy pattern can be used in JavaScript in many cases to replace a switch statement. It is especially helpful
[Link]("none of the previous conditions was true"); when the number of conditions is dynamic or very large. It allows the code for each condition to be independent
}
and separately testable.
}
Strategy object is simple an object with multiple functions, representing each separate condition. Example:
Then there is also a different way to write this which reduces nesting:
const AnimalSays = {
if (i < 1) { dog () {
[Link]("i is smaller than 1"); return 'woof';
} else if (i < 2) { },
[Link]("i is smaller than 2");
} else { cat () {
[Link]("none of the previous conditions was true"); return 'meow';
},
[Link] – JavaScript® Notes for Professionals 77 [Link] – JavaScript® Notes for Professionals 78
lion () {
},
return 'roar'; Chapter 12: Arrays
// ... other animals Section 12.1: Converting Array-like Objects to Arrays
default () { What are Array-like Objects?
return 'moo';
} JavaScript has "Array-like Objects", which are Object representations of Arrays with a length property. For example:
};
var realArray = ['a', 'b', 'c'];
The above object can be used as follows: var arrayLike = {
0: 'a',
function makeAnimalSpeak (animal) { 1: 'b',
// Match the animal by type 2: 'c',
const speak = AnimalSays[animal] || [Link]; length: 3
[Link](animal + ' says ' + speak()); };
}
Common examples of Array-like Objects are the arguments object in functions and HTMLCollection or NodeList
Results: objects returned from methods like [Link] or [Link].
makeAnimalSpeak('dog') // => 'dog says woof' However, one key difference between Arrays and Array-like Objects is that Array-like objects inherit from
makeAnimalSpeak('cat') // => 'cat says meow' [Link] instead of [Link]. This means that Array-like Objects can't access common Array
makeAnimalSpeak('lion') // => 'lion says roar' prototype methods like forEach(), push(), map(), filter(), and slice():
makeAnimalSpeak('snake') // => 'snake says moo'
Section 11.5: Using || and && short circuiting [Link](desiredOption); // Error! indexOf is not defined.
[Link](function() {
The Boolean operators || and && will "short circuit" and not evaluate the second parameter if the first is true or [Link](/* Stuff here */) // Error! map is not defined.
false respectively. This can be used to write short conditionals like: }); // Error! forEach is not defined.
1. [Link]:
Version ≥ 6
const arrayLike = {
0: 'Value 0',
1: 'Value 1',
length: 2
};
[Link](value => {/* Do something */}); // Errors
const realArray = [Link](arrayLike);
[Link](value => {/* Do something */}); // Works
2. for...of:
Version ≥ 6
var realArray = [];
for(const element of arrayLike) {
[Link](element);
}
[Link] – JavaScript® Notes for Professionals 79 [Link] – JavaScript® Notes for Professionals 80
3. Spread operator: }); // Wow! this works
Version ≥ 7 Version ≥ 6
var realArray = [Link](arrayLike); [Link](domList, element => [Link]); // Creates an array of tagName's
Convert Array-like Objects to Arrays in ≤ ES5 The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to
reduce it to a single value.
Use [Link] like so:
Array Sum
var arrayLike = {
0: 'Value 0', This method can be used to condense all values of an array into a single value:
1: 'Value 1',
length: 2
[1, 2, 3, 4].reduce(function(a, b) {
};
return a + b;
var realArray = [Link](arrayLike);
});
realArray = [].[Link](arrayLike); // Shorter version
// → 10
[Link]('Value 1'); // Wow! this works
Optional second parameter can be passed to reduce(). Its value will be used as the first argument (specified as a)
You can also use [Link] to call [Link] methods on Array-like objects directly, without for the first call to the callback (specified as function(a, b)).
converting them:
[2].reduce(function(a, b) {
Version ≥ 5.1 [Link](a, b); // prints: 1 2
var domList = [Link]('#myDropdown option'); return a + b;
}, 1);
[Link](function() { // → 3
// Do stuff
}); // Error! forEach is not defined.
Version ≥ 5.1
Flatten Array of Objects
[Link](domList, function() {
// Do stuff
}); // Wow! this works The example below shows how to flatten an array of objects into a single object.
var array = [{
You can also use [].[Link]( arrayLikeObject ) to borrow array methods and glom them on to your object:
key: 'one',
Version ≥ 5.1 value: 1
}, {
var arrayLike = {
key: 'two',
0: 'Value 0',
value: 2
1: 'Value 1',
}, {
length: 2
key: 'three',
};
value: 3
}];
[Link](function() {
Version ≤ 5.1
// Do stuff
}); // Error! forEach is not defined. [Link](function(obj, current) {
obj[[Link]] = [Link];
[].[Link](arrayLike)(function(val){ return obj;
// Do stuff with val }, {});
[Link] – JavaScript® Notes for Professionals 81 [Link] – JavaScript® Notes for Professionals 82
Version ≥ 6
var arr = [1, 2, 1, 5, 9, 5];
[Link]((obj, current) => [Link](obj, {
[[Link]]: [Link] [Link]((prev, number) => {
}), {}); if([Link](number) === -1) {
Version ≥ 7 [Link](number);
[Link]((obj, current) => ({...obj, [[Link]]: [Link]}), {}); }
return prev;
}, []);
Note that the Rest/Spread Properties is not in the list of finished proposals of ES2016. It isn't supported by ES2016. // → [1, 2, 5, 9]
But we can use babel plugin babel-plugin-transform-object-rest-spread to support it.
[Link] – JavaScript® Notes for Professionals 83 [Link] – JavaScript® Notes for Professionals 84
// Suppose we want to get all odd number in an array: This returns:
var numbers = [5, 32, 43, 4];
Version ≥ 5.1 [{
var odd = [Link](function(n) { id: 1,
return n % 2 !== 0; name: "John",
}); age: 28
},{
Version ≥ 6
id: 2,
let odd = [Link](n => n % 2 !== 0); // can be shortened to (n => n % 2) name: "Jane",
age: 31
odd would contain the following array: [5, 43]. }]
Results in:
You can search in the whole array for a value like this:
['1', '2', 'a', 'c', 'E', 'f', 'K', 'l', 'o', 'r', 's', 't', 'v', 'W']
var young = [Link]((obj) => {
var flag = false;
[Link](obj).forEach((val) => {
if(String(val).indexOf("J") > -1) { Note: The above sort will throw an error if any array items are not a string. If you know that the array
flag = true; may contain items that are not strings use the safe version below.
return;
}
}); ['s', 't', 'a', 'c', 'K', 1, 'v', 'E', 'r', 'f', 'l', 'o', 'W'].sort((a, b) => {
if(flag) return obj; return [Link]().localeCompare(b);
}); });
[Link] – JavaScript® Notes for Professionals 85 [Link] – JavaScript® Notes for Professionals 86
String sorting by length (longest first) new Date(2009, 6, 11),
new Date(2016, 7, 23)
];
["zebras", "dogs", "elephants", "penguins"].sort(function(a, b) {
return [Link] - [Link];
[Link](function(a, b) {
});
if (a > b) return -1;
if (a < b) return 1;
Results in return 0;
});
["elephants", "penguins", "zebras", "dogs"];
// the date objects can also sort by its difference
// the same way that numbers array is sorting
String sorting by length (shortest first)
[Link](function(a, b) {
return b-a;
["zebras", "dogs", "elephants", "penguins"].sort(function(a, b) { });
return [Link] - [Link];
});
Results in:
Results in
[
"Tue Aug 23 2016 00:00:00 GMT-0600 (MDT)",
["dogs", "zebras", "penguins", "elephants"]; "Fri Mar 21 2014 00:00:00 GMT-0600 (MDT)",
"Sat Jul 11 2009 00:00:00 GMT-0600 (MDT)",
Numerical Sort (ascending) "Mon Dec 10 2007 00:00:00 GMT-0700 (MST)"
]
Sorting array by even and odd numbers Of course, you will need to include an if(condition === true) { break; } or an if(condition === true) {
return; } somewhere inside that for-loop to get it to stop running.
[10, 21, 4, 15, 7, 99, 0, 12].sort(function(a, b) {
return (a & 1) - (b & 1) || a - b; Usually, though, the initialization is used to declare an index, the condition is used to compare that index with a
}); minimum or maximum value, and the afterthought is used to increment the index:
Date Sort (descending) Using a traditional for loop to loop through an array
[Link] – JavaScript® Notes for Professionals 87 [Link] – JavaScript® Notes for Professionals 88
[Link](myArray[i]); for (i in myArray) {
} [Link](myArray[i]);
}
Or, if you prefer to loop backwards, you do this:
This should be used with care, however, as it doesn't behave the same as a traditional for loop in all cases, and
for (var i = [Link] - 1; i > -1; i--) { there are potential side-effects that need to be considered. See Why is using "for...in" with array iteration a bad
[Link](myArray[i]);
idea? for more details.
}
for...of
There are, however, many variations possible, like for example this one:
In ES 6, the for-of loop is the recommended way of iterating over a the values of an array:
for (var key = 0, value = myArray[key], length = [Link]; key < length; value =
myArray[++key]) { Version ≥ 6
[Link](value); let myArray = [1, 2, 3, 4];
} for (let value of myArray) {
let twoValue = value * 2;
... or this one ... [Link]("2 * value is: %d", twoValue);
}
Like traditional for loops, while loops are supported by even the oldest of browsers. The .forEach(...) method is an option in ES 5 and above. It is supported by all modern browsers, as well as
Internet Explorer 9 and later.
Also, note that every while loop can be rewritten as a for loop. For example, the while loop hereabove behaves the
exact same way as this for-loop: Version ≥ 5
[1, 2, 3, 4].forEach(function(value, index, arr) {
for(var key = 0; value = myArray[key++];){ var twoValue = value * 2;
[Link](value); [Link]("2 * value is: %d", twoValue);
} });
Comparing with the traditional for loop, we can't jump out of the loop in .forEach(). In this case, use the for loop,
for...in
or use partial iteration presented below.
In JavaScript, you can also do this:
[Link] – JavaScript® Notes for Professionals 89 [Link] – JavaScript® Notes for Professionals 90
In all versions of JavaScript, it is possible to iterate through the indices of an array using a traditional C-style for Libraries
loop.
Finally, many utility libraries also have their own foreach variation. Three of the most popular ones are these:
var myArray = [1, 2, 3, 4];
for(var i = 0; i < [Link]; ++i) { [Link](), in jQuery:
var twoValue = myArray[i] * 2;
[Link]("2 * value is: %d", twoValue); $.each(myArray, function(key, value) {
} [Link](value);
});
It's also possible to use while loop:
_.each(), in [Link]:
var myArray = [1, 2, 3, 4],
i = 0, sum = 0; _.each(myArray, function(value, key, myArray) {
while(i++ < [Link]) { [Link](value);
sum += i; });
}
[Link](sum);
_.forEach(), in [Link]:
[Link]
Elements can be skipped
[Link] iterates until we return true:
const [,b,,c] = [1, 2, 3, 4];
Version ≥ 5
// [].some stops once it finds a false result [Link](b, c); // → 2, 4
// thus, this iteration will stop on value 7 (since 7 % 2 !== 0)
[2, 4, 7, 9].some(function(value, index, arr) { Rest operator can be used too
[Link](value);
return value === 7; // iterate until we find value 7
const [b,c, ...xs] = [2, 3, 4, 5];
});
[Link](b, c, xs); // → 2, 3, [4, 5]
[Link] – JavaScript® Notes for Professionals 91 [Link] – JavaScript® Notes for Professionals 92
const triangle = [3, 4, 5]; if (!compareArrays(array1[i], array2[i])) { // Do items compare recursively
return false;
area(triangle); // → 6 }
}
return true; // must be equal
Notice the third argument is not named in the function because it's not needed.
}
In the following example, our callback checks if the given value occurs in the array. If it does, it is a duplicate and will
not be copied to the resulting array. Note: The function uses the strict equality operator === to compare non array items {a: 0} === {a: 0}
Version ≥ 5.1 is false
var uniqueArray = ['a', 1, 'a', 2, '1', 1].filter(function(value, index, self) {
return [Link](value) === index;
}); // returns ['a', 1, 2, '1'] Section 12.10: Reversing arrays
If your environment supports ES6, you can also use the Set object. This object lets you store unique values of any .reverse is used to reverse the order of items inside an array.
Results in:
Section 12.9: Array comparison
[4, 3, 2, 1]
For simple array comparison you can use JSON stringify and compare the output strings:
[Link] – JavaScript® Notes for Professionals 93 [Link] – JavaScript® Notes for Professionals 94
deepReverse(arr); Version ≥ 3
Sometimes, you need to work with an array while ensuring you don't modify the original. Instead of a clone var arrConc = [...array1, ...array2, ...array3, ...array4]
method, arrays have a slice method that lets you perform a shallow copy of any part of an array. Keep in mind
that this only clones the first level. This works well with primitive types, like numbers and strings, but not objects. Results in a new Array:
To shallow-clone an array (i.e. have a new array instance but with the same elements), you can use the following ["a", "b", "c", "d", "e", "f", "g", "h"]
one-liner:
Without Copying the First Array
var clone = [Link]();
var longArray = [1, 2, 3, 4, 5, 6, 7, 8],
This calls the built-in JavaScript [Link] method. If you pass arguments to slice, you can get more shortArray = [9, 10];
complicated behaviors that create shallow clones of only part of an array, but for our purposes just calling slice() Version ≥ 3
will create a shallow copy of the entire array.
Provide the elements of shortArray as parameters to push using [Link]
All method used to convert array like objects to array are applicable to clone an array:
[Link](longArray, shortArray);
Version ≥ 6 Version ≥ 6
arrayToClone = [1, 2, 3, 4, 5];
clone1 = [Link](arrayToClone); Use the spread operator to pass the elements of shortArray as separate arguments to push
clone2 = [Link](...arrayToClone);
clone3 = [...arrayToClone] // the shortest way [Link](...shortArray)
Version ≤ 5.1
arrayToClone = [1, 2, 3, 4, 5]; The value of longArray is now:
clone1 = [Link](arrayToClone);
clone2 = [].[Link](arrayToClone);
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Section 12.12: Concatenating Arrays Note that if the second array is too long (>100,000 entries), you may get a stack overflow error (because of how
apply works). To be safe, you can iterate instead:
Two Arrays
[Link](function (elem) {
var array1 = [1, 2]; [Link](elem);
var array2 = [3, 4, 5]; });
Version ≥ 3
var array3 = [Link](array2); // returns a new array Array and non-array values
Version ≥ 6
var array3 = [...array1, ...array2] var array = ["a", "b"];
Version ≥ 3
[Link] – JavaScript® Notes for Professionals 95 [Link] – JavaScript® Notes for Professionals 96
var arr1 = ["a","b"]; If the mapping is not performed then:
var arr2 = ["e", "f"];
let arr = [..."123456"]; // ["1", "2", "3", "4", "5", "6"]
var arrConc = [Link]("c", "d", arr2);
The spread operator can also be used to spread arguments into a function:
Results in a new Array:
function myFunction(a, b, c) { }
["a", "b", "c", "d", "e", "f"] let args = [0, 1, 2];
var columns = ["Date", "Number", "Size", "Location", "Age"]; The rest operator does the opposite of the spread operator by coalescing several elements into a single one
var rows = ["2001", "5", "Big", "Sydney", "25"];
var result = [Link](function(result, field, index) {
[a, b, ...rest] = [1, 2, 3, 4, 5, 6]; // rest is assigned [3, 4, 5, 6]
result[columns[index]] = field;
return result;
}, {}) Collect arguments of a function:
{
Date: "2001",
Section 12.15: Filtering values
Number: "5",
The filter() method creates an array filled with all array elements that pass a test provided as a function.
Size: "Big",
Location: "Sydney",
Version ≥ 5.1
Age: "25"
} [1, 2, 3, 4, 5].filter(function(value, index, arr) {
return value > 2;
});
Section 12.14: Array spread / rest Version ≥ 6
[1, 2, 3, 4, 5].filter(value => value > 2);
Spread operator
Version ≥ 6
Results in a new array:
With ES6, you can use spreads to separate individual elements into a comma-separated syntax:
[3, 4, 5]
[Link] – JavaScript® Notes for Professionals 97 [Link] – JavaScript® Notes for Professionals 98
so the overall process will result ];
var index = [Link](item => [Link] === 3); // 2
[ {}, true, 5 ] var index = [Link](item => [Link] === 12); // -1
For example:
FindIndex
var array = [1, 2, 3];
The findIndex() method returns an index in the array, if an element in the array satisfies the provided testing [Link]();
function. Otherwise -1 is returned.
array results in:
array = [
{ value: 1 }, [1, 2]
{ value: 2 },
{ value: 3 },
Both methods return the removed item;
{ value: 4 },
{ value: 5 }
Splice
[Link] – JavaScript® Notes for Professionals 99 [Link] – JavaScript® Notes for Professionals 100
Use .splice() to remove a series of elements from an array. .splice() accepts two parameters, the starting Care must be taken as this does not remove any items from the original array. The array may have been closed
index, and an optional number of elements to delete. If the second parameter is left out .splice() will remove all over when passed to a function. The array will remain in memory for the life of the function though you may not be
elements from the starting index through the end of the array. aware of this. This is a common source of memory leaks.
For example: Example of a memory leak resulting from bad array clearing:
Method 3
[Link]
Similar to method 2 but returns a new array containing the removed items. If you do not need the items this
Assigning value to length of array changes the length to given value. If new value is less than array length items will method is inefficient as the new array is still created only to be immediately dereferenced.
be removed from the end of value.
[Link](0); // should not use if you don't want the removed items
array = [1, 2, 3, 4, 5]; // only use this method if you do the following
[Link] = 2; var keepArr = [Link](0); // empties the array and creates a new array containing the
[Link](array); // [1, 2] // removed items
Related question.
Section 12.19: Removing all elements
var arr = [1, 2, 3, 4]; Section 12.20: Finding the minimum or maximum element
Method 1 If your array or array-like object is numeric, that is, if all its elements are numbers, then you can use [Link]
or [Link] by passing null as the first argument, and your array as the second.
Creates a new array and overwrites the existing array reference with a new one.
[Link] – JavaScript® Notes for Professionals 101 [Link] – JavaScript® Notes for Professionals 102
[Link](null, myArray); // 4 var arr = [1, 2, 3, 4];
Version ≥ 6 var arr2 = new Array(1, 2, 3, 4);
In ES6 you can use the ... operator to spread an array and take the minimum or maximum element.
If the Array constructor is used with no arguments, an empty array is created.
var maxValue = myArray[0]; Note that if it's used with exactly one argument and that argument is a number, an array of that length with all
for(var i = 1; i < [Link]; i++) { undefined values will be created instead:
var currentValue = myArray[i];
if(currentValue > maxValue) { var arr4 = new Array(4);
maxValue = currentValue;
}
} results in:
Version ≥ 5.1
[undefined, undefined, undefined, undefined]
The following example uses [Link]() to find the minimum or maximum:
That does not apply if the single argument is non-numeric:
var myArray = [1, 2, 3, 4];
var arr5 = new Array("foo");
[Link](function(a, b) {
return [Link](a, b);
results in:
}); // 1
[Link](function(a, b) { ["foo"]
return [Link](a, b); Version ≥ 6
}); // 4
Version ≥ 6 Similar to an array literal, [Link] can be used to create a new Array instance given a number of arguments:
To generalize the reduce version we'd have to pass in an initial value to cover the empty list case:
In contrast to the Array constructor, creating an array with a single number such as [Link](23) will create a new
array [23], rather than an Array with length 23.
function myMax(array) {
return [Link](function(maxSoFar, element) {
return [Link](maxSoFar, element);
The other way to create and initialize an array would be [Link]
}, -Infinity);
} var newArray = [Link]({ length: 5 }, (_, index) => [Link](index, 4));
For the details on how to properly use reduce see Reducing values.
Section 12.22: Joining array elements in a string
Section 12.21: Standard array initialization To join all of an array's elements into a string, you can use the join method:
There are many ways to create arrays. The most common are to use array literals, or the Array constructor: [Link](["Hello", " ", "world"].join("")); // "Hello world"
[Link] – JavaScript® Notes for Professionals 103 [Link] – JavaScript® Notes for Professionals 104
[Link]([1, 800, 555, 1234].join("-")); // "1-800-555-1234" Or if you want to change the array itself without creating a copy (for example if you write a function that get an
array as a function and manipulates it) you can use this snippet:
As you can see in the second line, items that are not strings will be converted first.
while(index = [Link](3) !== -1) { [Link](index, 1); }
Section 12.23: Removing/Adding elements using splice()
And if you need to remove just the first value found, remove the while loop:
The splice()method can be used to remove elements from an array. In this example, we remove the first 3 from
the array. var index = [Link](to_remove);
if(index !== -1) { [Link](index , 1); }
var values = [1, 2, 3, 4, 5, 3];
var i = [Link](3);
if (i >= 0) {
Section 12.26: Flattening Arrays
[Link](i, 1);
} 2 Dimensional arrays
// [1, 2, 4, 5, 3] Version ≥ 6
0 "a" [Link](String(deeplyNested).split(',').map(Number);
1 "b" #=> [4,5,6,7,8,9]
2 "c"
Or
Note: This method is not supported in Internet Explorer.
const flatten = [Link]().split(',').map(Number)
Portions of this content from [Link] by Mozilla Contributors licensed under CC-by-SA 2.5 [Link](flatten);
#=> [4,5,6,7,8,9]
[Link] – JavaScript® Notes for Professionals 105 [Link] – JavaScript® Notes for Professionals 106
Section 12.27: Append / Prepend items to Array Section 12.29: Logical connective of values
Unshift Version ≥ 5.1
For example: While .some combines the return values with OR, .every combines them with AND.
[Link]([]) // true
Now array is
[Link]([1, 2, 3]) // true
[Link]({}) // false
[ [Link](1) // false
["key1", 10],
["key2", 3],
In most cases you can instanceof to check if an object is an Array.
["key3", 40],
["key4", 20]
] [] instanceof Array; // true
{} instanceof Array; // false
[Link] has the an advantage over using a instanceof check in that it will still return true even if the
prototype of the array has been changed and will return false if a non-arrays prototype was changed to the Array
[Link] – JavaScript® Notes for Professionals 107 [Link] – JavaScript® Notes for Professionals 108
prototype. Version ≥ 6
[Link]((a,b) => a[1] - b[1]);
var arr = [];
[Link](arr, null); This will output
[Link](arr); // true
arr instanceof Array; // false
[
["key2", 3],
[Link](index, 0, item);
Be aware that the sort method operates on the array in place. It changes the array. Most other array methods
return a new array, leaving the original one intact. This is especially important to note if you use a functional
More advanced variant with multiple arguments and chaining support:
programming style and expect functions to not have side-effects.
/* Syntax:
[Link](index, value1, value2, ..., valueN) */ Section 12.33: Test all array items for equality
[Link] = function(index) { The .every method tests if all array elements pass a provided predicate test.
[Link](this, [index, 0].concat(
[Link](arguments, 1))); To test all objects for equality, you can use the following code snippets.
return this;
};
[1, 2, 1].every(function(item, i, list) { return item === list[0]; }); // false
[1, 1, 1].every(function(item, i, list) { return item === list[0]; }); // true
["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(1, 6); // ["b", "X", "Y", "Z", "c"]
Version ≥ 6
[1, 1, 1].every((item, i, list) => item === list[0]); // true
And with array-type arguments merging and chaining support:
Section 12.32: Sorting multidimensional array Section 12.34: Copy part of an Array
The slice() method returns a copy of a portion of an array.
Given the following array
It takes two parameters, [Link]([begin[, end]]) :
var array = [
["key1", 10],
begin
["key2", 3],
["key3", 40],
Zero-based index which is the beginning of extraction.
["key4", 20]
];
end
[Link] – JavaScript® Notes for Professionals 109 [Link] – JavaScript® Notes for Professionals 110
// Let's say we have this Array of Alphabets
var arr = ["a", "b", "c", "d"...]; Chapter 13: Objects
// I want an Array of the first two Alphabets Property Description
var newArr = [Link](0, 2); // newArr === ["a", "b"] value The value to assign to the property.
Example 2 writable Whether the value of the property can be changed or not.
// Let's say we have this Array of Numbers enumerable Whether the property will be enumerated in for in loops or not.
// and I don't know it's end
configurable Whether it will be possible to redefine the property descriptor or not.
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9...];
get A function to be called that will return the value of the property.
// I want to slice this Array starting from set A function to be called when the property is assigned a value.
// number 5 to its end
var newArr = [Link](4); // newArr === [5, 6, 7, 8, 9...]
Section 13.1: Shallow cloning
Version ≥ 6
ES6's [Link]() function can be used to copy all of the enumerable properties from an existing Object
instance to a new one.
const existing = { a: 1, b: 2, c: 3 };
Object rest/spread destructuring which is currently a stage 3 proposal provides an even simpler way to create
shallow clones of Object instances:
const existing = { a: 1, b: 2, c: 3 };
If you need to support older versions of JavaScript, the most-compatible way to clone an Object is by manually
iterating over its properties and filtering out inherited ones using .hasOwnProperty().
var existing = { a: 1, b: 2, c: 3 };
[Link] makes an object immutable by preventing the addition of new properties, the removal of existing
properties, and the modification of the enumerability, configurability, and writability of existing properties. It also
prevents the value of existing properties from being changed. However, it does not work recursively which means
that child objects are not automatically frozen and are subject to change.
The operations following the freeze will fail silently unless the code is running in strict mode. If the code is in strict
[Link] – JavaScript® Notes for Professionals 111 [Link] – JavaScript® Notes for Professionals 112
mode, a TypeError will be thrown. function deepClone(obj) {
function clone(obj, traversedObjects) {
var obj = { var copy;
foo: 'foo', // primitive types
bar: [1, 2, 3], if(obj === null || typeof obj !== "object") {
baz: { return obj;
foo: 'nested-foo' }
}
}; // detect cycles
for(var i = 0; i < [Link]; i++) {
[Link](obj); if(traversedObjects[i] === obj) {
throw new Error("Cannot clone circular object.");
// Cannot add new properties }
[Link] = true; }
Assuming that you have a "nice" object whose properties only contain primitive values, dates, arrays, or other "nice" You should include the additional check for hasOwnProperty because an object may have properties that are
objects, then the following function can be used for making deep clones. It is a recursive function that can detect inherited from the object's base class. Not performing this check can raise errors.
objects with a cyclic structure and will throw an error in such cases.
Version ≥ 5
[Link] – JavaScript® Notes for Professionals 113 [Link] – JavaScript® Notes for Professionals 114
You can also use [Link] function which return an Array containing all properties of an object and then you Use it as reducer: (merges an array to an object)
can loop through this array with [Link] or [Link] function.
return [Link]((result, user) => [Link]({}, {[[Link]]: user})
var obj = { 0: 'a', 1: 'b', 2: 'c' };
[Link](obj).map(function(key) {
Section 13.6: Object rest/spread (...)
[Link](key);
Version > 7
});
// outputs: 0, 1, 2
Object spreading is just syntactic sugar for [Link]({}, obj1, ..., objn);
The [Link]() method is used to copy the values of all enumerable own properties from one or more source let obj = { a: 1 };
objects to a target object. It will return the target object.
let obj2 = { ...obj, b: 2, c: 3 };
Use it to assign values to an existing object:
[Link](obj2); // { a: 1, b: 2, c: 3 };
var user = {
firstName: "John" As [Link] it does shallow merging, not deep merging.
};
let obj3 = { ...obj, b: { c: 2 } };
[Link](user, {lastName: "Doe", age:39});
[Link](user); // Logs: {firstName: "John", lastName: "Doe", age: 39} [Link](obj3); // { a: 1, b: { c: 2 } };
[Link] – JavaScript® Notes for Professionals 115 [Link] – JavaScript® Notes for Professionals 116
[Link](obj, { alert(word + '\n\n' + definition)
property1: {
value: true,
Note how we are using [] bracket notation to look at the variable named word; if we were to use the traditional .
writable: true
},
notation, then it would take the value literally, hence:
property2: {
value: 'Hello', [Link]([Link]) // doesn't work because word is taken literally and dictionary has no
writable: false field named `word`
} [Link]([Link]) // it works! because apple is taken literally
});
[Link](dictionary[word]) // it works! because word is a variable, and the user perfectly typed
in one of the words from our dictionary when prompted
Section 13.8: Accesor properties (get and set) [Link](dictionary[apple]) // error! apple is not defined (as a variable)
Version ≥ 5
You could also write literal values with [] notation by replacing the variable word with a string 'apple'. See
Treat a property as a combination of two functions, one to get the value from it, and another one to set the value in [Properties with special characters or reserved words] example.
it.
You can also set dynamic properties with the bracket syntax:
The get property of the property descriptor is a function that will be called to retrieve the value from the property. var property="test";
var obj={
The set property is also a function, it will be called when the property has been assigned a value, and the new value [property]=1;
};
will be passed as an argument.
[Link]([Link]);//1
You cannot assign a value or writable to a descriptor that has get or set
}
[[Link], [Link]] = [Link](" ");
Section 13.10: Arrays are Objects
});
[Link]([Link]); // -> "John Doe" Disclaimer: Creating array-like objects is not recommend. However, it is helpful to understand how they
work, especially when working with DOM. This will explain why regular array operations don't work on
[Link] = "Hill"; DOM objects returned from many DOM document functions. (i.e. querySelectorAll, [Link])
[Link]([Link]); // -> "John Hill"
[Link] = "Mary Jones"; Supposing we created the following object which has some properties you would expect to see in an Array.
[Link]([Link]) // -> "Mary"
var anObject = {
Section 13.9: Dynamic / variable property names foo: 'bar',
length: 'interesting',
'0': 'zero!',
Sometimes the property name needs to be stored into a variable. In this example, we ask the user what word needs
'1': 'one!'
to be looked up, and then provide the result from an object I've named dictionary. };
[Link] – JavaScript® Notes for Professionals 117 [Link] – JavaScript® Notes for Professionals 118
[Link]([Link], [Link]); // outputs: undefined bar writable: false
}); // TypeError
Since anArray is actually an object, just like anObject, we can even add custom wordy properties to anArray
[Link] = 'newFoo';
[Link]; // 'foo';
Disclaimer: Arrays with custom properties are not usually recommended as they can be confusing, but it
can be useful in advanced cases where you need the optimized functions of an Array. (i.e. jQuery objects) In strict mode these operations will throw a TypeError
(function () {
[Link] = 'it works!'; 'use strict';
[Link]([Link]);
var obj = { foo: 'foo' };
Note that anObject is only an array-like object. (also known as a List) It is not a true Array. This is important,
Section 13.12: Convert object's values to array
because functions like push and forEach (or any convenience function found in [Link]) will not work by Given this object:
default on array-like objects.
var obj = {
Many of the DOM document functions will return a List (i.e. querySelectorAll, [Link]) which is similar to a: "hello",
the array-like anObject we created above. See Converting Array-like Objects to Arrays b: "this is",
c: "javascript!",
[Link](typeof anArray == 'object', typeof anObject == 'object'); // outputs: true true };
[Link](anArray instanceof Object, anObject instanceof Object); // outputs: true true
[Link](anArray instanceof Array, anObject instanceof Array); // outputs: true false You can convert its values to an array by doing:
[Link]([Link](anArray), [Link](anObject)); // outputs: true false
var array = [Link](obj)
Section 13.11: [Link] .map(function(key) {
return obj[key];
Version ≥ 5 });
[Link] prevents the addition or removal of properties from an object. Once an object has been sealed its [Link](array); // ["hello", "this is", "javascript!"]
property descriptors can't be converted to another type. Unlike [Link] it does allow properties to be
edited. Section 13.13: Retrieving properties from an object
Attempts to do this operations on a sealed object will fail silently Characteristics of properties :
var obj = { foo: 'foo', bar: function () { return 'bar'; } }; Properties that can be retrieved from an object could have the following characteristics,
[Link](obj) Enumerable
Non - Enumerable
[Link] = 'newFoo';
own
[Link] = function () { return 'foo' };
[Link]; // undefined While creating the properties using [Link]fineProperty(ies), we could set its characteristics except "own".
[Link](); // 'foo' Properties which are available in the direct level not in the prototype level (__proto__) of an object are called as own
properties.
// Can't make foo an accessor property
[Link](obj, 'foo', { And the properties that are added into an object without using [Link](ies) will don't have its
get: function () { return 'newFoo'; }
enumerable characteristic. That means it be considered as true.
}); // TypeError
[Link] – JavaScript® Notes for Professionals 119 [Link] – JavaScript® Notes for Professionals 120
availability when retrieving it from its object, by using different programmatical methods. Those different methods [Link](props); //["a"]
will be discussed deeply below.
//Ex 3 : Data with non enumerable properties
var x = { a : 10 } , props;
Methods of retrieving properties :
[Link](x, "b", {value : 5, enumerable : false});
Properties from an object could be retrieved by the following methods, props = [Link](x);
This loop is very useful in retrieving enumerable properties from an object. Additionally this loop will retrieve 3. [Link]() function
enumerable own properties as well as it will do the same retrieval by traversing through the prototype chain
until it sees the prototype as null.
This function will retrieve both enumerable and non enumerable, own properties from an object. It was also
released as a part of ECMAScript 5.
//Ex 1 : Simple data
var x = { a : 10 , b : 3} , props = [];
//Ex 1 : Simple data
for(prop in x){ var x = { a : 10 , b : 3} , props;
[Link](prop);
} props = [Link](x);
//Ex 2 : Data with enumerable properties in prototype chain //Ex 2 : Data with enumerable properties in prototype chain
var x = { a : 10 , __proto__ : { b : 10 }} , props = []; var x = { a : 10 , __proto__ : { b : 10 }} , props;
props = [Link](x);
[Link] – JavaScript® Notes for Professionals 121 [Link] – JavaScript® Notes for Professionals 122
Section 13.14: Read-Only property var obj = {};
var a = { };
This error will be thrown:
[Link](a, 'foo', { value: 'original', writable: false });
[Link]([Link]);
And the property will still be read only.
Console output
[Link] = "new value";
[Link](foo);
original
Console output
We can avoid a property from showing up in for (... in ...) loops Section 13.17: [Link]
Get the description of a specific property in an object.
The enumerable property of the property descriptor tells whether that property will be enumerated while looping
through the object's properties. var sampleObject = {
hello: 'world'
var obj = { }; };
[Link] – JavaScript® Notes for Professionals 123 [Link] – JavaScript® Notes for Professionals 124
//*actually whether an assignment would take place in the case of a data property var obj = {propertyName1: 1}; //the pair is actually ('propertyName1', {value:1,
//also depends on the presence and value of the writable field - on that later on // writable:true,
// enumerable:true,
The property's type is determined by its descriptor's fields, and a property cannot be of both types. // configurable:true})
[Link](obj, 'propertyName2', {get: function() {
Data descriptors - [Link]('this will be logged ' +
'every time propertyName2 is accessed to get its value');
},
Required fields: value or writable or both
set: function() {
Optional fields:configurable,enumerable [Link]('and this will be logged ' +
'every time propertyName2\'s value is tried to be set')
Sample: //will be treated like it has enumerable:false, configurable:false
}});
{ //propertyName1 is the name of obj's data property
value: 10, //and propertyName2 is the name of its accessor property
writable: true;
}
Accessor descriptors -
obj.propertyName1 = 3;
Required fields: get or set or both
[Link](obj.propertyName1); //3
Optional fields: configurable, enumerable
obj.propertyName2 = 3; //and this will be logged every time propertyName2's value is tried to be set
Sample: [Link](obj.propertyName2); //this will be logged every time propertyName2 is accessed to get
its value
{
get: function () {
return 10; Section 13.19: [Link]
},
Version ≥ 5
enumerable: true
}
[Link](obj) returns an array of a given object's keys.
[Link] – JavaScript® Notes for Professionals 125 [Link] – JavaScript® Notes for Professionals 126
myObject[123] = 'hi!' // number 123 is automatically converted to a string regardless.
[Link](myObject['123']) // notice how using string 123 produced the same result
[Link](myObject['12' + '3']) // string concatenation const obj = {
[Link](myObject[120 + 3]) // arithmetic, still resulting in 123 and producing the same result one: 1,
[Link](myObject[123.0]) // this works too because 123.0 evaluates to 123 two: 2,
[Link](myObject['123.0']) // this does NOT work, because '123' != '123.0' three: 3
};
However, leading zeros are not recommended as that is interpreted as Octal notation. (TODO, we should produce
[Link](obj);
and link to an example describing octal, hexadecimal and exponent notation)
Console output
One
The proposed [Link]() method returns an array of key/value pairs for the given object. It does not return
an iterator like [Link](), but the Array returned by [Link]() can be iterated
[Link] – JavaScript® Notes for Professionals 127 [Link] – JavaScript® Notes for Professionals 128
Chapter 14: Arithmetic (Math) x % 2 != 0 // true if x is odd number
[Link]( 42 % 10); // 2
[Link]( 42 % -10); // 2 Section 14.3: Rounding
[Link](-42 % 10); // -2
[Link](-42 % -10); // -2 Rounding
[Link](-40 % 10); // -0
[Link]( 40 % 10); // 0 [Link]() will round the value to the closest integer using half round up to break ties.
This operator returns the remainder left over when one operand is divided by a second operand. When the first var a = [Link](2.3); // a is now 2
operand is a negative value, the return value will always be negative, and vice versa for positive values. var b = [Link](2.7); // b is now 3
var c = [Link](2.5); // c is now 3
In the example above, 10 can be subtracted four times from 42 before there is not enough left to subtract again
without it changing sign. The remainder is thus: 42 - 4 * 10 = 2. But
The remainder operator may be useful for the following problems: var c = [Link](-2.7); // c is now -3
var c = [Link](-2.5); // c is now -2
1. Test if an integer is (not) divisible by another number:
Note how -2.5 is rounded to -2. This is because half-way values are always rounded up, that is they're rounded to
x % 4 == 0 // true if x is divisible by 4 the integer with the next higher value.
x % 2 == 0 // true if x is even number
[Link] – JavaScript® Notes for Professionals 129 [Link] – JavaScript® Notes for Professionals 130
Rounding up var b = [Link] (myNum * multiplier) / multiplier; // 3400
var c = [Link](myNum * multiplier) / multiplier; // 3300
[Link]() will round the value up.
As a more usable function:
var a = [Link](2.3); // a is now 3
var b = [Link](2.7); // b is now 3 // value is the value to round
// places if positive the number of decimal places to round to
ceiling a negative number will round towards zero // places if negative the number of digits to round to
function roundTo(value, places){
var power = [Link](10, places);
var c = [Link](-1.1); // c is now 1
return [Link](value * power) / power;
}
Rounding down var myNum = 10000/3; // 3333.3333333333335
roundTo(myNum, 2); // 3333.33
roundTo(myNum, 0); // 3333
[Link]() will round the value down.
roundTo(myNum, -2); // 3300
[Link](2.3); // 2 (floor)
[Link](-2.3); // -2 (ceil) This will return the sine of r, a value between -1 and 1.
[Link](2147483648.1); // 2147483648 (floor)
[Link](-2147483649.1); // -2147483649 (ceil) [Link](r);
[Link](NaN); // NaN
This will return the arcsine (the reverse of the sine) of r.
Rounding to decimal places
[Link](r)
[Link], [Link](), and [Link]() can be used to round to a number of decimal places
This will return the hyperbolic arcsine of r.
To round to 2 decimal places:
Cosine
var myNum = 2/3; // 0.6666666666666666 [Link](r);
var multiplier = 100;
var a = [Link](myNum * multiplier) / multiplier; // 0.67
var b = [Link] (myNum * multiplier) / multiplier; // 0.67 This will return the cosine of r, a value between -1 and 1
var c = [Link](myNum * multiplier) / multiplier; // 0.66
[Link](r);
[Link] – JavaScript® Notes for Professionals 131 [Link] – JavaScript® Notes for Professionals 132
This will return the hyperbolic arccosine of r. Shift left is equivalent to integer multiply by [Link](2, n). When doing integer math, shift can significantly
improve the speed of some math operations.
Tangent
[Link](r); var n = 2;
var a = 5.4;
var result = (a << n) === [Link](a) * [Link](2,n);
This will return the tangent of r.
// result is true
a = 5.4 << n; // 20
[Link](r);
Bitwise right shift >> (Sign-propagating shift) >>> (Zero-fill right shift)
This will return the arctangent (the reverse of the tangent) of r. Note that it will return an angle in radians between a = 0b1001 >> 1; // a === 0b0100
a = 0b1001 >> 2; // a === 0b0010
-π/2 and π/2.
a = 0b1001 >> 3; // a === 0b0001
Math.atan2(x, y); A negative 32bit value always has the left most bit on:
This will return the value of an angle from (0, 0) to (x, y) in radians. It will return a value between -π and π, not a = 0b11111111111111111111111111110111 | 0;
including π. [Link](a); // -9
b = a >> 2; // leftmost bit is shifted 1 to the right then new left most bit is set to on (1)
[Link](b); // -3
Section 14.5: Bitwise operators b = a >>> 2; // leftmost bit is shifted 1 to the right. the new left most bit is set to off (0)
[Link](b); // 2147483643
Note that all bitwise operations operate on 32-bit integers by passing any operands to the internal function ToInt32.
The result of a >>> operation is always positive.
Bitwise or
The result of a >> is always the same sign as the shifted value.
var a;
a = 0b0011 | 0b1010; // a === 0b1011 Right shift on positive numbers is the equivalent of dividing by the [Link](2,n) and flooring the result:
// truth table
// 1010 | (or)
a = 256.67;
// 0011
n = 4;
// 1011 (result)
result = (a >> n) === [Link]( [Link](a) / [Link](2,n) );
Bitwise and // result is true
a = a >> n; // 16
a = 0b0011 & 0b1010; // a === 0b0010
// truth table
result = (a >>> n) === [Link]( [Link](a) / [Link](2,n) );
// 1010 & (and)
// result is true
// 0011
a = a >>> n; // 16
// 0010 (result)
Bitwise not
Right shift zero fill (>>>) on negative numbers is different. As JavaScript does not convert to unsigned ints when
a = ~0b0011; // a === 0b1100 doing bit operations there is no operational equivalent:
// truth table
// 10 ~(not)
a = -256.67;
// 01 (result)
result = (a >>> n) === [Link]( [Link](a) / [Link](2,n) );
Bitwise xor (exclusive or) // result is false
a = 0b1010 ^ 0b0011; // a === 0b1001 Bitwise assignment operators
// truth table
// 1010 ^ (xor) With the exception of not (~) all the above bitwise operators can be used as assignment operators:
// 0011
// 1001 (result)
a |= b; // same as: a = a | b;
Bitwise left shift a ^= b; // same as: a = a ^ b;
a = 0b0001 << 1; // a === 0b0010 a &= b; // same as: a = a & b;
a = 0b0001 << 2; // a === 0b0100 a >>= b; // same as: a = a >> b;
a = 0b0001 << 3; // a === 0b1000 a >>>= b; // same as: a = a >>> b;
a <<= b; // same as: a = a << b;
[Link] – JavaScript® Notes for Professionals 133 [Link] – JavaScript® Notes for Professionals 134
Warning: JavaScript uses Big Endian to store integers. This will not always match the Endian of the device/OS. When c = a ** b;
using typed arrays with bit lengths greater than 8 bits you should check if the environment is Little Endian or Big
Endian before applying bitwise operations. c will now be 8
Warning: Bitwise operators such as & and | are not the same as the logical operators && (and) and || (or). They will
provide incorrect results if used as logical operators. The ^ operator is not the power operator (ab). Use [Link] to find the nth root of a number.
Finding the nth roots is the inverse of raising to the nth power. For example 2 to the power of 5 is 32. The 5th root
Section 14.6: Incrementing (++) of 32 is 2.
The increment and decrement operators are commonly used in for loops, for example: To use [Link]() to get a number from an arbitrary range (not [0,1)) use this function to get a random
number between min (inclusive) and max (exclusive): interval of [min, max)
for(var i = 0; i < 42; ++i)
{ function getRandomArbitrary(min, max) {
// do something awesome! return [Link]() * (max - min) + min;
} }
Notice how the prefix variant is used. This ensures that a temporarily variable isn't needlessly created (to return the To use [Link]() to get an integer from an arbitrary range (not [0,1)) use this function to get a random
value prior to the operation). number between min (inclusive) and max (exclusive): interval of [min, max)
var a = 2, To use [Link]() to get an integer from an arbitrary range (not [0,1)) use this function to get a random
b = 3, number between min (inclusive) and max (inclusive): interval of [min, max]
c = [Link](a, b);
function getRandomIntInclusive(min, max) {
c will now be 8 return [Link]([Link]() * (max - min + 1)) + min;
}
Version > 6
let a = 2,
b = 3,
[Link] – JavaScript® Notes for Professionals 135 [Link] – JavaScript® Notes for Professionals 136
Section 14.9: Addition (+) var data = new Uint32Array(buf);
data[0] = 0x0F000000;
if(buf8[0] === 0x0f){
The addition operator (+) adds numbers.
isLittleEndian = false;
}
})();
var a = 9,
b = 3, Little-Endian stores most significant bytes from right to left.
c = a + b;
Big-Endian stores most significant bytes from left to right.
c will now be 12
var myNum = 0x11223344 | 0; // 32 bit signed integer
This operand can also be used multiple times in a single assignment: var buf = new ArrayBuffer(4);
var data8 = new Uint8ClampedArray(buf);
var a = 9, var data32 = new Uint32Array(buf);
b = 3, data32[0] = myNum; // store number in 32Bit array
c = 8,
d = a + b + c; If the system uses Little-Endian, then the 8bit byte values will be
null + null; // 0 If the system uses Big-Endian, then the 8bit byte values will be
null + undefined; // NaN
null + {}; // "null[object Object]" [Link](data8[0].toString(16)); // 0x11
null + ''; // "null" [Link](data8[1].toString(16)); // 0x22
[Link](data8[2].toString(16)); // 0x33
If the operands are a string and a number, the number is converted to a string and then they're concatenated, [Link](data8[3].toString(16)); // 0x44
which may lead to unexpected results when working with strings that look numeric.
Example where Endian type is important
"123" + 1; // "1231" (not 124)
var canvas = [Link]("canvas");
var ctx = [Link]("2d");
If a boolean value is given in place of any of the number values, the boolean value is converted to a number (0 for
var imgData = [Link](0, 0, [Link], [Link]);
false, 1 for true) before the sum is calculated:
// To speed up read and write from the image buffer you can create a buffer view that is
// 32 bits allowing you to read/write a pixel in a single operation
true + 1; // 2 var buf32 = new Uint32Array([Link]);
false + 5; // 5 // Mask out Red and Blue channels
null + 1; // 1 var mask = 0x00FF00FF; // bigEndian pixel channels Red,Green,Blue,Alpha
undefined + 1; // NaN if(isLittleEndian){
mask = 0xFF00FF00; // littleEndian pixel channels Alpha,Blue,Green,Red
If a boolean value is given alongside a string value, the boolean value is converted to a string instead: }
var len = [Link];
var i = 0;
true + "1"; // "true1"
while(i < len){ // Mask all pixels
false + "bar"; // "falsebar"
buf32[i] &= mask; //Mask out Red and Blue
}
Section 14.10: Little / Big endian for typed arrays when using [Link](imgData);
bitwise operators
Section 14.11: Get Random Between Two Numbers
To detect the endian of the device
Returns a random integer between min and max:
var isLittleEndian = true;
(()=>{ function randomBetween(min, max) {
var buf = new ArrayBuffer(4); return [Link]([Link]() * (max - min + 1) + min);
var buf8 = new Uint8ClampedArray(buf); }
[Link] – JavaScript® Notes for Professionals 137 [Link] – JavaScript® Notes for Professionals 138
Examples: As you probably noticed, these functions return an index, so you could have more descriptive outcomes stored in
an array. Here's an example.
// randomBetween(0, 10);
[Link]([Link]() * 11); var rewards = ["gold coin","silver coin","diamond","god sword"];
var likelihoods = [5,9,1,0];
// randomBetween(1, 10); // least likely to get a god sword (0/15 = 0%, never),
[Link]([Link]() * 10) + 1; // most likely to get a silver coin (9/15 = 60%, more than half the time)
// randomBetween(-10, -2);
[Link]([Link]() * 9) - 10; Section 14.13: Subtraction (-)
The subtraction operator (-) subtracts numbers.
Section 14.12: Simulating events with dierent probabilities
Sometimes you may only need to simulate an event with two outcomes, maybe with different probabilities, but you
var a = 9;
may find yourself in a situation that calls for many possible outcomes with different probabilities. Let's imagine you
var b = 3;
want to simulate an event that has six equally probable outcomes. This is quite simple. var c = a - b;
function simulateEvent(numEvents) {
c will now be 6
var event = [Link](numEvents*[Link]());
return event;
If a string or boolean is provided in place of a number value, it gets converted to a number before the difference is
}
calculated (0 for false, 1 for true):
// simulate fair die
[Link]("Rolled a "+(simulateEvent(6)+1)); // Rolled a 2 "5" - 1; // 4
7 - "3"; // 4
"5" - true; // 4
However, you may not want equally probable outcomes. Say you had a list of three outcomes represented as an
array of probabilities in percents or multiples of likelihood. Such an example might be a weighted die. You could
If the string value cannot be converted into a Number, the result will be NaN:
rewrite the previous function to simulate such an event.
"foo" - 1; // NaN
function simulateEvent(chances) {
100 - "bar"; // NaN
var sum = 0;
[Link](function(chance) {
});
sum+=chance;
Section 14.14: Multiplication (*)
var rand = [Link]();
The multiplication operator (*) perform arithmetic multiplication on numbers (literals or variables).
var chance = 0;
for(var i=0; i<[Link]; i++) {
chance+=chances[i]/sum; [Link]( 3 * 5); // 15
if(rand<chance) { [Link](-3 * 5); // -15
return i; [Link]( 3 * -5); // -15
} [Link](-3 * -5); // 15
}
// should never be reached unless sum of probabilities is less than 1 Section 14.15: Getting maximum and minimum
// due to all being zero or some being negative probabilities
return -1; The [Link]() function returns the largest of zero or more numbers.
}
[Link](4, 12); // 12
// simulate weighted dice where 6 is twice as likely as any other face [Link](-1, -15); // -1
// using multiples of likelihood
[Link]("Rolled a "+(simulateEvent([1,1,1,1,1,2])+1)); // Rolled a 1
The [Link]() function returns the smallest of zero or more numbers.
// using probabilities
[Link]("Rolled a "+(simulateEvent([1/7,1/7,1/7,1/7,1/7,2/7])+1)); // Rolled a 6 [Link](4, 12); // 4
[Link](-1, -15); // -15
[Link] – JavaScript® Notes for Professionals 139 [Link] – JavaScript® Notes for Professionals 140
Getting maximum and minimum from an array: [Link](n);
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9],
max = [Link](Math, arr), Example:
min = [Link](Math, arr);
[Link]([Link](0.60)); // 0
[Link](max); // Logs: 9
[Link]([Link](0.40)); // 0
[Link](min); // Logs: 1
[Link]([Link](5.1)); // 5
[Link]([Link](-5.1)); // -6
ECMAScript 6 spread operator, getting the maximum and minimum of an array: [Link]([Link](-5.9)); // -6
If you need to clamp a number to keep it inside a specific range boundary Cube Root
function clamp(min, max, val) { To find the cube root of a number, use the [Link]() function
return [Link]([Link](min, +val), max);
} Version ≥ 6
[Link](27) #=> 3
[Link](clamp(-10, 10, "4.30")); // 4.3
Finding nth-roots
[Link](clamp(-10, 10, -8)); // -8
[Link](clamp(-10, 10, 12)); // 10
To find the nth-root, use the [Link]() function and pass in a fractional exponent.
[Link](clamp(-10, 10, -15)); // -10
Section 14.17: Ceiling and Floor Section 14.19: Random with gaussian distribution
ceil() The [Link]() function should give random numbers that have a standard deviation approaching 0. When
picking from a deck of card, or simulating a dice roll this is what we want.
The ceil() method rounds a number upwards to the nearest integer, and returns the result.
But in most situations this is unrealistic. In the real world the randomness tends to gather around an common
Syntax: normal value. If plotted on a graph you get the classical bell curve or gaussian distribution.
[Link] – JavaScript® Notes for Professionals 141 [Link] – JavaScript® Notes for Professionals 142
} vec.y = [Link](dir) * dist; // get the y component
return r / v;
}
You can also ignore the distance to create a normalised (1 unit long) vector in the direction of dir
If your coordinate system has y as up then you need to switch cos and sin. In this case a positive direction is in a
counterclockwise direction from the x axis.
The image shows the distribution of random values for different values of v. The top left is standard single // get the directional vector where y points up
var dir = 1.4536; // direction in radians
[Link]() call the bottom right is [Link]() summed 8 times. This is from 5,000,000 samples using
var vec = {};
Chrome vec.x = [Link](dir); // get the x component
vec.y = [Link](dir); // get the y component
This method is most efficient at v<5
[Link] – JavaScript® Notes for Professionals 143 [Link] – JavaScript® Notes for Professionals 144
Section 14.23: Periodic functions using [Link] t += phase * [Link] * 2; // add the phase offset
var v = [Link](t); // get the value at the calculated position in the cycle
v *= amplitude; // set the amplitude
[Link] and [Link] are cyclic with a period of 2*PI radians (360 deg) they output a wave with an amplitude of 2
v += offset; // add the offset
in the range -1 to 1. return v;
}
Graph of sine and cosine function: (courtesy Wikipedia)
Or in a more compact (and slightly quicker form):
[Link](15 / 3); // 5
[Link](15 / 4); // 3.75
If used as a postfix to n, the operator returns the current n and then assigns the decremented the value.
If used as a prefix to n, the operator assigns the decremented n and then returns the changed value.
They are both very handy for many types of periodic calculations, from creating sound waves, to animations, and
even encoding and decoding image data var a = 5, // 5
b = a--, // 5
This example shows how to create a simple sin wave with control over period/frequency, phase, amplitude, and c = a // 4
offset.
In this case, b is set to the initial value of a. So, b will be 5, and c will be 4.
The unit of time being used is seconds.
The most simple form with control over frequency only. var a = 5, // 5
b = --a, // 4
c = a // 4
// time is the time in seconds when you want to get a sample
// Frequency represents the number of oscillations per second
function oscillator(time, frequency){ In this case, b is set to the new value of a. So, b will be 4, and c will be 4.
return [Link](time * 2 * [Link] * frequency);
} Common Uses
In almost all cases you will want to make some changes to the value returned. The common terms for modifications The decrement and increment operators are commonly used in for loops, for example:
Phase: The offset in terms of frequency from the start of the oscillations. It is a value in the range of 0 to 1 for (var i = 42; i > 0; --i) {
where the value 0.5 move the wave forward in time by half its frequency. A value of 0 or 1 makes no change. [Link](i)
}
Amplitude: The distance from the lowest value and highest value during one cycle. An amplitude of 1 has a
range of 2. The lowest point (trough) -1 to the highest (peak) 1. For a wave with frequency 1 the peak is at
Notice how the prefix variant is used. This ensures that a temporarily variable isn't needlessly created (to return the
0.25 seconds, and trough at 0.75.
value prior to the operation).
Offset: moves the whole wave up or down.
To include all these in the function: Note: Neither -- nor ++ are like normal mathematical operators, but rather they are very concise
operators for assignment. Notwithstanding the return value, both
function oscillator(time, frequency = 1, amplitude = 1, phase = 0, offset = 0){
var t = time * frequency * [Link] * 2; // get phase at time
[Link] – JavaScript® Notes for Professionals 145 [Link] – JavaScript® Notes for Professionals 146
x--
and
Chapter 15: Bitwise operators
--x Section 15.1: Bitwise operators
reassign to x such that x = x - 1. Bitwise operators perform operations on bit values of data. These operators convert operands to signed 32-bit
integers in two's complement.
const x = 1;
[Link](x--) // TypeError: Assignment to constant variable.
Conversion to 32-bit integers
[Link](--x) // TypeError: Assignment to constant variable.
[Link](--3) // ReferenceError: Invalid left-hand size expression in prefix operation.
Numbers with more than 32 bits discard their most significant bits. For example, the following integer with more
[Link](3--) // ReferenceError: Invalid left-hand side expression in postfix operation.
than 32 bits is converted to a 32-bit integer:
Before: 10100110111110100000000010000011110001000001
After: 10100000000010000011110001000001
Two's Complement
In normal binary we find the binary value by adding the 1's based on their position as powers of 2 - The rightmost
bit being 2^0 to the leftmost bit being 2^n-1 where n is the number of bits. For example, using 4 bits:
// Normal Binary
// 8 4 2 1
0 1 1 0 => 0 + 4 + 2 + 0 => 6
Two complement's format means that the number's negative counterpart (6 vs -6) is all the bits for a number
inverted, plus one. The inverted bits of 6 would be:
// Normal binary
0 1 1 0
// One's complement (all bits inverted)
1 0 0 1 => -8 + 0 + 0 + 1 => -7
// Two's complement (add 1 to one's complement)
1 0 1 0 => -8 + 0 + 2 + 0 => -6
Note: Adding more 1's to the left of a binary number does not change its value in two's compliment. The value 1010
and 1111111111010 are both -6.
Bitwise AND
The bitwise AND operation a & b returns the binary value with a 1 where both binary operands have 1's in a
specific position, and 0 in all other positions. For example:
13 & 7 => 5
// 13: 0..01101
// 7: 0..00111
//-----------------
// 5: 0..00101 (0 + 0 + 4 + 0 + 1)
Instead of this "masterpiece" (unfortunately too often seen in many real code parts):
function isEven(n) {
return n % 2 == 0;
}
[Link] – JavaScript® Notes for Professionals 147 [Link] – JavaScript® Notes for Professionals 148
function isOdd(n) {
if (isEven(n)) {
Section 15.2: Shift Operators
return false;
Bitwise shifting can be thought as "moving" the bits either left or right, and hence changing the value of the data
} else {
return true; operated on.
}
} Left Shift
You can check the (integer) number's parity in much more effective and simple manner: The left shift operator (value) << (shift amount) will shift the bits to the left by (shift amount) bits; the new
bits coming in from the right will be 0's:
if(n & 1) {
[Link]("ODD!"); 5 << 2 => 20
} else { // 5: 0..000101
[Link]("EVEN!"); // 20: 0..010100 <= adds two 0's to the right
}
The bitwise NOT operation ~a flips the bits of the given value a. This means all the 1's will become 0's and all the 0's
will become 1's. Right Shift (Zero fill)
The zero-fill right shift operator (value) >>> (shift amount) will move the bits to the right, and the new bits will
~13 => -14
be 0's. The 0's are shifted in from the left, and excess bits to the right are shifted off and discarded. This means it
// 13: 0..01101
//----------------- can make negative numbers into positive ones.
//-14: 1..10010 (-16 + 0 + 0 + 2 + 0)
-30 >>> 2 => 1073741816
// -30: 111..1100010
Bitwise XOR //1073741816: 001..1111000
The bitwise XOR (exclusive or) operation a ^ b places a 1 only if the two bits are different. Exclusive or means either Zero-fill right shift and sign-propagating right shift yield the same result for non negative numbers.
one or the other, but not both.
13 ^ 7 => 10
// 13: 0..01101
// 7: 0..00111
//-----------------
// 10: 0..01010 (0 + 8 + 0 + 2 + 0)
Real world example: swapping two integer values without additional memory allocation
[Link] – JavaScript® Notes for Professionals 149 [Link] – JavaScript® Notes for Professionals 150
Chapter 16: Constructor functions Chapter 17: Declarations and Assignments
Section 16.1: Declaring a constructor function Section 17.1: Modifying constants
Constructor functions are functions designed to construct a new object. Within a constructor function, the keyword Declaring a variable const only prevents its value from being replaced by a new value. const does not put any
this refers to a newly created object which values can be assigned to. Constructor functions "return" this new restrictions on the internal state of an object. The following example shows that a value of a property of a const
object automatically. object can be changed, and even new properties can be added, because the object that is assigned to person is
modified, but not replaced.
function Cat(name) {
[Link] = name; const person = {
[Link] = "Meow"; name: "John"
} };
[Link]('The name of the person is', [Link]);
Constructor functions are invoked using the new keyword:
[Link] = "Steve";
[Link]('The name of the person is', [Link]);
let cat = new Cat("Tom");
[Link]; // Returns "Meow"
[Link] = "Fox";
[Link]('The name of the person is', [Link], 'and the surname is', [Link]);
Constructor functions also have a prototype property which points to an object whose properties are automatically
inherited by all objects created with that constructor: Result:
[Link] = function() {
The name of the person is John
[Link]([Link]);
The name of the person is Steve
}
The name of the person is Steve and the surname is Fox
Important
You must declare and initialize a constant in the same statement.
[Link] – JavaScript® Notes for Professionals 151 [Link] – JavaScript® Notes for Professionals 152
let b = 'foo'; // Block-scope b += a;
const c = 'foo'; // Block-scope & immutable reference
b will now be 12
Keep in mind that you can't declare constants without initializing them at the same time.
This is functionally the same as
const foo; // "Uncaught SyntaxError: Missing initializer in const declaration"
b = b + a;
(An example of keyword-less variable declaration is not included above for technical reasons. Continue reading to
see an example.) Decrement by
var a = 9,
Section 17.4: Undefined b = 3;
b -= a;
Declared variable without a value will have the value undefined
b will now be 6
var a;
This is functionally the same as
[Link](a); // logs: undefined
b = b - a;
Trying to retrieve the value of undeclared variables results in a ReferenceError. However, both the type of
undeclared and unitialized variables is "undefined":
Multiply by
var a = 5,
var a;
b = 3;
[Link](typeof a === "undefined"); // logs: true
b *= a;
[Link](typeof variableDoesNotExist === "undefined"); // logs: true
b will now be 15
Section 17.5: Data Types
This is functionally the same as
JavaScript variables can hold many data types: numbers, strings, arrays, objects and more:
b = b * a;
// Number
var length = 16;
Divide by
// String var a = 3,
var message = "Hello, World!"; b = 15;
b /= a;
// Array
var carNames = ['Chevrolet', 'Nissan', 'BMW'];
b will now be 5
// Object
var person = { This is functionally the same as
firstName: "John",
lastName: "Doe" b = b / a;
};
Version ≥ 7
JavaScript has dynamic types. This means that the same variable can be used as different types: Raised to the power of
var a = 3,
var a; // a is undefined b = 15;
var a = 5; // a is a Number b **= a;
var a = "John"; // a is a String
[Link] – JavaScript® Notes for Professionals 153 [Link] – JavaScript® Notes for Professionals 154
Section 17.7: Assignment Chapter 18: Loops
To assign a value to a previously declared variable, use the assignment operator, =:
Section 18.1: Standard "for" loops
a = 6;
b = "Foo"; Standard usage
for (var i = 0; i < 100; i++) {
As an alternative to independent declaration and assignment, it is possible to perform both steps in one statement: [Link](i);
}
var a = 6;
let b = "Foo"; Expected output:
It is in this syntax that global variables may be declared without a keyword; if one were to declare a bare variable
0
without an assignment immediately afterword, the interpreter would not be able to differentiate global
declarations a; from references to variables a;. 1
...
c = 5; 99
c = "Now the value is a String.";
myNewGlobal; // ReferenceError
Multiple declarations
Note, however, that the above syntax is generally discouraged and is not strict-mode compliant. This is to avoid the
Commonly used to cache the length of an array.
scenario in which a programmer inadvertently drops a let or var keyword from their statement, accidentally
creating a variable in the global namespace without realizing it. This can pollute the global namespace and conflict
var array = ['a', 'b', 'c'];
with libraries and the proper functioning of a script. Therefore global variables should be declared and initialized for (var i = 0; i < [Link]; i++) {
using the var keyword in the context of the window object, instead, so that the intent is explicitly stated. [Link](array[i]);
}
Additionally, variables may be declared several at a time by separating each declaration (and optional value
assignment) with a comma. Using this syntax, the var and let keywords need only be used once at the beginning of Expected output:
each statement.
'a'
globalA = "1", globalB = "2";
let x, y = 5; 'b'
var person = 'John Doe', 'c'
foo,
age = 14,
date = new Date(); Changing the increment
for (var i = 0; i < 100; i += 2 /* Can also be: i = i + 2 */) {
Notice in the preceding code snippet that the order in which declaration and assignment expressions occur (var a, [Link](i);
b, c = 2, d;) does not matter. You may freely intermix the two. }
0
2
4
...
98
Decremented loop
for (var i = 100; i >=0; i--) {
[Link](i);
}
[Link] – JavaScript® Notes for Professionals 155 [Link] – JavaScript® Notes for Professionals 156
Expected output: const names = ['bob', 'alejandro', 'zandra', 'anna', 'bob'];
Expected output:
You can also use for...of loops to iterate over Maps. This works similarly to arrays and sets, except the iteration
variable stores both a key and a value.
0
1 const map = new Map()
.set('abc', 1)
2
.set('def', 2)
for...of will treat a string as a sequence of Unicode characters: for (const [key, value] of map) {
[Link](key + ' is mapped to ' + value)
const string = "abc"; }
for (let chr of string) { /*Logs:
[Link](chr); abc is mapped to 1
} def is mapped to 2
*/
Expected output:
Objects
abc for...of loops do not work directly on plain Objects; but, it is possible to iterate over an object’s properties by
switching to a for...in loop, or using [Link]():
Sets
const someObject = { name: 'Mike' };
for...of works on Set objects.
for (let key of [Link](someObject)) {
[Link](key + ": " + someObject[key]);
Note:
}
[Link] – JavaScript® Notes for Professionals 157 [Link] – JavaScript® Notes for Professionals 158
name: Mike [Link](i);
i--; /* equivalent to i=i-1 */
}
Warning 100
for...in is intended for iterating over object keys, not array indexes. Using it to loop through an array is 99
generally discouraged. It also includes properties from the prototype, so it may be necessary to check if 98
the key is within the object using hasOwnProperty. If any attributes in the object are defined by the ...
defineProperty/defineProperties method and set the param enumerable: false, those attributes will 1
be inaccessible.
Do...while Loop
var object = {"a":"foo", "b":"bar", "c":"baz"};
A do...while loop will always execute at least once, regardless of whether the condition is true or false:
// `a` is inaccessible
[Link](object , 'a', {
enumerable: false, var i = 101;
}); do {
for (var key in object) { [Link](i);
if ([Link](key)) { } while (i < 100);
[Link]('object.' + key + ', ' + object[key]);
} Expected output:
}
Section 18.4: "while" Loops When you put the continue keyword in a for loop, execution jumps to the update expression (i++ in the example):
Expected output: 0
2
0
1 Continuing a While Loop
...
When you continue in a while loop, execution jumps to the condition (i < 3 in the example):
99
var i = 0;
while (i < 3) {
Decremented loop
if (i === 1) {
var i = 100; i = 2;
while (i > 0) { continue;
[Link] – JavaScript® Notes for Professionals 159 [Link] – JavaScript® Notes for Professionals 160
} }
[Link](i);
i++;
} i=0 j=0 skips rest of j values
10
Expected output:
i=1 j=1 skips rest of j values
20
0 2 1 i=2 j=2 skips rest of j values
2 30
31
32
Section 18.6: Break specific nested loops i=3 j=3 skips rest of j values
40
We can name our loops and break the specific one when necessary. 41
42
outerloop:
43
for (var i = 0;i<3;i++){
innerloop: i=4 j=4 does not log and loops are done
for (var j = 0;j <3; j++){
[Link](i);
[Link](j);
if (j == 1){
break outerloop;
}
}
}
Output:
0
0
0
1
A do while loop is guaranteed to run at least once as it's condition is only checked at the end of an iteration. A
traditional while loop may run zero or more times as its condition is checked at the beginning of an iteration.
[Link] – JavaScript® Notes for Professionals 161 [Link] – JavaScript® Notes for Professionals 162
Chapter 19: Functions }
This climbing behavior can also mean that one reference may "shadow" over a similarly named reference in the
Functions in JavaScript provide organized, reusable code to perform a set of actions. Functions simplify the coding outer scope since it gets seen first.
process, prevent redundant logic, and make code easier to follow. This topic describes the declaration and
utilization of functions, arguments, parameters, return statements and scope in JavaScript. var a = 'hello';
[Link](a); // => 'hello' However, functions are not the only blocks that create a scope (if you are using let or const). let and const
[Link](b); // reference error
declarations have a scope of the nearest block statement. See here for a more detailed description.
}
[Link] – JavaScript® Notes for Professionals 163 [Link] – JavaScript® Notes for Professionals 164
A curried version of this function would look like: (function namedIIFE() {
throw error; // We can now see the error thrown in 'namedIIFE()'
function prism(l) { }());
return function(w) {
return function(h) { While wrapping a function in parenthesis is the most common way to denote to the JavaScript parser to expect an
return l * w * h;
expression, in places where an expression is already expected, the notation can be made more concise:
}
}
} var a = function() { return 42 }();
[Link](a) // => 42
Version ≥ 6
// alternatively, with concise ECMAScript 6+ syntax:
var prism = l => w => h => l * w * h; Arrow version of immediately invoked function:
Version ≥ 6
You can call these sequence of functions with prism(2)(3)(5), which should evaluate to 30. (() => [Link]("Hello!"))(); // => Hello!
Without some extra machinery (like with libraries), currying is of limited syntactical flexibility in JavaScript (ES 5/6)
due to the lack of placeholder values; thus, while you can use var a = prism(2)(3) to create a partially applied Section 19.4: Named Functions
function, you cannot use prism()(3)(5).
Functions can either be named or unnamed (anonymous functions):
Section 19.3: Immediately Invoked Function Expressions var namedSum = function sum (a, b) { // named
return a + b;
Sometimes you don't want to have your function accessible/stored as a variable. You can create an Immediately }
Invoked Function Expression (IIFE for short). These are essentially self-executing anonymous functions. They have
access to the surrounding scope, but the function itself and any internal variables will be inaccessible from outside. var anonSum = function (a, b) { // anonymous
An important thing to note about IIFE is that even if you name your function, IIFE are not hoisted like standard return a + b;
}
functions are and cannot be called by the function name they are declared with.
namedSum(1, 3);
(function() { anonSum(1, 3);
alert("I've run - but can't be run again because I'm immediately invoked at runtime,
leaving behind only the result I generate");
}());
4
4
This is another way to write IIFE. Notice that the closing parenthesis before the semicolon was moved and placed
right after the closing curly bracket:
But their names are private to their own scope:
(function() {
alert("This is IIFE too."); var sumTwoNumbers = function sum (a, b) {
})(); return a + b;
}
You can easily pass parameters into an IIFE:
sum(1, 3);
(function(message) {
alert(message);
}("Hello World!")); Uncaught ReferenceError: sum is not defined
var example = (function() { When you are debugging, the name of the function will appear in the error/stack trace
return 42;
Named functions are hoisted while anonymous functions are not
}());
[Link](example); // => 42 Named functions and anonymous functions behave differently when handling recursion
Depending on ECMAScript version, named and anonymous functions may treat the function name property
If required it is possible to name an IIFE. While less often seen, this pattern has several advantages, such as differently
providing a reference which can be used for a recursion and can make debugging simpler as the name is included
in the callstack.
Named functions are hoisted
[Link] – JavaScript® Notes for Professionals 165 [Link] – JavaScript® Notes for Professionals 166
When using an anonymous function, the function can only be called after the line of declaration, whereas a named Hello!
function can be called before declaration. Consider Uncaught TypeError: say is not a function
foo();
var foo = function () { // using an anonymous function This can be solved using a named function
[Link]('bar');
} // The outer variable can even have the same name as the function
// as they are contained in different scopes
var say = function say (times) {
Uncaught TypeError: foo is not a function if (times > 0) {
[Link]('Hello!');
sayHelloTimes(2);
What if somewhere in your code the original function binding gets redefined? sayHelloTimes(2);
say(times - 1);
}
}
The name property of functions
var sayHelloTimes = say;
Before ES6, named functions had their name properties set to their function names, and anonymous functions had
say = "oops";
their name properties set to the empty string.
sayHelloTimes(2);
[Link] – JavaScript® Notes for Professionals 167 [Link] – JavaScript® Notes for Professionals 168
Version ≤ 5 function example() {
var foo = function () {} return this.x;
[Link]([Link]); // outputs '' }
Section 19.5: Binding `this` and arguments The double colon bind operator can be used as a shortened syntax for the concept explained above:
window.x = 12;
[Link] – JavaScript® Notes for Professionals 169 [Link] – JavaScript® Notes for Professionals 170
Section 19.6: Functions with an Unknown Number of Section 19.7: Anonymous Function
Arguments (variadic functions)
Defining an Anonymous Function
To create a function which accepts an undetermined number of arguments, there are two methods depending on
your environment. When a function is defined, you often give it a name and then invoke it using that name, like so:
Version ≤ 5 foo();
Whenever a function is called, it has an Array-like arguments object in its scope, containing all the arguments function foo(){
passed to the function. Indexing into or iterating over this will give access to the arguments, for example // ...
}
function logSomeThings() {
for (var i = 0; i < [Link]; ++i) { When you define a function this way, the JavaScript runtime stores your function in memory and then creates a
[Link](arguments[i]); reference to that function, using the name you've assigned it. That name is then accessible within the current
} scope. This can be a very convenient way to create a function, but JavaScript does not require you to assign a name
}
to a function. The following is also perfectly legal:
logSomeThings('hello', 'world');
// logs "hello" function() {
// logs "world" // ...
}
Note that you can convert arguments to an actual Array if need-be; see: Converting Array-like Objects to Arrays
When a function is defined without a name, it's known as an anonymous function. The function is stored in
Version ≥ 6 memory, but the runtime doesn't automatically create a reference to it for you. At first glance, it may appear as if
such a thing would have no use, but there are several scenarios where anonymous functions are very convenient.
From ES6, the function can be declared with its last parameter using the rest operator (...). This creates an Array
which holds the arguments from that point onwards Assigning an Anonymous Function to a Variable
function personLogsSomeThings(person, ...msg) { A very common use of anonymous functions is to assign them to a variable:
[Link](arg => {
[Link](person, 'says', arg);
var foo = function(){ /*...*/ };
});
}
foo();
[Link] – JavaScript® Notes for Professionals 171 [Link] – JavaScript® Notes for Professionals 172
var hashValue = hash( 'Secret Value' ); [Link]('Bad.')
};
function getHashFunction( algorithm ){
bar(true);
if ( algorithm === 'sha1' ) return function( value ){ /*...*/ };
else if ( algorithm === 'md5' ) return function( value ){ /*...*/ }; // Console Output:
// Whassup?
} // Bad.
// ...my initialize function is now accessible from global scope. // Assign bar to the original function, and assign foo to another function.
// There is a risk someone could call it again, probably by accident. var bar = foo;
initialize(); foo = function(){
</script> [Link]('Bad.')
};
<script>
// Using an anonymous function, and then immediately bar(true);
// invoking it, hides my foo variable and guarantees
// no one else can call it a second time. // Console Output:
(function(){ // Whassup?
var foo = ''; // Whassup?
}()) // <--- the parentheses invokes the function immediately
</script> Note that the function name is scoped to itself. The name has not leaked into the outer scope:
Self-Referential Anonymous Functions
myself(false); // ReferenceError: myself is not defined
Sometimes it's useful for an anonymous function to be able to refer to itself. For example, the function may need to
recursively call itself or add properties to itself. If the function is anonymous, though, this can be very difficult as it This technique is especially useful when dealing with recursive anonymous functions as callback parameters:
requires knowledge of the variable that the function has been assigned to. This is the less than ideal solution:
Version ≥ 5
// Calculate the Fibonacci value for each number in an array:
var foo = function(callAgain){
var fib = false,
[Link]( 'Whassup?' );
result = [1,2,3,4,5,6,7,8].map(
// Less than ideal... we're dependent on a variable reference...
function fib(n){
if (callAgain === true) foo(false);
return ( n <= 2 ) ? 1 : fib( n - 1 ) + fib( n - 2 );
};
});
// result = [1, 1, 2, 3, 5, 8, 13, 21]
foo(true);
// fib = false (the anonymous function name did not overwrite our fib variable)
// Console Output:
// Whassup?
// Whassup?
Section 19.8: Default parameters
Before ECMAScript 2015 (ES6), a parameter's default value could be assigned in the following way:
// Assign bar to the original function, and assign foo to another function.
var bar = foo;
foo = function(){ function printMsg(msg) {
[Link] – JavaScript® Notes for Professionals 173 [Link] – JavaScript® Notes for Professionals 174
msg = typeof msg !== 'undefined' ? // if a value was provided }
msg : // then, use that value in the reassignment
'Default value for msg.'; // else, assign a default value add(1); // 4, 4
[Link](msg); add(3); // 12, 12
} add(2, 7); // 18, 18
add(1, 2, 5); // 8, 10
add(1, 2, 5, 10); // 8, 20
ES6 provided a new syntax where the condition and reassignment depicted above is no longer necessary:
Reusing the function's return value in a new invocation's default value:
Version ≥ 6 Version ≥ 6
function printMsg(msg='Default value for msg.') { let array = [1]; // meaningless: this will be overshadowed in the function's scope
[Link](msg); function add(value, array = []) {
} [Link](value);
return array;
printMsg(); // -> "Default value for msg."
}
printMsg(undefined); // -> "Default value for msg."
add(5); // [5]
printMsg('Now my msg in different!'); // -> "Now my msg in different!"
add(6); // [6], not [5, 6]
add(6, add(5)); // [5, 6]
This also shows that if a parameter is missing when the function is invoked, its value is kept as undefined, as it can
arguments value and length when lacking parameters in invocation
be confirmed by explicitly providing it in the following example (using an arrow function):
Version ≥ 6 The arguments array object only retains the parameters whose values are not default, i.e. those that are explicitly
let param_check = (p = 'str') => [Link](p + ' is of type: ' + typeof p); provided when the function is invoked:
Version ≥ 6
param_check(); // -> "str is of type: string"
param_check(undefined); // -> "str is of type: string" function foo(a = 1, b = a + 1) {
[Link]([Link], arguments);
param_check(1); // -> "1 is of type: number" [Link](a,b);
param_check(this); // -> "[object Window] is of type: object" }
Functions/variables as default values and reusing parameters foo(); // info: 0 >> [] | log: 1, 2
foo(4); // info: 1 >> [4] | log: 4, 5
The default parameters' values are not restricted to numbers, strings or simple objects. A function can also be set foo(5, 6); // info: 2 >> [5, 6] | log: 5, 6
as the default value callback = function(){}:
foo(function (){ This is useful, because functions that operate on one object (the object that they are a property of) can be
[Link]('custom');
repurposed to operate on another, compatible object. Additionally, arguments can be given in one shot as arrays,
});
// custom similar to the spread (...) operator in ES6.
[Link] – JavaScript® Notes for Professionals 175 [Link] – JavaScript® Notes for Professionals 176
[Link](myObj, 5, 4); // success; `this` in set() is re-routed to myObj instead of obj multiplyTwoThenAddTen(10); // 30
[Link](myObj, [5, 4]); // same as above; note the array
The "application" part of partial application simply means fixing parameters of a function.
[Link](myObj); // prints { a: 3, b: 5 }
ECMAScript 5 introduced another method called bind() in addition to call() and apply() to explicitly set this
value of the function to specific object. In JavaScript all arguments are passed by value. When a function assigns a new value to an argument variable, that
change will not be visible to the caller:
It behaves quite differently than the other two. The first argument to bind() is the this value for the new function.
All other arguments represent named parameters that should be permanently set in the new function. var obj = {a: 2};
function myfunc(arg){
arg = {a: 5}; // Note the assignment is to the parameter variable itself
function showName(label) {
}
[Link](label + ":" + [Link]);
myfunc(obj);
}
[Link](obj.a); // 2
var student1 = {
name: "Ravi"
}; However, changes made to (nested) properties of such arguments, will be visible to the caller:
var student2 = {
name: "Vinod" var obj = {a: 2};
}; function myfunc(arg){
arg.a = 5; // assignment to a property of the argument
// create a function just for student1 }
var showNameStudent1 = [Link](student1); myfunc(obj);
showNameStudent1("student1"); // outputs "student1:Ravi" [Link](obj.a); // 5
// attaching a method to an object doesn't change `this` value of that method. As primitive valued arguments, like numbers or strings, are immutable, there is no way for a function to mutate
[Link] = showNameStudent1; them:
[Link]("student2"); // outputs "student2:Ravi"
var s = 'say';
Example:
When a function wants to mutate an object passed as argument, but does not want to actually mutate the caller's
object, the argument variable should be reassigned:
This function ...
Version ≥ 6
function multiplyThenAdd(a, b, c) {
var obj = {a: 2, b: 3};
return a * b + c;
function myfunc(arg){
}
arg = [Link]({}, arg); // assignment to argument variable, shallow copy
arg.a = 5;
... can be used to create another function that will always multiply by 2 and then add 10 to the passed value; }
myfunc(obj);
function reversedMultiplyThenAdd(c, b, a) { [Link](obj.a); // 2
return a * b + c;
} As an alternative to in-place mutation of an argument, functions can create a new value, based on the argument,
and return it. The caller can then assign it, even to the original variable that was passed as argument:
function factory(b, c) {
return [Link](null, c, b);
var a = 2;
}
function myfunc(arg){
arg++;
var multiplyTwoThenAddTen = factory(2, 10);
return arg;
[Link] – JavaScript® Notes for Professionals 177 [Link] – JavaScript® Notes for Professionals 178
} and easily create a transformation track:
a = myfunc(a);
[Link](obj.a); // 3 Version ≥ 6
const formatText = compose(capitalize, sign);
function addition (argument1, argument2){ Implementation of compose are present in many JavaScript utility libraries (lodash, rambda, etc.) but you can also
return argument1 + argument2; start out with a simple implementation such as:
}
Version ≥ 6
[Link](addition(2, 3)); // -> 5
const compose = (...funs) =>
arguments object x =>
[Link]((ac, f) => f(ac), x);
The arguments object contains all the function's parameters that contain a non-default value. It can also be used
even if the parameters are not explicitly declared: Section 19.14: Get the name of a function object
(function() { [Link](arguments) })(0,'str', [2,{3}]) // -> [0, "str", Array[2]] Version ≥ 6
Although when printing arguments the output resembles an Array, it is in fact an object: ES6:
Composing multiple functions into one is a functional programming common practice; return result ? result[1] : ''
}
composition makes a pipeline through which our data will transit and get modified simply working on the function-
composition (just like snapping pieces of a track together)...
Section 19.15: Recursive Function
you start out with some single responsibility functions:
A recursive function is simply a function, that would call itself.
Version ≥ 6
const capitalize = x => [Link](/^\w/, m => [Link]()); function factorial (n) {
const sign = x => x + ',\nmade with love'; if (n <= 1) {
return 1;
}
[Link] – JavaScript® Notes for Professionals 179 [Link] – JavaScript® Notes for Professionals 180
}
return n * factorial(n - 1);
}
Running this function like so will look like this:
The above function shows a basic example of how to perform a recursive function to return a factorial. [Link](firstChar("JS"));
It is important that such functions make some sort of sentinel value check to avoid infinite loops. In the first
When JavaScript sees an incomplete statement like var it looks to the next line to complete itself. However, if you
example above, when n is less than or equal to 1, the recursion stops, allowing the result of each call to be returned
make the same mistake with the return statement, you will not get what you expected.
back up the call stack.
return
Section 19.16: Using the Return Statement "Hi, my name is "+ name + ". " +
"I'm "+ age + " years old.";
The return statement can be a useful way to create output for a function. The return statement is especially useful
if you do not know in which context the function will be used yet. This code will return undefined because return by itself is a complete statement in JavaScript, so it will not look to
the next line to complete itself. If you need to split up a return statement into multiple lines, put a value next to
//An example function that will take a string as input and return return before you split it up, like so.
//the first character of the string.
Console output will be: A function defined like this is accessible from anywhere within its context by its name. But sometimes it can be
useful to treat function references like object references. For example, you can assign an object to a variable based
> H on some set of conditions and then later retrieve a property from one or the other object:
[Link] – JavaScript® Notes for Professionals 181 [Link] – JavaScript® Notes for Professionals 182
In JavaScript, you can do the same thing with functions: function getValue(){
return 41;
}
// Example 1
var hashAlgorithm = 'sha1';
var hash; A reference to a function is like any other value. As you've seen, a reference can be assigned to a variable, and that
variable's reference value can be subsequently assigned to other variables. You can pass around references to
if ( hashAlgorithm === 'sha1' ) hash = function(value){ /*...*/ };
functions like any other value, including passing a reference to a function as the return value of another function.
else if ( hashAlgorithm === 'md5' ) hash = function(value){ /*...*/ };
For example:
hash('Fred');
// Example 5
// getHashingFunction returns a function, which is assigned
In the example above, hash is a normal variable. It is assigned a reference to a function, after which the function it
// to hash for later use:
references can be invoked using parentheses, just like a normal function declaration. var hash = getHashingFunction( 'sha1' );
// ...
The example above references anonymous functions... functions that do not have their own name. You can also hash('Fred');
use variables to refer to named functions. The example above could be rewritten like so:
// Example 6
Or, you can assign function references from object properties: var hashedValue = getHashingFunction( 'sha1' )( 'Fred' );
A Note on Hoisting
// Example 3
var hashAlgorithms = {
sha1: function(value) { /**/ }, Keep in mind that, unlike normal function declarations, variables that reference functions are not "hoisted". In
md5: function(value) { /**/ } example 2, the md5Hash and sha1Hash functions are defined at the bottom of the script, but are available
}; everywhere immediately. No matter where you define a function, the interpreter "hoists" it to the top of its scope,
making it immediately available. This is not the case for variable definitions, so code like the following will break:
var hashAlgorithm = 'sha1';
var hash;
var functionVariable;
if ( hashAlgorithm === 'sha1' ) hash = hashAlgorithms.sha1;
else if ( hashAlgorithm === 'md5' ) hash = hashAlgorithms.md5; hoistedFunction(); // works, because the function is "hoisted" to the top of its scope
functionVariable(); // error: undefined is not a function.
hash('Fred');
function hoistedFunction(){}
functionVariable = function(){};
You can assign the reference to a function held by one variable to another by omitting the parentheses. This can
result in an easy-to-make mistake: attempting to assign the return value of a function to another variable, but
accidentally assigning the reference to the function.
// Example 4
var a = getValue;
var b = a; // b is now a reference to getValue.
var c = b(); // b is invoked, so c now holds the value returned by getValue (41)
[Link] – JavaScript® Notes for Professionals 183 [Link] – JavaScript® Notes for Professionals 184
Chapter 20: Functional JavaScript .bind(h, h1, h2)
.bind(g, g1, g2)
.bind(f, f1, f2);
// invoke the callback function. // func doesn't have to know anything about monads
callbackFn(); [Link] = function (func, ...args) {
} return identityMonad(func(value, ...args));
};
// invoke your higher-order function with a callback function.
iAmJustFunction(iAmCallbackFunction); // Get the value wrapped in this monad
[Link] = function () {
A higher-order function is also a function that returns another function as its result. return value;
};
function iAmJustFunction() {
return monad;
// do some stuff ...
};
// return a function.
return function iAmReturnedFunction() { It works with primitive values
[Link]("returned function has been invoked");
} var value = 'foo',
} f = x => x + ' changed',
g = x => x + ' again';
// invoke your higher-order function and its returned function.
iAmJustFunction()(); identityMonad(value)
.apply(f)
This is an example of an implementation of the identity monad in JavaScript, and could serve as a starting point to
And also with objects
create other monads.
var value = { foo: 'foo' },
Based on the conference by Douglas Crockford on monads and gonads
f = x => identityMonad([Link](x, { foo: 'bar' })),
g = x => [Link](x, { bar: 'foo' }),
Using this approach reusing your functions will be easier because of the flexibility this monad provides, and h = x => [Link]('foo: ' + [Link] + ', bar: ' + [Link]);
composition nightmares:
identityMonad(value)
f(g(h(i(j(k(value), j1), i2), h1, h2), g1, g2), f1, f2) .bind(f)
.apply(g)
.bind(h); // Logs 'foo: bar, bar: foo'
readable, nice and clean:
[Link] – JavaScript® Notes for Professionals 185 [Link] – JavaScript® Notes for Professionals 186
divideMonad = (x, ...args) => identityMonad(x / multiply(...args)), let b = pure(obj)
log = x => [Link](x), [Link](obj) // Logs { "a": 0 }
substract = (x, ...args) => x - add(...args); [Link](b) // Logs 1
identityMonad(100)
The function did not change the object obj values
.apply(add, 10, 29, 13)
.apply(multiply, 2)
.bind(divideMonad, 2)
.apply(substract, 67, 34)
.apply(multiply, 1239)
Pure functions must not rely on variables outside their scope
.bind(divideMonad, 20, 54, 2)
.apply([Link])
.call(log); // Logs 29
Impure function
A basic principle of functional programming is that it avoids changing the application state (statelessness) and let impure = (input) => {
variables outside its scope (immutability). // Multiply with variable outside function scope
let output = input * a;
return output;
Pure functions are functions that:
}
with a given input, always return the same output [Link](impure(2)) // Logs 2
they do not rely on any variable outside their scope a++; // a becomes equal to 2
they do not modify the state of the application (no side effects) [Link](impure(2)) // Logs 4
Let's take a look at some examples: This impure function rely on variable a that is defined outside its scope. So, if a is modified, impure's function result
will be different.
Pure function
Pure functions must not change any variable outside their scope
let pure = (input) => {
let a = 1;
// Multiply with variable inside function scope
Impure function
let output = input * a;
return output;
let obj = { a: 0 } }
let b = impure(obj)
Section 20.4: Accepting Functions as Arguments
[Link](obj) // Logs { "a": 1 }
[Link](b) // Logs 1 function transform(fn, arr) {
let result = [];
for (let el of arr) {
The function changed the obj.a value that is outside its scope. [Link](fn(el)); // We push the result of the transformed item to result
}
Pure function return result;
}
let obj = { a: 0 }
[Link](transform(x => x * 2, [1,2,3,4])); // [2, 4, 6, 8]
const pure = (input) => {
// Does not modify obj As you can see, our transform function accepts two parameters, a function and a collection. It will then iterate the
let output = input.a + 1;
collection, and push values onto the result, calling fn on each of them.
return output;
}
Looks familiar? This is very similar to how [Link]() works!
[Link] – JavaScript® Notes for Professionals 187 [Link] – JavaScript® Notes for Professionals 188
[Link]([1, 2, 3, 4].map(x => x * 2)); // [2, 4, 6, 8]
Chapter 21: Prototypes, objects
In the conventional JS there are no class instead we have prototypes. Like the class, prototype inherits the
properties including the methods and the variables declared in the class. We can create the new instance of the
object whenever it is necessary by, [Link](PrototypeName); (we can give the value for the constructor as
well)
};
[Link] = function() {
if ([Link]) { // checks whether this prototype has instance of speak
[Link] = "Steve"
[Link]('Hi, I am ' + [Link]);
} else{
[Link]('Sorry i can not speak');
}
};
obj = [Link]([Link]);
[Link]();
We can pass value for the constructor and make the boolean true and false based on the requirement.
Detailed Explanation
[Link] = [Link]([Link]);
[Link] = Student;
[Link] = function() {
if ([Link]) {
[Link]('Hi, I am ' + [Link] + ', the ' + [Link]);
}
};
[Link] – JavaScript® Notes for Professionals 189 [Link] – JavaScript® Notes for Professionals 190
var Customer = function(name) {
[Link](this); // inheriting from the base class
[Link] = name;
Chapter 22: Classes
Section 22.1: Class Constructor
};
var bill = new Student('Billy', 'Teacher'); It's defined in a class block as though you're defining a method named constructor, though it's actually handled
var carter = new Customer('Carter');
as a special case.
var andy = new Student('Andy', 'Bill');
var virat = new Customer('Virat');
class MyClass {
[Link](); constructor(option) {
// Hi, I am Bob, the Teacher [Link](`Creating instance using ${option} option.`);
[Link] = option;
[Link](); }
// Hi, I am Carter }
A small thing to note is that a class constructor cannot be made static via the static keyword, as described below
for other methods.
If the subclass declares its own constructor then it must invoke the parents constructor via super() before it can
access this.
class SuperClass {
constructor() {
[Link] = [Link];
}
log() {
[Link](`Hello ${[Link]}`);
}
constructor() {
super();
[Link] = 'subclass';
}
[Link] – JavaScript® Notes for Professionals 191 [Link] – JavaScript® Notes for Professionals 192
Section 22.3: Static Methods const myClassInstance = new MyClass();
[Link] = 'Joe';
[Link] = 'Bob';
Static methods and properties are defined on the class/constructor itself, not on instance objects. These are specified
in a class definition by using the static keyword. [Link]([Link]); // logs: "Bob"
[Link](myClassInstance.names_); // logs: ["Joe", "Bob"]
class MyClass {
static myStaticMethod() { If you only define a setter, attempting to access the property will always return undefined.
return 'Hello';
}
const classInstance = new class {
set prop(value) {
static get myStaticProperty() {
[Link]('setting', value);
return 'Goodbye';
}
}
};
}
We can see that static properties are not defined on object instances:
If you only define a getter, attempting to assign the property will have no effect.
Here's an example class which provides a getter and setter for its .name property. Each time it's assigned, we'll constructor () { // - does generate a closure with each instantiation.
record the new name in an internal .names_ array. Each time it's accessed, we'll return the latest name.
const list = []; // - local state ("private member").
[Link] – JavaScript® Notes for Professionals 193 [Link] – JavaScript® Notes for Professionals 194
var q = new Queue; // [METADATA]() {
// return {
[Link](9); // ... first in ... make: [Link],
[Link](8); // model: [Link]
[Link](7); // };
// }
[Link]([Link]()); // 9 ... first out.
[Link]([Link]()); // 8 // you can also use any javascript expression
[Link]([Link]()); // 7
[Link](q); // {} // this one is just a string, and could also be defined with simply add()
[Link]([Link](q)); // ["enqueue","dequeue"] ["add"](a, b) {
return a + b;
}
With every instantiation of a Queue type the constructor generates a closure.
// this one is dynamically evaluated
Thus both of a Queue type's own methods enqueue and dequeue (see [Link](q)) still do have access to list
[1 + 2]() {
that continues to live in its enclosing scope that, at construction time, has been preserved. return "three";
}
Making use of this pattern - emulating private members via privileged public methods - one should keep in mind }
that, with every instance, additional memory will be consumed for every own property method (for it is code that
can't be shared/reused). The same is true for the amount/size of state that is going to be stored within such a let MazdaMPV = new Car("Mazda", "MPV");
[Link](4, 5); // 9
closure.
MazdaMPV[3](); // "three"
MazdaMPV[METADATA](); // { make: "Mazda", model: "MPV" }
Section 22.6: Methods
Methods can be defined in classes to perform a function and optionally return a result.
Section 22.8: Managing Private Data with Classes
They can receive arguments from the caller.
One of the most common obstacles using classes is finding the proper approach to handle private states. There are
4 common solutions for handling private states:
class Something {
constructor(data) {
[Link] = data
Using Symbols
}
Symbols are new primitive type introduced on in ES2015, as defined at MDN
doSomething(text) {
return {
data: [Link], A symbol is a unique and immutable data type that may be used as an identifier for object properties.
text
}
} When using symbol as a property key, it is not enumerable.
}
As such, they won't be revealed using for var in or [Link].
var s = new Something({})
[Link]("hi") // returns: { data: {}, text: "hi" } Thus we can use symbols to store private data.
Section 22.7: Dynamic Method Names const topSecret = Symbol('topSecret'); // our private key; will only be accessible on the scope of
the module file
export class SecretAgent{
There is also the ability to evaluate expressions when naming methods similar to how you can access an objects' constructor(secret){
properties with []. This can be useful for having dynamic property names, however is often used in conjunction this[topSecret] = secret; // we have access to the symbol key (closure)
with Symbols. [Link] = 'just a simple gardner';
[Link] = () => {
let METADATA = Symbol('metadata'); figureWhatToDo(topSecret[topSecret]); // we have access to topSecret
};
class Car { }
constructor(make, model) { }
[Link] = make;
[Link] = model; Because symbols are unique, we must have reference to the original symbol to access the private property.
}
import {SecretAgent} from '[Link]'
// example using symbols
[Link] – JavaScript® Notes for Professionals 195 [Link] – JavaScript® Notes for Professionals 196
const agent = new SecretAgent('steal all the ice cream'); constructor(secret){
// ok let's try to get the secret out of him! const topSecret = secret;
[Link](agent); // ['coverStory'] only cover story is public, our secret is kept. [Link] = 'just a simple gardner';
agent[Symbol('topSecret')]; // undefined, as we said, symbols are always unique, so only the [Link] = () => {
original symbol will help us to get the data. figureWhatToDo(topSecret); // we have access to topSecret
};
}
But it's not 100% private; let's break that agent down! We can use the [Link] method to
}
get the object symbols.
In this example as well the data is 100% private and can't be reached outside the class, so our agent is safe.
const secretKeys = [Link](agent);
agent[secretKeys[0]] // 'steal all the ice cream' , we got the secret.
Using naming conventions
Using WeakMaps We will decide that any property who is private will be prefixed with _.
WeakMap is a new type of object that have been added for es6. Note that for this approach the data isn't really private.
The key in a WeakMap is held weakly. What this means is that, if there are no other strong references to
the key, the entire entry will be removed from the WeakMap by the garbage collector.
Section 22.9: Class Name binding
ClassDeclaration's Name is bound in different ways in different scopes -
The idea is to use the WeakMap, as a static map for the whole class, to hold each instance as key and keep the
1. The scope in which the class is defined - let binding
private data as a value for that instance key.
2. The scope of the class itself - within { and } in class {} - const binding
Thus only inside the class will we have access to the WeakMap collection.
class Foo {
// Foo inside this block is a const binding
Let's give our agent a try, with WeakMap:
}
// Foo here is a let binding
const topSecret = new WeakMap(); // will hold all private data of all instances.
export class SecretAgent{
constructor(secret){
For example,
[Link](this,secret); // we use this, as the key, to set it on our instance private
data class A {
[Link] = 'just a simple gardner'; foo() {
[Link] = () => { A = null; // will throw at runtime as A inside the class is a `const` binding
figureWhatToDo([Link](this)); // we have access to topSecret }
}; }
} A = null; // will NOT throw as A here is a `let` binding
}
This is not the same for a Function -
Because the const topSecret is defined inside our module closure, and since we didn't bind it to our instance
properties, this approach is totally private, and we can't reach the agent topSecret. function A() {
A = null; // works
Define all methods inside the constructor }
[Link] = function foo() {
A = null; // works
The idea here is simply to define all our methods and members inside the constructor and use the closure to access
}
private members without assigning them to this. A = null; // works
[Link] – JavaScript® Notes for Professionals 197 [Link] – JavaScript® Notes for Professionals 198
Chapter 23: Namespacing Chapter 24: Context (this)
Section 23.1: Namespace by direct assignment Section 24.1: this with simple objects
//Before: antipattern 3 global variables var person = {
var setActivePage = function () {}; name: 'John Doe',
var getPage = function() {}; age: 42,
var redirectPage = function() {}; gender: 'male',
bio: function() {
//After: just 1 global variable, no function collision and more meaningful function names [Link]('My name is ' + [Link]);
var NavigationNs = NavigationNs || {}; }
[Link] = function() {} };
[Link] = function() {} [Link](); // logs "My name is John Doe"
[Link] = function() {} var bio = [Link];
bio(); // logs "My name is undefined"
Section 23.2: Nested Namespaces In the above code, [Link] makes use of the context (this). When the function is called as [Link](), the
When multiple modules are involved, avoid proliferating global names by creating a single global namespace. From context gets passed automatically, and so it correctly logs "My name is John Doe". When assigning the function to a
there, any sub-modules can be added to the global namespace. (Further nesting will slow down performance and variable though, it loses its context.
add unnecessary complexity.) Longer names can be used if name clashes are an issue:
In non-strict mode, the default context is the global object (window). In strict mode it is undefined.
Here the context (this) is lost in the inner callback function. To correct this, you can save the value of this in a
variable:
[Link]('myAJAXButton'). > var self = this;
makeAJAXRequest(function(result){
if (result) { // success
[Link] = 'success';
}
})
}
Version ≥ 6
ES6 introduced arrow functions which include lexical this binding. The above example could be written like this:
[Link]('myAJAXButton'). > makeAJAXRequest(result => {
if (result) { // success
[Link] = 'success';
}
})
}
[Link] – JavaScript® Notes for Professionals 199 [Link] – JavaScript® Notes for Professionals 200
Section 24.3: Binding function context //outputs: I'm Stackoverflow
Version ≥ 5.1
[Link](person3);
Every function has a bind method, which will create a wrapped function that will call it with the correct context. See //outputs: I'm Stackoverflow
Hard binding
function Person(){
[Link]("I'm " + [Link]);
}
Person();
//outputs: I'm Stackoverflow
[Link](person1);
//outputs: I'm Stackoverflow
[Link](person2);
[Link] – JavaScript® Notes for Professionals 201 [Link] – JavaScript® Notes for Professionals 202
Chapter 25: Setters and Getters }
this._firstname = firstname;
this._lastname = lastname;
Setters and getters are object properties that call a function when they are set/gotten.
get firstname() {
return this._firstname;
Section 25.1: Defining a Setter/Getter Using }
[Link]fineProperty set firstname(name) {
this._firstname = name;
var setValue; }
var obj = {};
[Link](obj, "objProperty", { get lastname() {
get: function(){ return this._lastname;
return "a value"; }
},
set: function(value){ set lastname(name) {
setValue = value; this._lastname = name;
} }
}); }
Section 25.2: Defining an Setter/Getter in a Newly Created let person = new Person('John', 'Doe');
JavaScript allows us to define getters and setters in the object literal syntax. Here's an example: [Link] = 'Foo';
[Link] = 'Bar';
var date = {
year: '2017', [Link]([Link], [Link]); // Foo Bar
month: '02',
day: '27',
get date() {
// Get the date in YYYY-MM-DD format
return `${[Link]}-${[Link]}-${[Link]}`
},
set date(dateString) {
// Set the date from a YYYY-MM-DD formatted string
var dateRegExp = /(\d{4})-(\d{2})-(\d{2})/;
Accessing the [Link] property would return the value 2017-02-27. Setting [Link] = '2018-01-02 would call
the setter function, which would then parse the string and set [Link] = '2018', [Link] = '01', and
[Link] = '02'. Trying to pass an incorrectly formatted string (such as "hello") would throw an error.
[Link] – JavaScript® Notes for Professionals 203 [Link] – JavaScript® Notes for Professionals 204
Chapter 26: Events Chapter 27: Inheritance
Section 26.1: Page, DOM and Browser loading Section 27.1: Standard function prototype
This is an example to explain the variations of load events. Start by defining a Foo function that we'll use as a constructor.
<body > By editing [Link], we can define properties and methods that will be shared by all instances of Foo.
<img src="image1" />
<img src="image2" />
</body> [Link] = function() {
return 'I am bar';
<script> };
function someFunction() {
[Link]("Hi! I am loaded"); We can then create an instance using the new keyword, and call the method.
}
</script> var foo = new Foo();
In this case, the message is logged once all the contents of the page including the images and stylesheets(if any) are [Link]([Link]()); // logs `I am bar`
completely loaded.
2. DOMContentLoaded event
Section 27.2: Dierence between [Link] and
[Link]
[Link]("DOMContentLoaded", function(event) { Unlike in languages like Python, static properties of the constructor function are not inherited to instances.
[Link]("Hello! I am loaded");
Instances only inherit from their prototype, which inherits from the parent type's prototype. Static properties are
});
never inherited.
In the above code, the message is logged only after the DOM/document is loaded (ie:once the DOM is constructed). function Foo() {};
[Link] = 'bold';
3. Self-invoking anonymous function
var foo = new Foo();
Here, the message gets logged as soon as the browser interprets the anonymous function. It means, this function [Link]([Link]); // 'bold'
can get executed even before the DOM is loaded. [Link]([Link]); // 'italic'
Now we want another object called obj that inherits from prototype, which is the same as saying that prototype is
the prototype of obj
Now all the properties and methods from prototype will be available to obj
[Link]([Link]);
[Link] – JavaScript® Notes for Professionals 205 [Link] – JavaScript® Notes for Professionals 206
[Link]([Link]()); [Link]([Link]);
"foo"
"foo" 1
Prototypal inheritance is made through object references internally and objects are completely mutable. This
foo is an instance of Foo. The JavaScript coding convention says if a function begins with a capital letter case it can
means any change you make on a prototype will immediately affect every other object that prototype is prototype
be called as a constructor (with the new operand).
of.
To add properties or methods to the "class" you have to add them to its prototype, which can be found in the
[Link] = "bar"; prototype property of the constructor.
[Link]([Link]);
[Link] = 'bar';
Console output [Link]([Link]);
[Link] is the prototype of every object, so it's strongly recommended you don't mess with it, especially
if you use any third party library, but we can play with it a little bit. bar
[Link] = 'foo';
In fact what Foo is doing as a "constructor" is just creating objects with [Link] as it's prototype.
[Link]([Link]);
[Link]([Link]);
You can find a reference to its constructor on every object
Console output
[Link]([Link]);
"foo"
"foo"
function Foo(id, name) { ...
Fun fact I've used the browser console to make these examples and broken this page by adding that
breakingLibraries property. [Link]({ }.constructor);
IMPORTANT NOTE: Since ES6 it doesn't make sense to use pseudo-classical inheritance since the language true
simulates conventional classes. If you're not using ES6, you should. If you still want to use the classical inheritance
pattern and you're in a ECMAScript 5 or lower environment, then pseudo-classical is your best bet.
[Link](foo instanceof Object);
A "class" is just a function that is made to be called with the new operand and it's used as a constructor.
true
function Foo(id, name) {
[Link] = id;
[Link] = name; Section 27.5: Setting an Object's prototype
}
Version ≥ 5
var foo = new Foo(1, 'foo');
With ES5+, the [Link] function can be used to create an Object with any other Object as it's prototype.
[Link] – JavaScript® Notes for Professionals 207 [Link] – JavaScript® Notes for Professionals 208
const anyObj = {
hello() { Chapter 28: Method Chaining
[Link](`[Link] is ${[Link]}`);
};
},
Section 28.1: Chainable object design and chaining
Chaining and Chainable is a design methodology used to design object behaviors so that calls to object functions
let objWithProto = [Link](anyObj);
[Link] = 'bar'; return references to self, or another object, providing access to additional function calls allowing the calling
statement to chain together many calls without the need to reference the variable holding the object/s.
[Link](); // "[Link] is bar"
Objects that can be chained are said to be chainable. If you call an object chainable, you should ensure that all
To explicitly create an Object without a prototype, use null as the prototype. This means the Object will not inherit returned objects / primitives are of the correct type. It only takes one time for your chainable object to not return
from [Link] either and is useful for Objects used for existence checking dictionaries, e.g. the correct reference (easy to forget to add return this) and the person using your API will lose trust and avoid
chaining. Chainable objects should be all or nothing (not a chainable object even if parts are). An object should not
let objInheritingObject = {}; be called chainable if only some of its functions are.
let objInheritingNull = [Link](null);
Object designed to be chainable
'toString' in objInheritingObject; // true
'toString' in objInheritingNull ; // false function Vec(x = 0, y = 0){
this.x = x;
Version ≥ 6
this.y = y;
// the new keyword implicitly implies the return type
From ES6, the prototype of an existing Object can be changed using [Link], for example
// as this and thus is chainable by default.
}
let obj = [Link]({foo: 'foo'}); [Link] = {
obj = [Link](obj, {bar: 'bar'}); add : function(vec){
this.x += vec.x;
[Link]; // undefined this.y += vec.y;
[Link]; // "bar" return this; // return reference to self to allow chaining of function calls
},
This can be done almost anywhere, including on a this object or in a constructor. scale : function(val){
this.x *= val;
Note: This process is very slow in current browsers and should be used sparingly, try to create the Object with the this.y *= val;
return this; // return reference to self to allow chaining of function calls
desired prototype instead.
},
log :function(val){
Version < 5
[Link](this.x + ' : ' + this.y);
return this;
Before ES5, the only way to create an Object with a manually defined prototype was to construct it with new, for
},
example clone : function(){
return new Vec(this.x,this.y);
var proto = {fizz: 'buzz'}; }
}
function ConstructMyObj() {}
Chaining example
[Link] = proto;
var vec = new Vec();
var objWithProto = new ConstructMyObj(); [Link]({x:10,y:10})
[Link]; // "buzz" .add({x:10,y:10})
.log() // console output "20 : 20"
.add({x:10,y:10})
This behaviour is close enough to [Link] that it is possible to write a polyfill.
.scale(1/30)
.log() // console output "1 : 1"
.clone() // returns a new instance of the object
.scale(2) // from which you can continue chaining
.log()
Not all function calls return a useful chainable type, nor do they always return a reference to self. This is where
common sense use of naming is important. In the above example the function call .clone() is unambiguous. Other
[Link] – JavaScript® Notes for Professionals 209 [Link] – JavaScript® Notes for Professionals 210
examples are .toString() implies a string is returned. When you assign the results of a chain the last returning call or object reference is assigned.
The advantage of changing is clearer more maintainable code. Some people prefer it and will make chainable a
Syntax convention
requirement when selecting an API. There is also a performance benefit as it allows you to avoid having to create
variables to hold interim results. With the last word being that chainable objects can be used in a conventional way
There is no formal usage syntax when chaining. The convention is to either chain the calls on a single line if short or
as well so you don't enforce chaining by making an object chainable.
to chain on the new line indented one tab from the referenced object with the dot on the new line. Use of the
semicolon is optional but does help by clearly denoting the end of the chain.
Section 28.2: Method Chaining
[Link](2).add({x:2,y:2}).log(); // for short chains
Method chaining is a programming strategy that simplifies your code and beautifies it. Method chaining is done by
[Link](2) // or alternate syntax ensuring that each method on an object returns the entire object, instead of returning a single element of that
.add({x:2,y:2}) object. For example:
.log(); // semicolon makes it clear the chain ends here
function Door() {
// and sometimes though not necessary
[Link] = '';
[Link](2)
[Link] = '';
.add({x:2,y:2})
[Link] = 'closed';
.clone() // clone adds a new reference to the chain
}
.log(); // indenting to signify the new reference
[Link] = function() {
// for chains in chains
[Link] = 'opened';
[Link](2)
return this;
.add({x:2,y:2})
}
.add([Link]({x:2,y:2}) // a chain as an argument
.add({x:2,y:2}) // is indented
[Link] = function() {
.scale(2))
[Link] = 'closed';
.log();
return this;
}
// or sometimes
[Link] = function(width,height) {
[Link](2)
[Link] = width;
.add({x:2,y:2})
[Link] = height;
.add([Link]({x:2,y:2}) // a chain as an argument
return this;
.add({x:2,y:2}) // is indented
}
.scale(2)
).log(); // the argument list is closed on the new line
[Link] = function() {
A bad syntax [Link]('The',[Link],'x',[Link],'Door is',[Link]);
vec // new line before the first function call return this;
.scale() // can make it unclear what the intention is }
.log();
var smallDoor = new Door();
vec. // the dot on the end of the line [Link](20,100).open().doorStatus().close().doorStatus();
scale(2). // is very difficult to see in a mass of code
scale(1/2); // and will likely frustrate as can easily be missed Note that each method in [Link] returns this, which refers to the entire instance of that Door object.
// when trying to locate bugs
[Link] – JavaScript® Notes for Professionals 211 [Link] – JavaScript® Notes for Professionals 212
Chapter 29: Callbacks $.getJSON() syntax:
function foo(array) { The following would not work, because the data-handling code would likely be called before the data is actually
var sum = 0; received, because the $.getJSON function takes an unspecified length of time and does not hold up the call stack as
for (var i = 0; i < [Link]; i++) { it waits for the JSON.
sum += array[i];
}
$.getJSON("[Link]", {});
return sum;
// data handling code
}
Now suppose that we want to do something with each value of the array, e.g. display it using alert(). We could Another example of an asynchronous function is jQuery's animate() function. Because it takes a specified time to
make the appropriate changes in the code of foo, like this: run the animation, sometimes it is desirable to run some code directly following the animation.
.animate() syntax:
function foo(array) {
var sum = 0;
for (var i = 0; i < [Link]; i++) { [Link]( properties, duration, callback );
alert(array[i]);
sum += array[i]; For example, to create a fading-out animation after which the element completely disappears, the following code
} can be run. Note the use of the callback.
return sum;
}
[Link]( { opacity: 0 }, 5000, function() {
[Link]();
But what if we decide to use [Link] instead of alert()? Obviously changing the code of foo, whenever we } );
decide to do something else with each value, is not a good idea. It is much better to have the option to change our
mind without changing the code of foo. That's exactly the use case for callbacks. We only have to slightly change This allows the element to be hidden right after the function has finished execution. This differs from:
foo's signature and body:
[Link]( { opacity: 0 }, 5000 );
function foo(array, callback) { [Link]();
var sum = 0;
for (var i = 0; i < [Link]; i++) { because the latter does not wait for animate() (an asynchronous function) to complete, and therefore the element
callback(array[i]);
is hidden right away, producing an undesirable effect.
sum += array[i];
}
return sum; Section 29.2: Continuation (synchronous and asynchronous)
}
Callbacks can be used to provide code to be executed after a method has completed:
And now we are able to change the behaviour of foo just by changing its parameters:
/**
var array = []; * @arg {Function} then continuation callback
foo(array, alert); */
foo(array, function (x) { function doSomething(then) {
[Link](x); [Link]('Doing something');
}); then();
}
Examples with Asynchronous Functions // Do something, then execute callback to log 'done'
doSomething(function () {
In jQuery, the $.getJSON() method to fetch JSON data is asynchronous. Therefore, passing code in a callback [Link]('Done');
makes sure that the code is called after the JSON is fetched. });
[Link] – JavaScript® Notes for Professionals 213 [Link] – JavaScript® Notes for Professionals 214
[Link]('Doing something else'); }, function onRejected(reason) {
[Link]("Rejected with reason " + reason);
// Outputs: });
// "Doing something"
// "Done"
Here then function then accepts two callback functions, onFulfilled and onRejected. Furthermore, only one of
// "Doing something else"
these two callback functions is actually called.
The doSomething() method above executes synchronously with the callback - execution blocks until doSomething() What's more interesting is that the function then returns before either of the callbacks are called. Hence, a callback
returns, ensuring that the callback is executed before the interpreter moves on. function may be called even after the original function has returned.
The then callbacks are considered continuations of the doSomething() methods. Providing a callback as the last bind effectively generates a new function that sets this to whatever was passed to bind then calls the
instruction in a function is called a tail-call, which is optimized by ES2015 interpreters. original function.
When you call a normal function, it does its job and then returns control back to the caller. Use arrow functions
However, sometimes a function needs to return control back to the caller in order to do its job: Arrow functions automatically bind the current this context.
[Link](function onFulfilled(value) {
[Link]("Fulfilled with value " + value); function SomeClass(msg, elem) {
[Link] – JavaScript® Notes for Professionals 215 [Link] – JavaScript® Notes for Professionals 216
[Link] = msg; [1,2,3,4,5].forEach(x => [Link](x));
[Link]('click', [Link](this));
}
Here the callback function function(x){[Link](x)} is reduced to x=>[Link](x)
[Link] = function(event) {
};
[Link]([Link], [Link]); Section 29.6: Error handling and control-flow branching
Callbacks are often used to provide error handling. This is a form of control flow branching, where some
Use arrow functions and the rest operator
instructions are executed only when an error occurs:
For DOM event listeners in particular you can implement the EventListener interface function onSuccess() {
[Link]('Value was expected');
function SomeClass(msg, elem) { }
[Link] = msg;
[Link]('click', this); function onFailure() {
} [Link]('Value was unexpected/exceptional');
}
[Link] = function(event) {
var fn = this[[Link]]; compare(true, onSuccess, onFailure);
if (fn) { compare(false, onSuccess, onFailure);
[Link](this, arguments);
} // Outputs:
}; // "Value was expected"
// "Value was unexpected/exceptional"
[Link] = function(event) {
[Link]([Link]); Code execution in compare() above has two possible branches: success when the expected and actual values are
}; the same, and error when they are different. This is especially useful when control flow should branch after some
asynchronous instruction:
Section 29.5: Callback using Arrow function function compareAsync(actual, success, failure) {
setTimeout(function () {
Using arrow function as callback function can reduce lines of code. compare(actual, success, failure)
}, 1000);
The default syntax for arrow function is }
[1,2,3,4,5].forEach(function(x){ It should be noted, multiple callbacks do not have to be mutually exclusive – both methods could be called.
[Link](x);
Similarly, the compare() could be written with callbacks that are optional (by using a noop as the default value - see
}
Null Object pattern).
[Link] – JavaScript® Notes for Professionals 217 [Link] – JavaScript® Notes for Professionals 218
Chapter 30: Intervals and Timeouts Section 30.4: Removing intervals
[Link]() returns an IntervalID, which can be used to stop that interval from continuing to run. To
Section 30.1: Recursive setTimeout do this, store the return value of [Link]() in a variable and call clearInterval() with that variable as
the only argument:
To repeat a function indefinitely, setTimeout can be called recursively:
function waitFunc(){
function repeatingFunc() { [Link]("This will be logged every 5 seconds");
[Link]("It's been 5 seconds. Execute the function again."); }
setTimeout(repeatingFunc, 5000);
} var interval = [Link](waitFunc,5000);
specified delay. However, it does not guarantee a regular interval between function executions. This behaviour also
varies because an exception before the recursive call to setTimeout will prevent it from repeating again, while This will log This will be logged every 5 seconds every 5 seconds, but will stop it after 32 seconds. So it will log
setInterval would repeat indefinitely regardless of exceptions. the message 6 times.
You don't need to create the variable, but it's a good practice as you can use that variable with clearInterval to stop var timeout = [Link](waitFunc,5000);
the currently running interval. [Link](stopFunc,3000);
var int = setInterval("doSomething()", 5000 ); /* 5 seconds */ This will not log the message because the timer is stopped after 3 seconds.
var int = setInterval(doSomething, 5000 ); /* same thing, no quotes, no parens */
doSomething(); setTimeout(function() {
[Link]('hello');
setTimeout([Link], 5000); }, 1000);
})()
Problems with setTimeout
[Link] – JavaScript® Notes for Professionals 219 [Link] – JavaScript® Notes for Professionals 220
for (i = 0; i < 3; ++i) {
setTimeout(function(){ Chapter 31: Regular expressions
[Link](i);
}, 500); Flags Details
} g global. All matches (don't return on the first match).
m multi-line. Causes ^ & $ to match the begin/end of each line (not only begin/end of string).
This will output the value 3 three times, which is not correct.
i insensitive. Case insensitive match (ignores case of [a-zA-Z]).
Workaround of this problem : u unicode : Pattern strings are treated as UTF-16. Also causes escape sequences to match Unicode characters.
sticky: matches only from the index indicated by the lastIndex property of this regular expression in the
y
for (i = 0; i < 3; ++i) { target string (and does not attempt to match from any later indexes).
setTimeout(function(j){
[Link](i);
}(i), 1000); Section 31.1: Creating a RegExp Object
}
Standard Creation
It will output the value 0,1,2. Here, we’re passing the i into the function as a parameter(j).
It is recommended to use this form only when creating regex from dynamic variables.
Order of operations
Use when the expression may change or the expression is user generated.
Additionally though, due to the fact that JavaScript is single threaded and uses a global event loop, setTimeout can
var re = new RegExp(".*");
be used to add an item to the end of the execution queue by calling setTimeout with zero delay. For example:
With flags:
setTimeout(function() {
[Link]('world');
}, 0); var re = new RegExp(".*", "gmi");
[Link]('hello'); With a backslash: (this must be escaped because the regex is specified with a string)
hello
Static initialization
world
Use when you know the regular expression will not change, and you know what the expression is before runtime.
Also, zero milliseconds here does not mean the function inside the setTimeout will execute immediately. It will take
slightly more than that depending upon the items to be executed remaining in the execution queue. This one is just var re = /.*/;
pushed to the end of the queue.
With flags:
Cancelling a timeout
var re = /.*/gmi;
clearTimeout() : stops the execution of the function specified in setTimeout()
Syntax : clearTimeout(timeoutVariable) or [Link](timeoutVariable) With a backslash: (this should not be escaped because the regex is specified in a literal)
[Link] – JavaScript® Notes for Professionals 221 [Link] – JavaScript® Notes for Professionals 222
m - Multiline. ^ and $ match the beginning and end of each line respectively treating \n and \r as delimiters instead "string".match(...
of simply the beginning and end of the entire string. "string".replace(...
"string".split(...
Version ≥ 6
"string".search(...
u - Unicode. If this flag is not supported you must match specific Unicode characters with \uXXXX where XXXX is the
Match with RegExp
character's value in hexadecimal.
[Link]("string".match(/[i-n]+/));
[Link]("string".match(/(r)[i-n]+/));
y - Finds all consecutive/adjacent matches.
Expected output
[Link] is 3, the (zero-based) location of the match. Array ["str", "gstr", "g"]
[Link]("string".search(/[i-n]+/));
Loop Through Matches Using .exec()
[Link]("string".search(/[o-q]+/));
var re = /a/g;
var result;
Expected output
while ((result = [Link]('barbatbaz')) !== null) {
[Link]("found '" + result[0] + "', next exec starts at index '" + [Link] + "'");
}
3
-1
Expected output
found 'a', next exec starts at index '2' Section 31.6: RegExp Groups
found 'a', next exec starts at index '5'
JavaScript supports several types of group in its Regular Expressions, capture groups, non-capture groups and look-
found 'a', next exec starts at index '8'
aheads. Currently, there is no look-behind support.
Sometimes the desired match relies on its context. This means a simple RegExp will over-find the piece of the String
The String object has the following methods that accept regular expressions as arguments.
[Link] – JavaScript® Notes for Professionals 223 [Link] – JavaScript® Notes for Professionals 224
that is of interest, so the solution is to write a capture group (pattern). The captured data can then be referenced }
});
as...
// will return Start string End
Say there is a String where all + signs need to be replaced with a space, but only if they follow a letter character. This // "My name is Doe, John Doe"
means a simple match would include that letter character and it would also be removed. Capturing it is the solution
as it means the matched letter can be preserved.
Section 31.8: Using [Link]() with parentheses regex to
let str = "aa+b+cc+1+2", extract matches of a string
re = /([a-z])\+/g;
Sometimes you doesn't want to simply replace or remove the string. Sometimes you want to extract and process
// String replacement matches. Here an example of how you manipulate matches.
[Link](re, '$1 '); // "aa b cc 1+2"
// Function replacement What is a match ? When a compatible substring is found for the entire regex in the string, the exec command
[Link](re, (m, $1) => $1 + ' '); // "aa b cc 1+2"
produce a match. A match is an array compose by firstly the whole substring that matched and all the parenthesis
in the match.
Non-Capture
Imagine a html string :
Using the form (?:pattern), these work in a similar way to capture groups, except they do not store the contents
of the group after the match. <html>
<head></head>
They can be particularly useful if other data is being captured which you don't want to move the indices of, but <body>
need to do some advanced pattern matching such as an OR <h1>Example</h1>
<p>Look at this great link : <a href="[Link]
[Link]
let str = "aa+b+cc+1+2",
Copyright <a href="[Link]
re = /(?:\b|c)([a-z])\+/g;
</body>
If the desired match relies on something which follows it, rather than matching that and capturing it, it is possible to
But now, imagine you want the href and the anchor of each link. And you want it together. You can simply add a
use a look-ahead to test for it but not include it in the match. A positive look-ahead has the form (?=pattern), a
new regex in for each match OR you can use parentheses :
negative look-ahead (where the expression match only happens if the look-ahead pattern did not match) has the
form (?!pattern)
var re = /<a[^>]*href="(https?:\/\/.*)"[^>]*>([^<]*)<\/a>/g;
var str = '<html>\n <head></head>\n <body>\n <h1>Example</h1>\n <p>Look at this
let str = "aa+b+cc+1+2", great link: <a href="[Link] [Link]
re = /\+(?=[a-z])/g; Copyright <a href="[Link] </body>\';\n';
var m;
[Link](re, ' '); // "aa b cc+1+2" var links = [];
Section 31.7: Replacing string match with a callback function while ((m = [Link](str)) !== null) {
if ([Link] === [Link]) {
[Link]++;
String#replace can have a function as its second argument so you can provide a replacement based on some }
logic. [Link](m[0]); // The all substring
[Link](m[1]); // The href subpart
"Some string Some".replace(/Some/g, (match, startIndex, wholeString) => { [Link](m[2]); // The anchor subpart
if(startIndex == 0){
return 'Start'; [Link]({
} else { match : m[0], // the entire match
return 'End'; href : m[1], // the first parenthesis => (https?:\/\/.*)
[Link] – JavaScript® Notes for Professionals 225 [Link] – JavaScript® Notes for Professionals 226
}
anchor : m[2],
});
// the second ([^<]*)
Chapter 32: Cookies
At the end of the loop, you have an array of link with anchor and href and you can use it to write markdown for
Section 32.1: Test if cookies are enabled
example : If you want to make sure cookies are enabled before using them, you can use [Link]:
[Link] +=
COOKIE_NAME + "=" + COOKIE_VALUE
+ "; expires=" + COOKIE_EXPIRES
+ "; path=" + COOKIE_PATH;
This will set cookie_value to the value of the cookie, if it exists. If the cookie is not set, it will set cookie_value to
null
[Link] – JavaScript® Notes for Professionals 227 [Link] – JavaScript® Notes for Professionals 228
Chapter 33: Web Storage // Clear storage
[Link]();
If you want to store simple structured data, you can use JSON to serialize it to and from strings for storage.
// Remove specific data
delete [Link];
var players = [{name: "Tyler", score: 22}, {name: "Ryan", score: 41}];
[Link]('players', [Link](players)); // Clear (delete) all stored data
[Link]();
[Link]([Link]([Link]('players')));
// [ Object { name: "Tyler", score: 22 }, Object { name: "Ryan", score: 41 } ]
[Link] = [Link]('user-value');
Browser Google Chrome Opera Firefox Safari Internet Explorer
Version 40 27 34 6-8 9-11 [Link] = function(event) {
Space available 10MB 10MB 10MB 5MB 10MB [Link]('user-value', [Link]);
};
// Set
[Link]('storage', function(event) {
[Link] = "Hi!"; // Same as: [Link]("greet", "Hi!");
if ([Link] === 'user-value') {
[Link] = [Link];
// Get
}
[Link]; // Same as: [Link]("greet");
});
// Remove item
delete [Link]; // Same as: [Link]("greet"); Notes
[Link] – JavaScript® Notes for Professionals 229 [Link] – JavaScript® Notes for Professionals 230
Event is not fired or catchable under Chrome, Edge and Safari if domain was modified through script. Section 33.5: localStorage length
First window [Link] property returns an integer number indicating the number of elements in the localStorage
// page url: [Link]
[Link] = '[Link]'; Example:
Second Window
[Link]; // 3
// page url: [Link]
[Link] = '[Link]';
Section 33.6: Error conditions
var output = [Link]('p');
[Link](output); Most browsers, when configured to block cookies, will also block localStorage. Attempts to use it will result in an
exception. Do not forget to manage these cases.
// Listener will never called under Chrome(53), Edge and Safari(10.0).
[Link]('storage', function(event) {
if ([Link] === 'user-value') { var video = [Link]('video')
[Link] = [Link]; try {
} [Link] = [Link]('volume')
}); } catch (error) {
alert('If you\'d like your volume saved, turn on cookies')
}
Section 33.4: sessionStorage [Link]()
The sessionStorage object implements the same Storage interface as localStorage. However, instead of being If error were not handled, program would stop functioning properly.
shared with all pages from the same origin, sessionStorage data is stored separately for every window/tab. Stored
data persists between pages in that window/tab for as long as it's open, but is visible nowhere else. Section 33.7: Clearing storage
var audio = [Link]('audio'); To clear the storage, simply run
// Maintain the volume if the user clicks a link then navigates back here.
[Link]();
[Link] = Number([Link]('volume') || 1.0);
[Link] = function(event) {
};
[Link]('volume', [Link]); Section 33.8: Remove Storage Item
To remove a specific item from the browser Storage (the opposite of setItem) use removeItem
Save data to sessionStorage
[Link]("greet");
[Link]('key', 'value');
Example:
Get saved data from sessionStorage
[Link]("greet", "hi");
var data = [Link]('key'); [Link]("greet");
[Link] – JavaScript® Notes for Professionals 231 [Link] – JavaScript® Notes for Professionals 232
Chapter 34: Data attributes Chapter 35: JSON
Section 34.1: Accessing data attributes Parameter Details
[Link] Parse a JSON string
Using the dataset property input(string) JSON string to be parsed.
reviver(function) Prescribes a transformation for the input JSON string.
The new dataset property allows access (for both reading and writing) to all data attributes data-* on any element.
[Link] Serialize a serializable value
<p>Countries:</p>
value(string) Value to be serialized according to the JSON specification.
<ul> replacer(function or String[] or
Selectively includes certain properties of the value object.
<li id="C1" data-id="US" data-dial-code="1">USA</li> Number[])
<li id="C2" data-id="CA" data-dial-code="1">Canada</li> If a number is provided, then space number of whitespaces will be
<li id="C3" data-id="FF" data-dial-code="3">France</li> space(String or Number) inserted of readability. If a string is provided, the string (first 10
</ul> characters) will be used as whitespaces.
<button type="button" Country Details</button>
<script>
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write
function showDetails(item) {
var msg = [Link] and easy for machines to parse and generate. It is important to realize that, in JavaScript, JSON is a string and not an
+ "\r\nISO ID: " + [Link] object.
+ "\r\nDial Code: " + [Link];
alert(msg); A basic overview can be found on the [Link] website which also contains links to implementations of the standard
}
in many different programming languages.
function correctDetails(item) {
var item = [Link]("C3"); Section 35.1: JSON versus JavaScript literals
[Link] = "FR";
[Link] = "33"; JSON stands for "JavaScript Object Notation", but it's not JavaScript. Think of it as just a data serialization format that
} happens to be directly usable as a JavaScript literal. However, it is not advisable to directly run (i.e. through eval())
</script>
JSON that is fetched from an external source. Functionally, JSON isn't very different from XML or YAML – some
confusion can be avoided if JSON is just imagined as some serialization format that looks very much like JavaScript.
Note: The dataset property is only supported in modern browsers and it's slightly slower than the getAttribute
and setAttribute methods which are supported by all browsers. Even though the name implies just objects, and even though the majority of use cases through some kind of API
always happen to be objects and arrays, JSON is not for just objects or arrays. The following primitive types are
Using the getAttribute & setAttribute methods
supported:
If you want to support the older browsers before HTML5, you can use the getAttribute and setAttribute
String (e.g. "Hello World!")
methods which are used to access any attribute including the data attributes. The two functions in the example
Number (e.g. 42)
above can be written this way:
Boolean (e.g. true)
The value null
<script>
function showDetails(item) {
var msg = [Link] undefined is not supported in the sense that an undefined property will be omitted from JSON upon serialization.
+ "\r\nISO ID: " + [Link]("data-id") Therefore, there is no way to deserialize JSON and end up with a property whose value is undefined.
+ "\r\nDial Code: " + [Link]("data-dial-code");
alert(msg); The string "42" is valid JSON. JSON doesn't always have to have an outer envelope of "{...}" or "[...]".
}
While some JSON is also valid JavaScript and some JavaScript is also valid JSON, there are some subtle differences
function correctDetails(item) {
between both languages and neither language is a subset of the other.
var item = [Link]("C3");
[Link]("id", "FR");
Take the following JSON string as an example:
[Link]("data-dial-code", "33");
}
</script> {"color": "blue"}
This can be directly inserted into JavaScript. It will be syntactically valid and will yield the correct value:
[Link] – JavaScript® Notes for Professionals 233 [Link] – JavaScript® Notes for Professionals 234
However, we know that "color" is a valid identifier name and the quotes around the property name can be omitted: Version ≥ 6
const jsonString = '[{"name":"John","score":51},{"name":"Jack","score":17}]';
const skin = {color: "blue"};
const data = [Link](jsonString, (key, value) =>
key === 'name' ? [Link]() : value
We also know that we can use single quotes instead of double quotes: );
But, if we were to take both of these literals and treat them as JSON, neither will be syntactically valid JSON: [
{
{color: "blue"} 'name': 'JOHN',
{'color': 'blue'} 'score': 51
},
JSON strictly requires all property names to be double quoted and string values to be double quoted as well. {
'name': 'JACK',
'score': 17
It's common for JSON-newcomers to attempt to use code excerpts with JavaScript literals as JSON, and scratch their
}
heads about the syntax errors they are getting from the JSON parser. ]
More confusion starts arising when incorrect terminology is applied in code or in conversation.
This is particularly useful when data must be sent that needs to be serialized/encoded when being transmitted with
A common anti-pattern is to name variables that hold non-JSON values as "json": JSON, but one wants to access it deserialized/decoded. In the following example, a date was encoded to its ISO 8601
representation. We use the reviver function to parse this in a JavaScript Date.
fetch(url).then(function (response) {
Version ≥ 5.1
const json = [Link]([Link]); // Confusion ensues!
var jsonString = '{"date":"2016-01-04T23:00:00.000Z"}';
// We're done with the notion of "JSON" at this point,
// but the concept stuck with the variable name. var data = [Link](jsonString, function (key, value) {
}); return (key === 'date') ? new Date(value) : value;
});
Version ≥ 6
In the above example, [Link] is a JSON string that is returned by some API. JSON stops at the HTTP
const jsonString = '{"date":"2016-01-04T23:00:00.000Z"}';
response domain. The variable with the "json" misnomer holds just a JavaScript value (could be an object, an array,
or even a simple number!) const data = [Link](jsonString, (key, value) =>
key === 'date' ? new Date(value) : value
A less confusing way to write the above is: );
fetch(url).then(function (response) { It is important to make sure the reviver function returns a useful value at the end of each iteration. If the reviver
const value = [Link]([Link]);
function returns undefined, no value or the execution falls off towards the end of the function, the property is
// We're done with the notion of "JSON" at this point. deleted from the object. Otherwise, the property is redefined to be the return value.
// You don't talk about JSON after parsing JSON.
});
Section 35.3: Serializing a value
Developers also tend to throw the phrase "JSON object" around a lot. This also leads to confusion. Because as A JavaScript value can be converted to a JSON string using the [Link] function.
mentioned above, a JSON string doesn't have to hold an object as a value. "JSON string" is a better term. Just like
"XML string" or "YAML string". You get a string, you parse it, and you end up with a value. [Link](value[, replacer[, space]])
Section 35.2: Parsing with a reviver function 1. value The value to convert to a JSON string.
[Link] – JavaScript® Notes for Professionals 235 [Link] – JavaScript® Notes for Professionals 236
2. replacer A function that alters the behaviour of the stringification process or an array of String and Number speed: [Link]
};
objects that serve as a whitelist for filtering the properties of the value object to be included in the JSON
};
string. If this value is null or is not provided, all properties of the object are included in the resulting JSON
string. [Link] = function(data) {
return new Car([Link], [Link]);
// replacer as a function };
function replacer (key, value) { Version ≥ 6
// Filtering out properties
class Car {
if (typeof value === "string") {
constructor(color, speed) {
return
[Link] = color;
}
[Link] = speed;
return value
this.id_ = [Link]();
}
}
var foo = { foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7 }
toJSON() {
[Link](foo, replacer)
return {
// -> '{"week": 45, "month": 7}'
$type: '[Link]',
// replacer as an array color: [Link],
[Link](foo, ['foundation', 'week', 'month']) speed: [Link]
// -> '{"foundation": "Mozilla", "week": 45, "month": 7}' };
// only the `foundation`, `week`, and `month` properties are kept }
3. space For readability, the number of spaces used for indentation may be specified as the third parameter. static fromJSON(data) {
return new Car([Link], [Link]);
[Link]({x: 1, y: 1}, null, 2) // 2 space characters will be used for indentation }
/* output: }
{
var userJson = [Link]({
'x': 1,
name: "John",
'y': 1
car: new Car('red', 'fast')
}
});
*/
[Link]({x: 1, y: 1}, null, '\t') var userObject = [Link](userJson, function reviver(key, value) {
/* output: return (value && value.$type === '[Link]') ? [Link](value) : value;
{ });
'x': 1,
'y': 1 This produces the following object:
}
*/
{
name: "John",
Section 35.4: Serializing and restoring class instances car: Car {
color: "red",
speed: "fast",
You can use a custom toJSON method and reviver function to transmit instances of your own class in JSON. If an
id_: 0.19349242527065402
object has a toJSON method, its result will be serialized instead of the object itself. }
}
Version < 6
function Car(color, speed) {
[Link] = color; Section 35.5: Serializing with a replacer function
[Link] = speed;
} A replacer function can be used to filter or transform values being serialized.
[Link] = function() {
const userRecords = [
return {
{name: "Joe", points: 14.9, level: 31.5},
$type: '[Link]',
{name: "Jane", points: 35.5, level: 74.4},
color: [Link],
{name: "Jacob", points: 18.5, level: 41.2},
[Link] – JavaScript® Notes for Professionals 237 [Link] – JavaScript® Notes for Professionals 238
];
{name: "Jessie", points: 15.1, level: 28.1},
Chapter 36: AJAX
// Remove names and round numbers to integers to anonymize records before sharing
AJAX stands for "Asynchronous JavaScript and XML". Although the name includes XML, JSON is more often used due
const anonymousReport = [Link](userRecords, (key, value) =>
key === 'name' to its simpler formatting and lower redundancy. AJAX allows the user to communicate with external resources
? undefined without reloading the webpage.
: (typeof value === 'number' ? [Link](value) : value)
);
Section 36.1: Sending and Receiving JSON Data via POST
This produces the following string: Version ≥ 6
'[{"points":14,"level":31},{"points":35,"level":74},{"points":18,"level":41},{"points":15,"level":2 Fetch request promises initially return Response objects. These will provide response header information, but they
8}]' don't directly include the response body, which may not have even loaded yet. Methods on the Response object
such as .json() can be used to wait for the response body to load, then parse it.
const array = [Link]('[1, 2, "c", "d", {"e": false}]'); const usersPromise = fetch('/api', {
[Link](array); // logs: [1, 2, "c", "d", {e: false}] method : 'POST',
body : [Link](requestData)
[Link] – JavaScript® Notes for Professionals 239 [Link] – JavaScript® Notes for Professionals 240
Now we're going to look at where to use these functions. [Link](message);
[Link] = 'red';
var request = new XMLHttpRequest();
[Link] = String(error);
});
Inside the onreadystatechange function you should have an if statement with condition: [Link] == 4
&& [Link] == 200.
Section 36.4: Using GET with parameters
If true: the request is finished and response is ready that's where we'll use removePreloader().
This function runs an AJAX call using GET allowing us to send parameters (object) to a file (string) and launch a
Else if false: the request is still in progress, in this case we'll run the function addPreloader() callback (function) when the request has been ended.
Version ≥ 6
Here's how we use it:
View live results on HyperWeb.
const url =
ajax('[Link]', {type:"Volvo", model:"300", color:"purple"}, function(response) {
'[Link] +
// add here the code to be executed when data comes back to this page
'&tagged=javascript&sort=month&filter=unsafe&key=gik4BOCMC7J9doavgYteRw((';
// for example [Link](response) will show the AJAX response in console
});
fetch(url).then(response => [Link]()).then(data => {
if (data.error_message) {
throw new Error(data.error_message); And the following shows how to retrieve the url parameters in [Link]:
}
if(isset($_REQUEST['type'], $_REQUEST['model'], $_REQUEST['color'])) {
const list = [Link]('ol'); // they are set, we can use them !
[Link](list); $response = 'The color of your car is ' . $_REQUEST['color'] . '. ';
$response .= 'It is a ' . $_REQUEST['type'] . ' model ' . $_REQUEST['model'] . '!';
for (const {title, link} of [Link]) { echo $response;
const entry = [Link]('li'); }
const hyperlink = [Link]('a');
[Link](hyperlink);
If you had [Link](response) in callback function the result in console would have been:
[Link](entry);
[Link] = title;
The color of your car is purple. It is a Volvo model 300!
[Link] = link;
}
}).then(null, error => {
const message = [Link]('pre');
[Link] – JavaScript® Notes for Professionals 241 [Link] – JavaScript® Notes for Professionals 242
Section 36.5: Check if a file exists via a HEAD request Chapter 37: Enumerations
This function executes an AJAX request using the HEAD method allowing us to check whether a file exists in the
directory given as an argument. It also enables us to launch a callback for each case (success, failure). Section 37.1: Enum definition using [Link]()
Version ≥ 5.1
function fileExists(dir, successCallback, errorCallback) {
var xhttp = new XMLHttpRequest;
JavaScript does not directly support enumerators but the functionality of an enum can be mimicked.
/* Check the status code of the request */
[Link] = function() { // Prevent the enum from being changed
return ([Link] !== 404) ? successCallback : errorCallback; const TestEnum = [Link]({
}; One:1,
Two:2,
/* Open and send the request */ Three:3
[Link]('head', dir, false); });
[Link](); // Define a variable with a value from the enum
}; var x = [Link];
// Prints a value according to the variable's enum value
switch(x) {
Section 36.6: Using GET and no parameters case [Link]:
[Link]("111");
var xhttp = new XMLHttpRequest(); break;
[Link] = function () {
if ([Link] === [Link] && [Link] === 200) { case [Link]:
//parse the response in [Link]; [Link]("222");
} }
};
[Link]("GET", "ajax_info.txt", true); The above enumeration definition, can also be written as follows:
[Link]();
Version ≥ 6 var TestEnum = { One: 1, Two: 2, Three: 3 }
[Link](TestEnum);
The fetch API is a newer promise-based way to make asynchronous HTTP requests.
After that you can define a variable and print like before.
fetch('/').then(response => [Link]()).then(text => {
[Link]("The home page is " + [Link] + " characters long.");
});
Section 37.2: Alternate definition
Section 36.7: Listening to AJAX events at a global level The [Link]() method is available since version 5.1. For older versions, you can use the following code (note
that it also works in versions 5.1 and later):
// Store a reference to the native method
let open = [Link]; var ColorsEnum = {
WHITE: 0,
// Overwrite the native method GRAY: 1,
[Link] = function() { BLACK: 2
// Assign an event listener }
[Link]("load", event => [Link](XHR), false); // Define a variable with a value from the enum
// Call the stored reference to the native method var currentColor = [Link];
[Link](this, arguments);
};
Section 37.3: Printing an enum variable
After defining an enum using any of the above ways and setting a variable, you can print both the variable's value
as well as the corresponding name from the enum for the value. Here's an example:
[Link] – JavaScript® Notes for Professionals 243 [Link] – JavaScript® Notes for Professionals 244
if(color == [Link]) { "One",
[Link](color); // This will print "2" "Two",
var ce = ColorsEnum; "Three"
for (var name in ce) { ];
if (ce[name] == [Link]) enumObj = {};
[Link](name); // This will print "BLACK" [Link]((item, index)=>enumObj[item] = index + 1);
}
} // Do not allow the object to be changed
[Link](enumObj);
return enumObj;
Section 37.4: Implementing Enums Using Symbols }();
As ES6 introduced Symbols, which are both unique and immutable primitive values that may be used as the key [Link]([Link]); // 1 will be logged
of an Object property, instead of using strings as possible values for an enum, it's possible to use symbols.
var x = [Link];
// Simple symbol
switch(x) {
const newSymbol = Symbol();
case [Link]:
typeof newSymbol === 'symbol' // true
[Link]("111");
break;
// A symbol with a label
const anotherSymbol = Symbol("label");
case [Link]:
[Link]("222"); // 222 will be logged
// Each symbol is unique
break;
const yetAnotherSymbol = Symbol("label");
}
yetAnotherSymbol === anotherSymbol; // false
function describe(kingdom) {
switch(kingdom) {
case Regnum_Animale:
return "Animal kingdom";
case Regnum_Vegetabile:
return "Vegetable kingdom";
case Regnum_Lapideum:
return "Mineral kingdom";
}
describe(Regnum_Vegetabile);
// Vegetable kingdom
The Symbols in ECMAScript 6 article covers this new primitive type more in detail.
This Example demonstrates how to automatically assign a value to each entry in an enum list. This will prevent two
enums from having the same value by mistake. NOTE: [Link] browser support
[Link] – JavaScript® Notes for Professionals 245 [Link] – JavaScript® Notes for Professionals 246
Chapter 38: Map This method returns true if the element existed and has been removed, otherwise false:
[Link](key);
Section 38.1: Creating a Map
Example:
A Map is a basic mapping of keys to values. Maps are different from objects in that their keys can be anything
(primitive values as well as objects), not just strings and symbols. Iteration over Maps is also always done in the const map = new Map([[1, 2], [3, 4]]);
order the items were inserted into the Map, whereas the order is undefined when iterating over keys in an object. [Link]([Link](1)); // true
[Link]([Link](2)); // false
To create a Map, use the Map constructor:
Section 38.3: Removing an element from a Map The callback function has three arguments: value, key, and the map object.
To remove an element from a map use the .delete() method. const map = new Map([[1, 2], [3, 4]]);
[Link]((value, key, theMap) => [Link](`key: ${key}, value: ${value}`));
[Link](key); // logs:
// key: 1, value: 2
// key: 3, value: 4
Example:
const map = new Map([[1, 2], [3, 4]]); Section 38.6: Getting and setting elements
[Link]([Link](3)); // 4
[Link](3); Use .get(key) to get value by key and .set(key, value) to assign a value to a key.
[Link]([Link](3)); // undefined
If the element with the specified key doesn't exist in the map, .get() returns undefined.
[Link] – JavaScript® Notes for Professionals 247 [Link] – JavaScript® Notes for Professionals 248
.set() method returns the map object, so you can chain .set() calls.
Chapter 39: Timestamps
const map = new Map();
[Link]([Link](1)); // undefined
[Link](1, 2).set(3, 4);
Section 39.1: High-resolution timestamps
[Link]([Link](1)); // 2
[Link]() returns a precise timestamp: The number of milliseconds, including microseconds, since the
current web page started to load.
Section 38.7: Getting the number of elements of a Map
More generally, it returns the time elapsed since the [Link] event.
To get the numbers of elements of a Map, use the .size property:
t = [Link]();
const map = new Map([[1, 2], [3, 4]]);
[Link]([Link]); // 2 For example, in a web browser's main context, [Link]() returns 6288.319 if the web page began to load
6288 milliseconds and 319 microseconds ago.
t = [Link]();
For example, [Link]() returns 1461069314 if it was called on 19 April 2016 at 12:35:14 GMT.
t = (new Date()).getTime();
Or, to provide a [Link]() function for use in older browsers, use this polyfill:
if (![Link]) {
[Link] = function now() {
return new Date().getTime();
};
}
[Link] – JavaScript® Notes for Professionals 249 [Link] – JavaScript® Notes for Professionals 250
Chapter 40: Unary Operators typeof "bla";
typeof (typeof 1); // typeof always returns a string
The unusual behavior of [Link] with the typeof operator is from its former usage to detect legacy browsers.
If the property to be deleted is an own non-configurable property (can't be deleted):
For more information, see Why is [Link] defined but typeof [Link] returns "undefined"?
false in non-strict mode.
Examples:
Throws an error in strict mode
// returns 'number'
typeof 3.14; Description
typeof Infinity;
typeof NaN; // "Not-a-Number" is a "number" The delete operator does not directly free memory. It can indirectly free memory if the operation means all
references to the property are gone.
// returns 'string'
typeof "";
delete works on an object's properties. If a property with the same name exists on the object's prototype chain, the
[Link] – JavaScript® Notes for Professionals 251 [Link] – JavaScript® Notes for Professionals 252
property will be inherited from the prototype. +"42" // 42
+true // 1
delete does not work on variables or function names.
+false // 0
+null // 0
Examples:
+undefined // NaN
// Deleting a property +NaN // NaN
foo = 1; // a global variable is a property of `window`: `[Link]` +"foo" // NaN
delete foo; // true +{} // NaN
[Link](foo); // Uncaught ReferenceError: foo is not defined +function(){} // NaN
// Deleting a variable
Note that attempting to convert an array can result in unexpected return values.
var foo = 1;
delete foo; // false In the background, arrays are first converted to their string representations:
[Link](foo); // 1 (Not deleted)
[].toString() === '';
// Deleting a function [1].toString() === '1';
function foo(){ }; [1, 2].toString() === '1,2';
delete foo; // false
[Link](foo); // function foo(){ } (Not deleted) The operator then attempts to convert those strings to numbers:
// Deleting a property
+[] // 0 ( === +'' )
var foo = { bar: "42" };
+[1] // 1 ( === +'1' )
delete [Link]; // true
+[1, 2] // NaN ( === +'1,2' )
[Link](foo); // Object { } (Deleted bar)
Description
The unary plus (+) precedes its operand and evaluates to its operand. It attempts to convert the operand to a
number, if it isn't already. The void operator is often used to obtain the undefined primitive value, by means of writing void 0 or void(0).
Note that void is an operator, not a function, so () is not required.
Syntax:
+expression Usually the result of a void expression and undefined can be used interchangeably.
Returns: However, in older versions of ECMAScript, [Link] could be assigned any value, and it is still possible to
use undefined as name for function parameters variables inside functions, thus disrupting other code that relies on
a Number.
the value of undefined.
Description void will always yield the true undefined value though.
The unary plus (+) operator is the fastest (and preferred) method of converting something into a number. void 0 is also commonly used in code minification as a shorter way of writing undefined. In addition, it's probably
safer as some other code could've tampered with [Link].
It can convert:
Examples:
string representations of integers (decimal or hexadecimal) and floats.
booleans: true, false. Returning undefined:
null
function foo(){
Values that can't be converted will evaluate to NaN. return void 0;
}
[Link](foo()); // undefined
Examples:
+42 // 42
[Link] – JavaScript® Notes for Professionals 253 [Link] – JavaScript® Notes for Professionals 254
Changing the value of undefined inside a certain scope: a Number.
(function(undefined){ Description
var str = 'foo';
[Link](str === undefined); // true The truth table for the NOT operation is:
})('foo');
a NOT a
01
Section 40.6: The unary negation operator (-) 10
The unary negation (-) precedes its operand and negates it, after trying to convert it to number. 1337 (base 10) = 0000010100111001 (base 2)
~1337 (base 10) = 1111101011000110 (base 2) = -1338 (base 10)
Syntax:
-expression A bitwise not on a number results in: -(x + 1).
Returns:
Examples:
a Number. value (base 10) value (base 2) return (base 2) return (base 10)
2 00000010 11111100 -3
Description 1 00000001 11111110 -2
0 00000000 11111111 -1
The unary negation (-) can convert the same types / values as the unary plus (+) operator can.
-1 11111111 00000000 0
-2 11111110 00000001 1
Values that can't be converted will evaluate to NaN (there is no -NaN).
-3 11111100 00000010 2
Examples:
-42 // -42 Section 40.8: The logical NOT operator (!)
-"42" // -42
-true // -1 The logical NOT (!) operator performs logical negation on an expression.
-false // -0
-null // -0
Syntax:
-undefined // NaN
-NaN // NaN !expression
-"foo" // NaN Returns:
-{} // NaN
-function(){} // NaN a Boolean.
Note that attempting to convert an array can result in unexpected return values. Description
In the background, arrays are first converted to their string representations:
The logical NOT (!) operator performs logical negation on an expression.
[].toString() === '';
Boolean values simply get inverted: !true === false and !false === true.
[1].toString() === '1';
[1, 2].toString() === '1,2'; Non-boolean values get converted to boolean values first, then are negated.
This means that a double logical NOT (!!) can be used to cast any value to a boolean:
The operator then attempts to convert those strings to numbers:
Returns:
These are all equal to !false:
[Link] – JavaScript® Notes for Professionals 255 [Link] – JavaScript® Notes for Professionals 256
!0 === !new Boolean(0);
!'' === !new Boolean(''); Chapter 41: Generators
!NaN === !new Boolean(NaN);
!null === !new Boolean(null); Generator functions (defined by the function* keyword) run as coroutines, generating a series of values as they're
!undefined === !new Boolean(undefined);
requested through an iterator.
Examples:
!true // false Section 41.1: Generator Functions
!-1 // false
!"-1" // false A generator function is created with a function* declaration. When it is called, its body is not immediately executed.
!42 // false
Instead, it returns a generator object, which can be used to "step through" the function's execution.
!"42" // false
!"foo" // false
!"true" // false A yield expression inside the function body defines a point at which execution can suspend and resume.
!"false" // false
!{} // false function* nums() {
![] // false [Link]('starting'); // A
!function(){} // false yield 1; // B
[Link]('yielded 1'); // C
!false // true yield 2; // D
!null // true [Link]('yielded 2'); // E
!undefined // true yield 3; // F
!NaN // true [Link]('yielded 3'); // G
!0 // true }
!"" // true var generator = nums(); // Returns the iterator. No code in nums is executed
[Link] – JavaScript® Notes for Professionals 257 [Link] – JavaScript® Notes for Professionals 258
Section 41.2: Sending Values to Generator function* range(n) {
for (let i = 0; i < n; ++i) {
It is possible to send a value to the generator by passing it to the next() method. yield i;
}
}
function* summer() {
let sum = 0, value;
// looping
while (true) {
for (let n of range(10)) {
// receive sent value
// n takes on the values 0, 1, ... 9
value = yield;
}
if (value === null) break;
// spread operator
// aggregate values
let nums = [...range(3)]; // [0, 1, 2]
sum += value;
let max = [Link](...range(100)); // 99
}
return sum;
} Here is another example of use generator to custom iterable object in ES6. Here anonymous generator function
let generator = summer(); function * used.
// proceed until the first "yield" expression, ignoring the "value" argument let user = {
[Link](); name: "sam", totalReplies: 17, isBlocked: false
};
// from this point on, the generator aggregates values until we send "null"
[Link](1); user[[Link]] = function *(){
[Link](10);
[Link](100); let properties = [Link](this);
let count = 0;
// close the generator and collect the result let isDone = false;
let sum = [Link](null).value; // 111
for(let p of properties){
};
From within a generator function, the control can be delegated to another generator function using yield*.
for(let p of user){
function* g1() { [Link]( p );
yield 2; }
yield 3;
yield 4;
} Section 41.5: Async flow with generators
function* g2() { Generators are functions which are able to pause and then resume execution. This allows to emulate async
yield 1; functions using external libraries, mainly q or co. Basically it allows to write functions that wait for async results in
yield* g1();
order to go on:
yield 5;
}
function someAsyncResult() {
var it = g2(); return [Link]('newValue')
}
[Link]([Link]()); // 1
[Link]([Link]()); // 2 [Link](function * () {
[Link]([Link]()); // 3 var result = yield someAsyncResult()
[Link]([Link]()); // 4 [Link](result) // 'newValue'
[Link]([Link]()); // 5 })
[Link]([Link]()); // undefined
This allows to write async code as if it were synchronous. Moreover, try and catch work over several async blocks. If
Section 41.4: Iteration the promise is rejected, the error is caught by the next catch:
A generator is iterable. It can be looped over with a for...of statement, and used in other constructs which depend function asyncError() {
return new Promise(function (resolve, reject) {
on the iteration protocol.
setTimeout(function () {
[Link] – JavaScript® Notes for Professionals 259 [Link] – JavaScript® Notes for Professionals 260
reject(new Error('Something went wrong')) Generators are widely used with spawn (from taskJS or co) function, where the function takes in a generator and
}, 100)
allows us to write asynchronous code in a synchronous fashion. This does NOT mean that async code is converted
})
}
to sync code / executed synchronously. It means that we can write code that looks like sync but internally it is still
async.
[Link](function * () {
try {
var result = yield asyncError() Sync is BLOCKING; Async is WAITING. Writing code that blocks is easy. When PULLing, value appears in
} catch (e) { the assignment position. When PUSHing, value appears in the argument position of the callback.
[Link](e) // Something went wrong
}
}) When you use iterators, you PULL the value from the producer. When you use callbacks, the producer PUSHes the
value to the argument position of the callback.
Using co would work exactly the same but with co(function * (){...}) instead of [Link]
var i = [Link]() // PULL
Section 41.6: Iterator-Observer interface dosomething(..., v => {...}) // PUSH
A generator is a combination of two things - an Iterator and an Observer. Here, you pull the value from [Link]() and in the second, v => {...} is the callback and a value is PUSHed into the
argument position v of the callback function.
Iterator
Using this pull-push mechanism, we can write async programming like this,
An iterator is something when invoked returns an iterable. An iterable is something you can iterate upon. From
ES6/ES2015 onwards, all collections (Array, Map, Set, WeakMap, WeakSet) conform to the Iterable contract. let delay = t => new Promise(r => setTimeout(r, t));
spawn(function*() {
// wait for 100 ms and send 1
A generator(iterator) is a producer. In iteration the consumer PULLs the value from the producer. let x = yield delay(100).then(() => 1);
[Link](x); // 1
Whenever you call [Link](), you're essentially pull-ing value from the Iterator and pause the execution at yield. So, looking at the above code, we are writing async code that looks like it's blocking (the yield statements wait for
The next time you call [Link](), the execution resumes from the previously paused state. 100ms and then continue execution), but it's actually waiting. The pause and resume property of generator allows
us to do this amazing trick.
Observer
How does it work ?
A generator is also an observer using which you can send some values back into the generator.
The spawn function uses yield promise to PULL the promise state from the generator, waits till the promise is
function *gen() { resolved, and PUSHes the resolved value back to the generator so it can consume it.
[Link]('<br>observer:', yield 1);
} Use it now
var a = gen();
var i = [Link](); So, with generators and spawn function, you can clean up all your async code in NodeJS to look and feel like it's
while(![Link]) { synchronous. This will make debugging easy. Also the code will look neat.
[Link]('<br>iterator:', [Link]);
i = [Link](100);
This feature is coming to future versions of JavaScript - as async...await. But you can use them today in
}
ES2015/ES6 using the spawn function defined in the libraries - taskjs, co, or bluebird
Here you can see that yield 1 is used like an expression which evaluates to some value. The value it evaluates to is
the value sent as an argument to the [Link] function call.
So, for the first time [Link] will be the first value yielded (1), and when continuing the iteration to the next state,
we send a value back to the generator using [Link](100).
[Link] – JavaScript® Notes for Professionals 261 [Link] – JavaScript® Notes for Professionals 262
Chapter 42: Promises [Link](value => {
// Work has completed successfully,
// promise has been fulfilled with "value"
Section 42.1: Introduction }).catch(reason => {
// Something went wrong,
// promise has been rejected with "reason"
A Promise object represents an operation which has produced or will eventually produce a value. Promises provide a
});
robust way to wrap the (possibly pending) result of asynchronous work, mitigating the problem of deeply nested
callbacks (known as "callback hell"). Note: Calling [Link](...) and [Link](...) on the same promise might result in an Uncaught
exception in Promise if an error occurs, either while executing the promise or inside one of the callbacks, so the
States and control flow
preferred way would be to attach the next listener on the promise returned by the previous then / catch.
A promise can be in one of three states:
Alternatively, both callbacks can be attached in a single call to then:
pending — The underlying operation has not yet completed, and the promise is pending fulfillment.
[Link](onFulfilled, onRejected);
fulfilled — The operation has finished, and the promise is fulfilled with a value. This is analogous to returning a
value from a synchronous function.
Attaching callbacks to a promise that has already been settled will immediately place them in the microtask queue,
rejected — An error has occurred during the operation, and the promise is rejected with a reason. This is
and they will be invoked "as soon as possible" (i.e. immediately after the currently executing script). It is not
analogous to throwing an error in a synchronous function.
necessary to check the state of the promise before attaching callbacks, unlike with many other event-emitting
A promise is said to be settled (or resolved) when it is either fulfilled or rejected. Once a promise is settled, it implementations.
becomes immutable, and its state cannot change. The then and catch methods of a promise can be used to attach
Live demo
callbacks that execute when it is settled. These callbacks are invoked with the fulfillment value and rejection reason,
respectively.
Section 42.2: Promise chaining
The then method of a promise returns a new promise.
promise
// 5 seconds later
.then(() => 2)
// returning a value from a then callback will cause
// the new promise to resolve with this value
.then(value => { /* value === 2 */ });
Example Returning a Promise from a then callback will append it to the promise chain.
const promise = new Promise((resolve, reject) => {
// Perform some work (possibly asynchronous) function wait(millis) {
// ... return new Promise(resolve => setTimeout(resolve, millis));
}
if (/* Work has successfully finished and produced "value" */) {
resolve(value); const p = wait(5000).then(() => wait(4000)).then(() => wait(1000));
} else { [Link](() => { /* 10 seconds have passed */ });
// Something went wrong because of "reason"
// The reason is traditionally an Error object, although A catch allows a rejected promise to recover, similar to how catch in a try/catch statement works. Any chained
// this is not required or enforced.
then after a catch will execute its resolve handler using the value resolved from the catch.
let reason = new Error(message);
reject(reason);
const p = new Promise(resolve => {throw 'oh no'});
// Throwing an error also rejects the promise. [Link](() => 'oh yes').then([Link](console)); // outputs "oh yes"
throw reason;
} If there are no catch or reject handlers in the middle of the chain, a catch at the end will capture any rejection in
}); the chain:
The then and catch methods can be used to attach fulfillment and rejection callbacks: [Link](() => [Link]('oh yes'))
.then([Link](console)) // won't be called
[Link] – JavaScript® Notes for Professionals 263 [Link] – JavaScript® Notes for Professionals 264
.catch([Link](console)); // outputs "oh yes" .catch(reason => [Link](reason)); // outputs "Error!" after 6 seconds.
On certain occasions, you may want to "branch" the execution of the functions. You can do it by returning different Non-promise values in the iterable are "promisified".
promises from a function depending on the condition. Later in the code, you can merge all of these branches into
one to call other functions on them and/or to handle all errors in one place. [Link]([
resolve(1, 5000),
resolve(2, 6000),
promise
{ hello: 3 }
.then(result => {
])
if ([Link]) {
.then(values => [Link](values)); // outputs "[1, 2, { hello: 3 }]" after 6 seconds
return handlerFn1()
.then(handlerFn2);
} else if (result.condition2) { Destructuring assignment can help to retrieve results from multiple promises.
return handlerFn3()
.then(handlerFn4); [Link]([
} else { resolve(1, 5000),
throw new Error("Invalid result"); resolve(2, 6000),
} resolve(3, 7000)
}) ])
.then(handlerFn5) .then(([result1, result2, result3]) => {
.catch(err => { [Link](result1);
[Link](err); [Link](result2);
}); [Link](result3);
});
Thus, the execution order of the functions looks like:
The single catch will get the error on whichever branch it may occur.
the "then" reduction, which builds a chain that continues as long as the chain experiences success.
the "catch" reduction, which builds a chain that continues as long as the chain experiences error.
Section 42.3: Waiting for multiple concurrent promises
The "then" reduction
The [Link]() static method accepts an iterable (e.g. an Array) of promises and returns a new promise, which
resolves when all promises in the iterable have resolved, or rejects if at least one of the promises in the iterable This variant of the pattern builds a .then() chain, and might be used for chaining animations, or making a
have rejected. sequence of dependent HTTP requests.
// wait "millis" ms, then resolve with "value" [1, 3, 5, 7, 9].reduce((seq, n) => {
function resolve(value, milliseconds) { return [Link](() => {
return new Promise(resolve => setTimeout(() => resolve(value), milliseconds)); [Link](n);
} return new Promise(res => setTimeout(res, 1000));
});
// wait "millis" ms, then reject with "reason" }, [Link]()).then(
function reject(reason, milliseconds) { () => [Link]('done'),
return new Promise((_, reject) => setTimeout(() => reject(reason), milliseconds)); (e) => [Link](e)
} );
// will log 1, 3, 5, 7, 9, 'done' in 1s intervals
[Link]([
resolve(1, 5000), Explanation:
resolve(2, 6000),
resolve(3, 7000)
1. We call .reduce() on a source array, and provide [Link]() as an initial value.
]).then(values => [Link](values)); // outputs "[1, 2, 3]" after 7 seconds.
2. Every element reduced will add a .then() to the initial value.
[Link]([ 3. reduce()'s product will be [Link]().then(...).then(...).
resolve(1, 5000), 4. We manually append a .then(successHandler, errorHandler) after the reduce, to execute successHandler
reject('Error!', 6000), once all the previous steps have resolved. If any step was to fail, then errorHandler would execute.
resolve(2, 7000)
]).then(values => [Link](values)) // does not output anything
[Link] – JavaScript® Notes for Professionals 265 [Link] – JavaScript® Notes for Professionals 266
Note: The "then" reduction is a sequential counterpart of [Link](). [Link]([
reject(new Error('bad things!'), 1000),
The "catch" reduction resolve(2, 2000)
])
.then(value => [Link](value)) // does not output anything
This variant of the pattern builds a .catch() chain and might be used for sequentially probing a set of web servers
.catch(error => [Link]([Link])); // outputs "bad things!" after 1 second
for some mirrored resource until a working server is found.
var working_resource = 5; // one of the values from the source array Section 42.6: "Promisifying" functions with callbacks
[1, 3, 5, 7, 9].reduce((seq, n) => {
return [Link](() => { Given a function that accepts a Node-style callback,
[Link](n);
if(n === working_resource) { // 5 is working fooFn(options, function callback(err, result) { ... });
return new Promise((resolve, reject) => setTimeout(() => resolve(n), 1000));
} else { // all other values are not working
return new Promise((resolve, reject) => setTimeout(reject, 1000)); you can promisify it (convert it to a promise-based function) like this:
}
}); function promiseFooFn(options) {
}, [Link]()).then( return new Promise((resolve, reject) =>
(n) => [Link]('success at: ' + n), fooFn(options, (err, result) =>
() => [Link]('total failure') // If there's an error, reject; otherwise resolve
); err ? reject(err) : resolve(result)
// will log 1, 3, 5, 'success at 5' at 1s intervals )
);
}
Explanation:
1. We call .reduce() on a source array, and provide [Link]() as an initial value. This function can then be used as follows:
2. Every element reduced will add a .catch() to the initial value.
promiseFooFn(options).then(result => {
3. reduce()'s product will be [Link]().catch(...).catch(...).
// success!
4. We manually append .then(successHandler, errorHandler) after the reduce, to execute successHandler
}).catch(err => {
once any of the previous steps has resolved. If all steps were to fail, then errorHandler would execute. // error!
});
Note: The "catch" reduction is a sequential counterpart of [Link]() (as implemented in [Link], but not
currently in native ECMAScript). In a more generic way, here's how to promisify any given callback-style function:
Section 42.5: Waiting for the first of multiple concurrent function promisify(func) {
promises return function(...args) {
return new Promise((resolve, reject) => {
func(...args, (err, result) => err ? reject(err) : resolve(result));
The [Link]() static method accepts an iterable of Promises and returns a new Promise which resolves or
});
rejects as soon as the first of the promises in the iterable has resolved or rejected. }
}
// wait "milliseconds" milliseconds, then resolve with "value"
function resolve(value, milliseconds) { This can be used like this:
return new Promise(resolve => setTimeout(() => resolve(value), milliseconds));
}
const fs = require('fs');
const promisedStat = promisify([Link](fs));
// wait "milliseconds" milliseconds, then reject with "reason"
function reject(reason, milliseconds) {
promisedStat('/foo/bar')
return new Promise((_, reject) => setTimeout(() => reject(reason), milliseconds));
.then(stat => [Link]('STATE', stat))
}
.catch(err => [Link]('ERROR', err));
[Link]([
resolve(1,
resolve(2,
5000),
3000),
Section 42.7: Error Handling
resolve(3, 1000)
Errors thrown from promises are handled by the second parameter (reject) passed to then or by the handler
])
.then(value => [Link](value)); // outputs "3" after 1 second. passed to catch:
throwErrorAsync()
[Link] – JavaScript® Notes for Professionals 267 [Link] – JavaScript® Notes for Professionals 268
.then(null, error => { /* handle error here */ }); throwErrorAsync()
// or .then(() => { /* will not be called */ })
throwErrorAsync() .catch(error => { /* handle error*/ });
.catch(error => { /* handle error here */ }); // or
throwErrorAsync()
.then(() => { /* will not be called */ }, error => { /* handle error*/ });
Chaining
If you have a promise chain then an error will cause resolve handlers to be skipped: Alternatively, subscribe to the unhandledrejection event to catch any unhandled rejected promises:
An error handler returns a new promise, allowing you to continue a promise chain. The promise returned by the
error handler is resolved with the value returned by the handler: The event argument contains information about the rejection. [Link] is the error object and [Link]
is the promise object that caused the event.
throwErrorAsync()
.catch(error => { /* handle error here */; return result; }) In Nodejs the rejectionhandled and unhandledrejection events are called rejectionHandled and
.then(result => { /* handle result here */ }); unhandledRejection on process, respectively, and have a different signature:
You can let an error cascade down a promise chain by re-throwing the error: [Link]('rejectionHandled', (reason, promise) => {});
[Link]('unhandledRejection', (reason, promise) => {});
throwErrorAsync()
.catch(error => { The reason argument is the error object and the promise argument is a reference to the promise object that caused
/* handle error from throwErrorAsync() */ the event to fire.
throw error;
}) Usage of these unhandledrejection and rejectionhandled events should be considered for debugging purposes
.then(() => { /* will not be called if there's an error */ })
only. Typically, all promises should handle their rejections.
.catch(error => { /* will get called with the same error */ });
Note: Currently, only Chrome 49+ and [Link] support unhandledrejection and rejectionhandled events.
It is possible to throw an exception that is not handled by the promise by wrapping the throw statement inside a
setTimeout callback: Caveats
Chaining with fulfill and reject
new Promise((resolve, reject) => {
setTimeout(() => { throw new Error(); }); The then(fulfill, reject) function (with both parameters not null) has unique and complex behavior, and
});
shouldn't be used unless you know exactly how it works.
This works because promises cannot handle exceptions thrown asynchronously. The function works as expected if given null for one of the inputs:
Unhandled rejections
// the following calls are equivalent
[Link](fulfill, null)
An error will be silently ignored if a promise doesn't have a catch block or reject handler: [Link](fulfill)
To prevent this, always use a catch block: However, it adopts unique behavior when both inputs are given:
[Link] – JavaScript® Notes for Professionals 269 [Link] – JavaScript® Notes for Professionals 270
// the following calls are not equivalent! Instead of throwing, do as follows:
[Link](fulfill, reject)
[Link](fulfill).catch(reject) function foo(arg) {
if (arg === 'unexepectedValue') {
// the following calls are not equivalent! return [Link](new Error('UnexpectedValue'))
[Link](fulfill, reject) }
[Link](reject).then(fulfill)
return new Promise(resolve =>
The then(fulfill, reject) function looks like it is a shortcut for then(fulfill).catch(reject), but it is not, and setTimeout(() => resolve(arg), 1000)
)
will cause problems if used interchangeably. One such problem is that the reject handler does not handle errors
}
from the fulfill handler. Here is what will happen:
Wrap your function into a promise chain
[Link]() // previous promise is fulfilled
.then(() => { throw new Error(); }, // error in the fulfill handler Your throw statement will be properly caught when it is already inside a promise chain:
error => { /* this is not called! */ });
function foo(arg) {
return [Link]()
The above code will result in a rejected promise because the error is propagated. Compare it to the following code,
.then(() => {
which results in a fulfilled promise: if (arg === 'unexepectedValue') {
throw new Error('UnexpectedValue')
[Link]() // previous promise is fulfilled }
.then(() => { throw new Error(); }) // error in the fulfill handler
.catch(error => { /* handle error */ }); return new Promise(resolve =>
setTimeout(() => resolve(arg), 1000)
A similar problem exists when using then(fulfill, reject) interchangeably with catch(reject).then(fulfill), )
})
except with propagating fulfilled promises instead of rejected promises.
}
If such function is used in the middle of a promise chain, then apparently there is no problem: The synchronous and asynchronous branches of the above code can be reconciled by redundantly wrapping the
synchronous operation inside a promise:
makeSomethingAsync().
.then(() => foo('unexpectedValue')) var fetch = result
.catch(err => [Link](err)) // <-- Error: UnexpectedValue will be caught here ? [Link](result)
: fetchResult();
However, if the same function is called outside of a promise chain, then the error will not be handled by it and will
[Link](processResult);
be thrown to the application:
When caching the result of an asynchronous call, it is preferable to cache the promise rather than the result itself.
foo('unexpectedValue') // <-- error will be thrown, so the application will crash
.then(makeSomethingAsync) // <-- will not run
This ensures that only one asynchronous operation is required to resolve multiple parallel requests.
.catch(err => [Link](err)) // <-- will not catch
Care should be taken to invalidate cached values when error conditions are encountered.
[Link] – JavaScript® Notes for Professionals 271 [Link] – JavaScript® Notes for Professionals 272
var cachedPromise; // immediately invoked
// value === 2
function fetchResult() { });
if (!cachedPromise) {
cachedPromise = fetch(planets)
The [Link] static method returns a promise which immediately rejects with the given reason.
.catch(function (e) {
// Invalidate the current result to retry on the next fetch
cachedPromise = null; let rejected = [Link]("Oops!");
// re-raise the error to propagate it to callers [Link](reason => {
throw e; // immediately invoked
}); // reason === "Oops!"
} });
return cachedPromise;
}
Section 42.11: Using ES2017 async/await
Section 42.9: Delay function call The same example above, Image loading, can be written using async functions. This also allows using the common
try/catch method for exception handling.
The setTimeout() method calls a function or evaluates an expression after a specified number of milliseconds. It is
also a trivial way to achieve an asynchronous operation. Note: as of April 2017, the current releases of all browsers but Internet Explorer supports async functions.
In this example calling the wait function resolves the promise after the time specified as first argument: function loadImage(url) {
return new Promise((resolve, reject) => {
function wait(ms) { const img = new Image();
return new Promise(resolve => setTimeout(resolve, ms)); [Link]('load', () => resolve(img));
} [Link]('error', () => {
reject(new Error(`Failed to load ${url}`));
wait(5000).then(() => { });
[Link]('5 seconds have passed...'); [Link] = url;
}); });
}
The [Link] static method can be used to wrap values into promises. // load /[Link] and append to #image-holder, otherwise throw error
try {
let img = await loadImage('[Link]
let resolved = [Link](2);
[Link]('image-holder').appendChild(img);
[Link](value => {
}
// immediately invoked
catch (error) {
// value === 2
[Link](error);
});
}
In fact, value can be any "thenable" (object defining a then method that works sufficiently like a spec-compliant You would usually use this functionality for cleanup:
promise). This allows [Link] to convert untrusted 3rd-party objects into trusted 1st-party Promises.
var loadingData = true;
let resolved = [Link]({
then(onResolved) { fetch('/data')
onResolved(2); .then(result => processData([Link]))
} .catch(error => [Link](error))
}); .finally(() => {
[Link](value => { loadingData = false;
[Link] – JavaScript® Notes for Professionals 273 [Link] – JavaScript® Notes for Professionals 274
}); return new Promise(function(resolve, reject) {
let request = new XMLHttpRequest();
[Link]('GET', path);
It is important to note that the finally callback doesn't affect the state of the promise. It doesn't matter what value
[Link] = resolve;
it returns, the promise stays in the fulfilled/rejected state that it had before. So in the example above the promise [Link] = reject;
will be resolved with the return value of processData([Link]) even though the finally callback returned [Link]();
undefined. });
};
With the standardization process still being in progress, your promises implementation most likely won't support
finally callbacks out of the box. For synchronous callbacks you can add this functionality with a polyfill however: More robust error handling can be done using the following onload and onerror functions.
It is possible to effectively apply a function (cb) which returns a promise to each element of an array, with each [Link] = function() {
element waiting to be processed until the previous element is processed. reject({
'status': [Link],
'message': [Link]
function promiseForEach(arr, cb) {
});
var i = 0;
};
This can be helpful if you need to efficiently process thousands of items, one at a time. Using a regular for loop to
create the promises will create them all at once and take up a significant amount of RAM.
[Link] – JavaScript® Notes for Professionals 275 [Link] – JavaScript® Notes for Professionals 276
Chapter 43: Set [Link](some_val);
This function will return true if the value existed in the set and was removed, or false otherwise.
Parameter Details
If an iterable object is passed, all of its elements will be added to the new Set. null is treated as
iterable
undefined. Section 43.4: Checking if a value exist in a set
value The value of the element to add to the Set object.
To check if a given value exists in a set, use .has() method:
callback Function to execute for each element.
thisArg Optional. Value to use as this when executing callback. [Link](someVal);
The Set object lets you store unique values of any type, whether primitive values or object references. Will return true if someVal appears in the set, false otherwise.
Set objects are collections of values. You can iterate through the elements of a set in insertion order. A value in the
Set may only occur ONCE; it is unique in the Set's collection. Distinct values are discriminated using the
Section 43.5: Clearing a Set
SameValueZero comparison algorithm. You can remove all the elements in a set using the .clear() method:
This property, unlike [Link], is read-only, which means that you can't change it by assigning
const mySet = new Set();
something to it:
Or you can create a set from any iterable object to give it starting values:
[Link] = 5;
[Link]; // 4
const arr = [1,2,3,4,4,5];
const mySet = new Set(arr);
In strict mode it even throws an error:
In the example above the set content would be {1, 2, 3, 4, 5}. Note that the value 4 appears only once, unlike in
TypeError: Cannot set property size of #<Set> which has only a getter
the original array used to create it.
Section 43.2: Adding a value to a Set Section 43.7: Converting Sets to arrays
To add a value to a Set, use the .add() method: Sometimes you may need to convert a Set to an array, for example to be able to use [Link] methods like
.filter(). In order to do so, use [Link]() or destructuring-assignment:
[Link](5);
var mySet = new Set([1, 2, 3, 4]);
//use [Link]
If the value already exist in the set it will not be added again, as Sets contain unique values.
const myArray = [Link](mySet);
//use destructuring-assignment
Note that the .add() method returns the set itself, so you can chain add calls together: const myArray = [...mySet];
[Link](1).add(2).add(3);
Now you can filter the array to contain only even numbers and convert it back to Set using Set constructor:
Section 43.3: Removing value from a set mySet = new Set([Link](x => x % 2 === 0));
To remove a value from a set, use .delete() method: mySet now contains only even numbers:
[Link] – JavaScript® Notes for Professionals 277 [Link] – JavaScript® Notes for Professionals 278
[Link](mySet); // Set {2, 4}
Chapter 44: Modals - Prompts
Section 43.8: Intersection and dierence in Sets Section 44.1: About User Prompts
There are no build-in methods for intersection and difference in Sets, but you can still achieve that but converting
User Prompts are methods part of the Web Application API used to invoke Browser modals requesting a user action
them to arrays, filtering, and converting back to Sets:
such as confirmation or input.
alert("Hello World");
Section 43.9: Iterating Sets
More information below in "Using alert()".
You can use a simple for-of loop to iterate a Set:
boolean = [Link](message)
const mySet = new Set([1, 2, 3]);
Show a modal popup with the provided message.
for (const value of mySet) { Provides [OK] and [Cancel] buttons which will respond with a boolean value true / false respectively.
[Link](value); // logs 1, 2 and 3
}
confirm("Delete this comment?");
When iterating over a set, it will always return values in the order they were first added to the set. For example:
result = [Link](message, defaultValue)
const set = new Set([4, 5, 6])
[Link](10)
Show a modal popup with the provided message and an input field with an optional pre-filled value.
[Link](5) //5 already exists in the set
[Link](set) //[4, 5, 6, 10]
Returns as result the user provided input value.
print();
<script>
// Persistent Prompt modal
var userName;
while(!userName) {
userName = prompt("Enter your name", "");
if(!userName) {
alert("Please, we need your name!");
} else {
[Link] – JavaScript® Notes for Professionals 279 [Link] – JavaScript® Notes for Professionals 280
[Link]("name").innerHTML = userName;
}
}
</script>
jsFiddle demo
<div id="post-102">
Do not overuse this method, as it prevents the user from accessing other parts of the page until the box is closed.
<p>I like Confirm modals.</p> Also it stops the further code execution, until user clicks OK . (in particular, the timers which were set with
<a data-deletepost="post-102">Delete post</a> setInterval() or setTimeout() don't tick either). The alert box only works in browsers, and its design cannot be
</div> modified.
<div id="post-103">
<p>That's way too cool!</p> Parameter Description
<a data-deletepost="post-103">Delete post</a>
Required. Specifies the text to display in the alert box, or an object converted into a string and
</div> message
displayed.
// Collect all buttons
var deleteBtn = [Link]("[data-deletepost]"); Return value
Syntax
alert("Hello world!");
// Or, alternatively...
[Link]("Hello world!");
Produces
[Link] – JavaScript® Notes for Professionals 281 [Link] – JavaScript® Notes for Professionals 282
Chapter 45: execCommand and Section 45.1: Listening to Changes of contenteditable
contenteditable Events that work with most form elements (e.g., change, keydown, keyup, keypress) do not work with
contenteditable.
commandId value
Instead, you can listen to changes of contenteditable contents with the input event. Assuming
⋮ Inline formatting commands
contenteditableHtmlElement is a JS DOM object that is contenteditable:
backColor Color value String
bold [Link]("input", function() {
createLink URL String [Link]("contenteditable element changed");
});
fontName Font family name
fontSize "1", "2", "3", "4", "5", "6", "7"
foreColor Color value String Section 45.2: Getting started
strikeThrough The HTML attribute contenteditable provides a simple way to turn a HTML element into a user-editable area
superscript
unlink <div contenteditable>You can <b>edit</b> me!</div>
⋮ Block formatting commands
delete Native Rich-Text editing
formatBlock "address", "dd", "div", "dt", "h1", "h2", "h3", "h4", "h5", "h6", "p", "pre"
Using JavaScript and execCommandW3C you can additionally pass more editing features to the currently focused
forwardDelete contenteditable element (specifically at the caret position or selection).
insertHorizontalRule
insertHTML HTML String The execCommand function method accepts 3 arguments
insertUnorderedList value String If a command expects a command-related String value, otherwise "".
(see: Parameters→value)
justifyCenter
justifyFull Example using the "bold" command and "formatBlock" (where a value is expected):
justifyLeft
justifyRight [Link]("bold", false, ""); // Make selected text bold
[Link]("formatBlock", false, "H2"); // Make selected text Block-level <h2>
outdent
⋮ Clipboard commands
Quick Start Example:
copy Currently Selected String
cut Currently Selected String <button data-edit="bold"><b>B</b></button>
paste <button data-edit="italic"><i>I</i></button>
<button data-edit="formatBlock:p">P</button>
⋮ Miscellaneous commands
<button data-edit="formatBlock:H1">H1</button>
defaultParagraphSeparator <button data-edit="insertUnorderedList">UL</button>
redo <button data-edit="justifyLeft">⇤</button>
<button data-edit="justifyRight">⇥</button>
selectAll <button data-edit="removeFormat">×</button>
styleWithCSS
undo <div contenteditable><p>Edit me!</p></div>
useCSS <script>
[].[Link]([Link]("[data-edit]"), function(btn) {
[Link]("click", edit, false);
});
[Link] – JavaScript® Notes for Professionals 283 [Link] – JavaScript® Notes for Professionals 284
function edit(event) { [Link]('underline', false, null); // toggles underline
[Link]();
var cmd_val = [Link](":");
[Link](cmd_val[0], false, cmd_val[1]);
}
<script>
jsFiddle demo
Basic Rich-Text editor example (Modern browsers)
Final thoughts
Even being present for a long time (IE6), implementations and behaviors of execCommand vary from browser to
browser making "building a Fully-featured and cross-browser compatible WYSIWYG editor" a hard task to any
experienced JavaScript developer.
Even if not yet fully standardized you can expect pretty decent results on the newer browsers like Chrome, Firefox,
Edge. If you need better support for other browsers and more features like HTMLTable editing etc. a rule of thumbs
is to look for an already existent and robust Rich-Text editor.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<textarea id="content"></textarea>
<input type="button" id="copyID" value="Copy" />
<script type="text/javascript">
var button = [Link]("copyID"),
input = [Link]("content");
[Link]("click", function(event) {
[Link]();
[Link]();
[Link]("copy");
});
</script>
</body>
</html>
Additionally, developers can use JavaScript to apply formatting to the current selection (highlighted text).
[Link] – JavaScript® Notes for Professionals 285 [Link] – JavaScript® Notes for Professionals 286
Chapter 46: History [Link](number|URL)
This example inserts a new record into the history, address bar, and page title.
Note this is different from the [Link](). Which updates the current history entry, rather than
adding a new one.
This method modifies the current history entry instead of creating a new one. Mainly used when we want to update
URL of the current history entry.
This example replaces the current history, address bar, and page title.
Note this is different from the [Link](). Which inserts a new history entry, rather than replacing the
current one.
The go() method loads a specific URL from the history list. The parameter can either be a number which goes to the
URL within the specific position (-1 goes back one page, 1 goes forward one page), or a string. The string must be a
partial or full URL, and the function will go to the first URL that matches the string.
Syntax
[Link] – JavaScript® Notes for Professionals 287 [Link] – JavaScript® Notes for Professionals 288
Chapter 47: Navigator Object Chapter 48: BOM (Browser Object Model)
Section 47.1: Get some basic browser data and return it as a Section 48.1: Introduction
JSON object
The BOM (Browser Object Model) contains objects that represent the current browser window and components;
The following function can be used to get some basic information about the current browser and return it in JSON objects that model things like history, device's screen, etc
format.
The topmost object in BOM is the window object, which represents the current browser window or tab.
function getBrowserInfo() {
var
json = "[{",
Property Description
[Link] Whether the window has been closed
[Link] – JavaScript® Notes for Professionals 289 [Link] – JavaScript® Notes for Professionals 290
[Link]
[Link]
Number of <iframe> elements in window
Gets or sets the name of the window
Chapter 49: The Event Loop
[Link] Height of window
[Link] Width of window
Section 49.1: The event loop in a web browser
[Link] X-coordinate of pointer, relative to top left corner of screen The vast majority of modern JavaScript environments work according to an event loop. This is a common concept in
[Link] Y-coordinate of pointer, relative to top left corner of screen computer programming which essentially means that your program continually waits for new things to happen,
[Link] Current URL of window object (or local file path) and when they do, reacts to them. The host environment calls into your program, spawning a "turn" or "tick" or
[Link] Reference to history object for browser window or tab. "task" in the event loop, which then runs to completion. When that turn has finished, the host environment waits for
[Link] Reference to screen object something else to happen, before all this starts.
[Link]ffset Distance document has been scrolled horizontally
A simple example of this is in the browser. Consider the following example:
[Link]ffset Distance document has been scrolled vertically
<!DOCTYPE html>
Section 48.3: Window Object Methods <title>Event loop example</title>
<script>
The most important object in the Browser Object Model is the window object. It helps in accessing information
[Link]("this a script entry point");
about the browser and its components. To access these features, it has various methods and properties.
[Link] = () => {
Method Description [Link]("onclick");
[Link]() Creates dialog box with message and an OK button };
[Link]() Remove focus from window
setTimeout(() => {
[Link]() Closes a browser window [Link]("setTimeout callback log 1");
[Link]firm() Creates dialog box with message, an OK button and a cancel button [Link]("setTimeout callback log 2");
[Link]() Get CSS styles applied to an element }, 100);
</script>
[Link](x,y) Move a window's left and top edge to supplied coordinates
[Link]() Opens new browser window with URL specified as parameter In this example, the host environment is the web browser.
[Link]() Tells browser that user wants to print contents of current page
[Link]() Creates dialog box for retrieving user input 1. The HTML parser will first execute the <script>. It will run to completion.
2. The call to setTimeout tells the browser that, after 100 milliseconds, it should enqueue a task to perform the
[Link]() Scrolls the document by the specified number of pixels
given action.
[Link]() Scrolls the document to the specified coordinates
3. In the meantime, the event loop is then responsible for continually checking if there's something else to do:
[Link]() Do something repeatedly at specified intervals
for example, rendering the web page.
[Link]() Do something after a specified amount of time 4. After 100 milliseconds, if the event loop is not busy for some other reason, it will see the task that
[Link]() Stop window from loading setTimeout enqueues, and run the function, logging those two statements.
5. At any time, if someone clicks on the body, the browser will post a task to the event loop to run the click
handler function. The event loop, as it goes around continually checking what to do, will see this, and run that
function.
You can see how in this example there are several different types of entry points into JavaScript code, which the
event loop invokes:
Each turn of the event loop is responsible for many things; only some of them will invoke these JavaScript tasks. For
full details, see the HTML specification
One last thing: what do we mean by saying that each event loop task "runs to completion"? We mean that it is not
generally possible to interrupt a block of code that is queued to run as a task, and it is never possible to run code
interleaved with another block of code. For example, even if you clicked at the perfect time, you could never get the
[Link] – JavaScript® Notes for Professionals 291 [Link] – JavaScript® Notes for Professionals 292
above code to log "onclick" in between the two setTimeout callback log 1/2"s. This is due to the way the task-
posting works; it is cooperative and queue-based, instead of preemptive. Chapter 50: Strict mode
Section 49.2: Asynchronous operations and the event loop Section 50.1: For entire scripts
Many interesting operations in common JavaScript programming environments are asynchronous. For example, in Strict mode can be applied on entire scripts by placing the statement "use strict"; before any other statements.
the browser we see things like
"use strict";
// strict mode now applies for the rest of the script
[Link](() => {
[Link]("this happens later");
}, 100); Strict mode is only enabled in scripts where you define "use strict". You can combine scripts with and without
strict mode, because the strict state is not shared among different scripts.
and in [Link] we see things like
Version ≥ 6
function notStrict() {
// but not here
}
"use strict";
delete [Link]; // throws a TypeError
The above statement would simply be ignored if you don't use strict mode, however now you know why it does not
execute as expected.
function setAge() {
[Link] = 25; // No errors
}
function setAge() {
[Link] – JavaScript® Notes for Professionals 293 [Link] – JavaScript® Notes for Professionals 294
"use strict"; function strict_scope() {
[Link] = 25; // TypeError: can't define property "age": Object is not extensible "use strict";
} a = "bar"; // variable is global
}
In strict mode however, any access to an undeclared variable will throw a reference error: function foo(bar, bar) {} // No error. bar is set to the final argument when called
"use strict";
"use strict";
function foo(bar, bar) {}; // SyntaxError: duplicate formal argument bar
a = 12; // ReferenceError: a is not defined
[Link](a);
Section 50.6: Function scoping in strict mode
This is useful because JavaScript has a number of possible events that are sometimes unexpected. In non-strict-
mode, these events often lead developers to believe they are bugs or unexpected behavior, thus by enabling strict- In Strict Mode, functions declared in a local block are inaccessible outside the block.
mode, any errors that are thrown enforces them to know exactly what is being done.
"use strict";
{
f(); // 'hi'
"use strict";
function f() {[Link]('hi');}
// Assuming a global variable mistypedVariable exists
}
mistypedVaraible = 17; // this line throws a ReferenceError due to the
f(); // ReferenceError: f is not defined
// misspelling of variable
Scope-wise, function declarations in Strict Mode have the same kind of binding as let or const.
This code in strict mode displays one possible scenario: it throws a reference error which points to the assignment's
line number, allowing the developer to immediately detect the mistype in the variable's name.
Section 50.7: Behaviour of a function's arguments list
In non-strict-mode, besides the fact that no error is thrown and the assignment is successfully made, the
arguments object behave different in strict and non strict mode. In non-strict mode, the argument object will reflect
mistypedVaraible will be automatically declared in the global scope as a global variable. This implies that the
the changes in the value of the parameters which are present, however in strict mode any changes to the value of
developer needs to look up manually this specific assignment in the code.
the parameter will not be reflected in the argument object.
Furthermore, by forcing declaration of variables, the developer cannot accidentally declare global variables inside
functions. In non-strict-mode: function add(a, b){
[Link](arguments[0], arguments[1]); // Prints : 1,2
function foo() {
a = 5, b = 10;
a = "bar"; // variable is automatically declared in the global scope
}
[Link](arguments[0], arguments[1]); // Prints : 5,10
foo();
}
[Link](a); // >> bar
add(1, 2);
In strict mode, it is necessary to explicitly declare the variable:
For the above code, the arguments object is changed when we change the value of the parameters. However, for
function strict_scope() { strict mode, the same will not be reflected.
"use strict";
var a = "bar"; // variable is local
function add(a, b) {
}
'use strict';
strict_scope();
[Link](a); // >> "ReferenceError: a is not defined"
[Link](arguments[0], arguments[1]); // Prints : 1,2
The variable can also be declared outside and after a function, allowing it to be used, for instance, in the global a = 5, b = 10;
scope:
[Link](arguments[0], arguments[1]); // Prints : 1,2
[Link] – JavaScript® Notes for Professionals 295 [Link] – JavaScript® Notes for Professionals 296
} }
It's worth noting that, if any one of the parameters is undefined, and we try to change the value of the parameter in Destructuring
both strict-mode or non-strict mode the arguments object remains unchanged.
function a({ x }) {
"use strict";
Strict mode
}
add(1)
// 1, undefined
// 1, undefined
Non-Strict Mode
function add(a,b) {
[Link](arguments[0],arguments[1]);
a = 5, b = 10;
[Link](arguments[0],arguments[1]);
}
add();
// undefined,undefined
// undefined,undefined
add(1);
// 1, undefined
// 5, undefined
is invalid JavaScript and will throw a SyntaxError because you cannot use the directive "use strict" in a function
with Non-Simple Parameter list like the one above - default assignment x = 5
Default assignment
function a(x = 1) {
"use strict";
[Link] – JavaScript® Notes for Professionals 297 [Link] – JavaScript® Notes for Professionals 298
Chapter 51: Custom Elements Chapter 52: Data Manipulation
Parameter Details Section 52.1: Format numbers as money
name The name of the new custom element.
[Link] The name of the native element being extended, if any. Fast and short way to format value of type Number as money, e.g. 1234567.89 => "1,234,567.89":
[Link] The custom prototype to use for the custom element, if any.
var num = 1234567.89,
formatted;
Section 51.1: Extending Native Elements
formatted = [Link](2).replace(/\d(?=(\d{3})+\.)/g, '$&,'); // "1,234,567.89"
It's possible to extent native elements, but their descendants don't get to have their own tag names. Instead, the is
attribute is used to specify which subclass an element is supposed to use. For example, here's an extension of the More advanced variant with support of any number of decimals [0 .. n], variable size of number groups [0 .. x]
<img> element which logs a message to the console when it's loaded. and different delimiter types:
<initially-hidden for="2">Hello</initially-hidden> The following solution may extract file extensions from full path:
<initially-hidden for="5">World</initially-hidden>
function get_extension(path) {
var basename = [Link](/[\\/]/).pop(), // extract file name from full path ...
// (supports `\\` and `/` separators)
pos = [Link]('.'); // get last position of `.`
[Link] – JavaScript® Notes for Professionals 299 [Link] – JavaScript® Notes for Professionals 300
if (basename === '' || pos < 1)
return "";
// if file name is empty or ...
// `.` not found (-1) or comes first (0) Chapter 53: Binary Data
Section 53.1: Getting binary representation of an image file
return [Link](pos + 1); // extract extension ignoring `.`
}
We'll assume you know how to load a file using the File API.
Section 52.3: Set object property given its string name
// preliminary code to handle getting local file and finally printing to console
function assign(obj, prop, value) { // the results of our function ArrayBufferToBinary().
if (typeof prop === 'string') var file = // get handle to local file.
prop = [Link]('.'); var reader = new FileReader();
[Link] = function(event) {
if ([Link] > 1) { var data = [Link];
var e = [Link](); [Link](ArrayBufferToBinary(data));
assign(obj[e] = };
[Link](obj[e]) === '[object Object]' [Link](file); //gets an ArrayBuffer of the file
? obj[e]
: {},
Now we perform the actual conversion of the file data into 1's and 0's using a DataView:
prop,
value);
} else function ArrayBufferToBinary(buffer) {
obj[prop[0]] = value; // Convert an array buffer to a string bit-representation: 0 1 1 0 0 0...
} var dataView = new DataView(buffer);
var response = "", offset = (8/8);
var obj = {}, for(var i = 0; i < [Link]; i += offset) {
propName = '[Link]'; response += dataView.getInt8(i).toString(2);
}
assign(obj, propName, 'Value'); return response;
}
// obj == {
// foo : { DataViews let you read/write numeric data; getInt8 converts the data from the byte position - here 0, the value
// bar : {
passed in - in the ArrayBuffer to signed 8-bit integer representation, and toString(2) converts the 8-bit integer to
// foobar : 'Value'
// } binary representation format (i.e. a string of 1's and 0's).
// }
// } Files are saved as bytes. The 'magic' offset value is obtained by noting we are taking files stored as bytes i.e. as 8-bit
integers and reading it in 8-bit integer representation. If we were trying to read our byte-saved (i.e. 8 bits) files to
32-bit integers, we would note that 32/8 = 4 is the number of byte spaces, which is our byte offset value.
For this task, DataViews are overkill. They are typically used in cases where endianness or heterogeneity of data are
encountered (e.g. in reading PDF files, which have headers encoded in different bases and we would like to
meaningfully extract that value). Because we just want a textual representation, we do not care about
heterogeneity as there is never a need to
A much better - and shorter - solution can be found using an UInt8Array typed array, which treats the entire
ArrayBuffer as composed of unsigned 8-bit integers:
function ArrayBufferToBinary(buffer) {
var uint8 = new Uint8Array(buffer);
return [Link]((binary, uint8) => binary + [Link](2), "");
}
[Link] – JavaScript® Notes for Professionals 301 [Link] – JavaScript® Notes for Professionals 302
data which can only be accessed through the asynchronous File interface. var characters = atob(data);
[Link] = function() {
array = [Link]; Section 53.5: Using TypedArrays
[Link]("Array contains", [Link], "bytes.");
}; TypedArrays are a set of types providing different views into fixed-length mutable binary ArrayBuffers. For the most
part, they act like Arrays that coerce all assigned values to a given numeric type. You can pass an ArrayBuffer
[Link](blob);
instance to a TypedArray constructor to create a new view of its data.
Version ≥ 6
Convert a Blob to an ArrayBuffer using a Promise (asynchronous)
var buffer = new ArrayBuffer(8);
var blob = new Blob(["\x01\x02\x03\x04"]); var byteView = new Uint8Array(buffer);
var floatView = new Float64Array(buffer);
var arrayPromise = new Promise(function(resolve) {
var reader = new FileReader(); [Link](byteView); // [0, 0, 0, 0, 0, 0, 0, 0]
[Link](floatView); // [0]
[Link] = function() { byteView[0] = 0x01;
resolve([Link]); byteView[1] = 0x02;
}; byteView[2] = 0x04;
byteView[3] = 0x08;
[Link](blob); [Link](floatView); // [6.64421383e-316]
});
[Link](function(array) { ArrayBuffers can be copied using the .slice(...) method, either directly or through a TypedArray view.
[Link]("Array contains", [Link], "bytes.");
}); var byteView2 = [Link]();
var floatView2 = new Float64Array([Link]);
Convert an ArrayBuffer or typed array to a Blob
byteView2[6] = 0xFF;
var array = new Uint8Array([0x04, 0x06, 0x07, 0x08]); [Link](floatView); // [6.64421383e-316]
[Link](floatView2); // [7.06327456e-304]
var blob = new Blob([array]);
[Link] – JavaScript® Notes for Professionals 303 [Link] – JavaScript® Notes for Professionals 304
[Link] += 2;
return result;
case 'Int32':
Chapter 54: Template Literals
var result = [Link].getInt32([Link], true);
Template literals are a type of string literal that allows values to be interpolated, and optionally the interpolation
[Link] += 4;
return result; and construction behaviour to be controlled using a "tag" function.
case 'Uint32':
var result = [Link].getUint32([Link], true);
[Link] += 4;
Section 54.1: Basic interpolation and multiline strings
return result;
Template literals are a special type of string literal that can be used instead of the standard '...' or "...". They
case 'Float':
case 'Float32': are declared by quoting the string with backticks instead of the standard single or double quotes: `...`.
var result = [Link].getFloat32([Link], true);
[Link] += 4; Template literals can contain line breaks and arbitrary expressions can be embedded using the ${ expression }
return result; substitution syntax. By default, the values of these substitution expressions are concatenated directly into the
case 'Double': string where they appear.
case 'Float64':
var result = [Link].getFloat64([Link], true);
const name = "John";
[Link] += 8;
const score = 74;
return result;
default:
[Link](`Game Over!
throw new Error("Unknown datatype");
}
${name}'s score was ${score * 10}.`);
};
Game Over!
[Link] = function() {
return [Link] < [Link]; John's score was 740.
}
var cursor = new ArrayBufferCursor(arrayBuffer); The first argument to the tag function, strings, is an Array of each constant piece of the literal. The remaining
arguments, ...substitutions, contain the evaluated values of each ${} substitution expression.
You can use the hasNext to check if there's still items
function settings(strings, ...substitutions) {
for(;[Link]();) { const result = new Map();
// There's still items to process for (let i = 0; i < [Link]; i++) {
} [Link](strings[i].trim(), substitutions[i]);
}
return result;
You can use the next method to take the next value: }
Map {"label" => "Content", "servers" => 17, "hostname" => "[Link]"}
The strings Array has a special .raw property referencing a parallel Array of the same constant pieces of the
template literal but exactly as they appear in the source code, without any backslash-escapes being replaced.
[Link] – JavaScript® Notes for Professionals 305 [Link] – JavaScript® Notes for Professionals 306
example`Hello ${'world'}.\n\nHow are you?`; <ul> ${[Link](name => HTML`
<li>${name}</li>
strings: ["Hello ", ".\n\nHow are you?", raw: ["Hello ", ".\\n\\nHow are you?"]]
`)} </ul>
substitutions: ["world"]
`;
[Link]`\n` will contain a backslash and the lowercase letter n, while `\n` or '\n' would contain a single
Template Literals can contain embedded expressions too. These expressions are indicated by a $ sign and curly
newline character instead. braces {}
Section 54.4: Templating HTML With Template Strings //Template Literal with an embedded expression
var x = 2;
You can create an HTML`...` template string tag function to automatically encodes interpolated values. (This var y = 3;
var theTotal = `The total is ${x + y}`; // Contains "The total is 5"
requires that interpolated values are only used as text, and may not be safe if interpolated values are used in
code such as scripts or styles.)
[Link] = HTML`
<h1><img src="${iconSrc}" /> ${title}</h1>
[Link] – JavaScript® Notes for Professionals 307 [Link] – JavaScript® Notes for Professionals 308
Chapter 55: Fetch Section 55.4: Send cookies
The fetch function does not send cookies by default. There are two possible ways to send cookies:
Options Details
method The HTTP method to use for the request. ex: GET, POST, PUT, DELETE, HEAD. Defaults to GET. 1. Only send cookies if the URL is on the same origin as the calling script.
headers A Headers object containing additional HTTP headers to include in the request.
fetch('/login', {
body The request payload, can be a string or a FormData object. Defaults to undefined
credentials: 'same-origin'
cache The caching mode. default, reload, no-cache })
referrer The referrer of the request.
2. Always send cookies, even for cross-origin calls.
mode cors, no-cors, same-origin. Defaults to no-cors.
credentials omit, same-origin, include. Defaults to omit. fetch('[Link] {
redirect follow, error, manual. Defaults to follow. credentials: 'include'
})
integrity Associated integrity metadata. Defaults to empty string.
Section 55.3: POST Data Section 55.6: Using Fetch to Display Questions from the Stack
Overflow API
Posting form data
const url =
fetch(`/example/submit`, { '[Link]
method: 'POST',
body: new FormData([Link]('example-form')) const questionList = [Link]('ul');
}); [Link](questionList);
[Link] – JavaScript® Notes for Professionals 309 [Link] – JavaScript® Notes for Professionals 310
Chapter 56: Scope },
increment: function () {
counter++;
[Link]();
var x = 4; // declaration in outer scope
[Link]([Link]());
function bar() {
[Link]([Link]());
[Link](x); // outer scope is captured on declaration
}
10
Sample output: 4
When makeCounter() is called, a snapshot of the context of that function is saved. All code inside makeCounter()
will use that snapshot in their execution. Two calls of makeCounter() will thus create two different snapshots, with
This concept of "capturing" scope is interesting because we can use and modify variables from an outer scope even their own copy of counter.
after the outer scope exits. For example, consider the following:
Immediately-invoked function expressions (IIFE)
function foo() {
var x = 4; // declaration in outer scope Closures are also used to prevent global namespace pollution, often through the use of immediately-invoked
function expressions.
function bar() {
[Link](x); // outer scope is captured on declaration Immediately-invoked function expressions (or, perhaps more intuitively, self-executing anonymous functions) are
}
essentially closures that are called right after declaration. The general idea with IIFE's is to invoke the side-effect of
return bar; creating a separate context that is accessible only to the code within the IIFE.
// x goes out of scope after foo returns Suppose we want to be able to reference jQuery with $. Consider the naive method, without using an IIFE:
}
var $ = jQuery;
var barWithX = foo(); // we've just polluted the global namespace by assigning window.$ to jQuery
barWithX(); // we can still access x
In the following example, an IIFE is used to ensure that the $ is bound to jQuery only in the context created by the
closure:
Sample output: 4
(function ($) {
// $ is assigned to jQuery here
In the above example, when foo is called, its context is captured in the function bar. So even after it returns, bar
})(jQuery);
can still access and modify the variable x. The function foo, whose context is captured in another function, is said to // but window.$ binding doesn't exist, so no pollution
be a closure.
See the canonical answer on Stackoverflow for more information on closures.
Private data
This lets us do some interesting things, such as defining "private" variables that are visible only to a specific function Section 56.2: Hoisting
or set of functions. A contrived (but popular) example:
What is hoisting?
function makeCounter() {
var counter = 0; Hoisting is a mechanism which moves all variable and function declarations to the top of their scope. However,
variable assignments still happen where they originally were.
return {
value: function () { For example, consider the following code:
return counter;
[Link] – JavaScript® Notes for Professionals 311 [Link] – JavaScript® Notes for Professionals 312
var bar = function () {};
[Link](foo); // → undefined
var foo = 42;
[Link](foo); // → 42
// Valid code:
foo();
The above code is the same as: function foo() {
bar();
var foo; // → Hoisted variable declaration }
function bar() {}
[Link](foo); // → undefined
foo = 42; // → variable assignment remains in the same place
[Link](foo); // → 42
// Invalid code:
foo();
Note that due to hoisting the above undefined is not the same as the not defined resulting from running: function foo() {
bar(); // → TypeError: bar is not a function
[Link](foo); // → foo is not defined }
var bar = function () {};
A similar principle applies to functions. When functions are assigned to a variable (i.e. a function expression), the
variable declaration is hoisted while the assignment remains in the same place. The following two code snippets are // (E) valid:
equivalent. function foo() {
bar();
}
[Link](foo(2, 3)); // → foo is not a function
var bar = function(){};
foo();
var foo = function(a, b) {
return a * b; Limitations of Hoisting
}
Initializing a variable can not be Hoisted or In simple JavaScript Hoists declarations not initialization.
var foo;
[Link](foo(2, 3)); // → foo is not a function
For example: The below scripts will give different outputs.
foo = function(a, b) {
return a * b;
} var x = 2;
var y = 4;
alert(x + y);
When declaring function statements, a different scenario occurs. Unlike function statements, function declarations
are hoisted to the top of their scope. Consider the following code:
This will give you an output of 6. But this...
[Link](foo(2, 3)); // → 6
var x = 2;
function foo(a, b) {
alert(x + y);
return a * b;
var y = 4;
}
This will give you an output of NaN. Since we are initializing the value of y, the JavaScript Hoisting is not happening,
The above code is the same as the next code snippet due to hoisting:
so the y value will be undefined. The JavaScript will consider that y is not yet declared.
function foo(a, b) {
So the second example is same as of below.
return a * b;
}
var x = 2;
[Link](foo(2, 3)); // → 6 var y;
alert(x + y);
y = 4;
Here are some examples of what is and what isn't hoisting:
function foo() {}
// Invalid code:
bar(); // → TypeError: bar is not a function
[Link] – JavaScript® Notes for Professionals 313 [Link] – JavaScript® Notes for Professionals 314
let j = 10;
}
[Link](i); // >> "ReferenceError: i is not defined"
[Link](j); // >> "ReferenceError: j is not defined"
Note that i and j are only declared in the for loop and are therefore undeclared outside of it.
In the top scope (outside any functions and blocks), var declarations put an element in the global object. let does
not:
Section 56.3: Dierence between var and let
var x = 4;
(Note: All examples using let are also valid for const) let y = 7;
var is available in all versions of JavaScript, while let and const are part of ECMAScript 6 and only available in some [Link](this.x); // >> 4
newer browsers. [Link](this.y); // >> undefined
Re-declaration
var is scoped to the containing function or the global space, depending when it is declared:
Declaring a variable twice using var doesn't produce an error (even though it's equivalent to declaring it once):
var x = 4; // global scope
var x = 4;
function DoThings() { var x = 7;
var x = 7; // function scope
[Link](x);
With let, this produces an error:
}
That means it "escapes" if statements and all similar block constructs: TypeError: Identifier x has already been declared
var x = 4;
The same is true when y is declared with var:
if (true) {
var x = 7;
} var y = 4;
[Link](x); // >> 7 let y = 7;
let i = 5;
for (let i = 0; i < 4; i++) {
[Link] – JavaScript® Notes for Professionals 315 [Link] – JavaScript® Notes for Professionals 316
{ Notice that apply allows you to pass an Array or the arguments object (array-like) as the list of arguments, whereas,
i = 6; // outer i is unavailable within the Temporal Dead Zone
call needs you to pass each argument separately.
let i;
}
These two methods give you the freedom to get as fancy as you want, like implementing a poor version of the
ECMAScript's native bind to create a function that will always be called as a method of an object from an original
ReferenceError: i is not defined function.
printObj();
The area between the start of a block and a let or const declaration is known as the Temporal Dead Zone, and any
references to the variable in this area will cause a ReferenceError. This happens even if the variable is assigned
This will log
before being declared:
In non-strict-mode, assigning a value to a variable without any declaration, automatically declares the variable in
the global scope. In this case, instead of y being automatically declared in the global scope, let reserves the
variable's name (y) and does not allow any access or assignment to it before the line where it is declared/initialized. The bind function has a lot going on
[Link]({ toPrint: "Foo" }); // >> "Foo" When using arrow functions this takes the value from the enclosing execution context's this (that is, this in arrow
[Link]({ toPrint: "Foo" }); // >> "Foo" functions has lexical scope rather than the usual dynamic scope). In global code (code that doesn't belong to any
function) it would be the global object. And it keeps that way, even if you invoke the function declared with the
You might notice that the syntax for both the invocations used above are the same. i.e. The signature looks similar. arrow notation from any of the others methods here described.
But there is a small difference in their usage, since we are dealing with functions and changing their scopes, we still var globalThis = this; //"window" in a browser, or "global" in [Link]
need to maintain the original arguments passed to the function. Both apply and call support passing arguments
to the target function as follows: var foo = (() => this);
[Link] – JavaScript® Notes for Professionals 317 [Link] – JavaScript® Notes for Professionals 318
var obj = {
withoutArrow: function() {
Section 56.8: Anonymous invocation
return this;
Invoking a function as an anonymous function, this will be the global object (self in the browser).
},
withArrow: () => this
}; function func() {
return this;
[Link]([Link]() === obj); //true }
[Link]([Link]() === globalThis); //true
func() === window; // true
var fn = [Link]; //no longer calling withoutArrow as a method Version = 5
var fn2 = [Link];
[Link](fn() === globalThis); //true In ECMAScript 5's strict mode, this will be undefined if the function is invoked anonymously.
[Link](fn2() === globalThis); //true
(function () {
fooObj = [Link](obj);
Section 56.9: Constructor invocation
fooObj(); When a function is invoked as a constructor with the new keyword this takes the value of the object being
constructed
This will log:
function Obj(name) {
[Link] = name;
bar }
Invoking a function as a method of an object the value of this will be that object.
This will log
var obj = {
name: "Foo", { name: "Foo" }
print: function () {
[Link]([Link])
[Link] – JavaScript® Notes for Professionals 319 [Link] – JavaScript® Notes for Professionals 320
TypeError: loadedData[i] is undefined
Chapter 57: Modules
error. This is because the scope of i is the global scope (or a function scope) and after the loop, i == 3. What we
need is not to "remember the state of i". This can be done using let:
Section 57.1: Defining a module
In ECMAScript 6, when using the module syntax (import/export), each file becomes its own module with a private
for(let i = 0; i < [Link]; i++)
namespace. Top-level functions and variables do not pollute the global namespace. To expose functions, classes,
jQuery("#container").append("<a class='button'>"+loadedData[i].label+"</a>")
.children().last() // now let's attach a handler to the button which is a child and variables for other modules to import, you can use the export keyword.
.on("click",function() { alert(loadedData[i].content); });
// not exported
function somethingPrivate() {
An example of loadedData to be tested with this code:
[Link]('TOP SECRET')
}
var loadedData = [
{ label:"apple", content:"green and round" },
{ label:"blackberry", content:"small black or blue" }, export const PI = 3.14;
{ label:"pineapple", content:"weird stuff.. difficult to explain the shape" }
]; export function doSomething() {
[Link]('Hello from a module!')
A fiddle to illustrate this }
function doSomethingElse(){
[Link]("Something else")
}
export {doSomethingElse}
Note: ES5 JavaScript files loaded via <script> tags will remain the same when not using import/export.
Only the values which are explicitly exported will be available outside of the module. Everything else can be
considered private or inaccessible.
Importing this module would yield (assuming the previous code block is in [Link]):
[Link]; // 3.14
[Link](); // 'Hello from a module!'
[Link](); // 'Something else'
new [Link](); // an instance of MyClass
[Link](); // This would fail since somethingPrivate was not exported
// [Link]
export const PI = 3.14;
export default function area(radius) {
return PI * radius * radius;
}
[Link] – JavaScript® Notes for Professionals 321 [Link] – JavaScript® Notes for Professionals 322
import circleArea from './circle'; Section 57.5: Importing named members with aliases
[Link](circleArea(4));
Sometimes you may encounter members that have really long member names, such as
Note that a default export is implicitly equivalent to a named export with the name default, and the imported thisIsWayTooLongOfAName(). In this case, you can import the member and give it a shorter name to use in your
binding (circleArea above) is simply an alias. The previous module can be written like current module:
import { default as circleArea } from './circle'; import {thisIsWayTooLongOfAName as shortName} from 'module'
[Link](circleArea(4));
shortName()
You can only have one default export per module. The name of the default export can be omitted.
You can import multiple long member names like this:
// named export: must have a name
export const PI = 3.14; import {thisIsWayTooLongOfAName as shortName, thisIsAnotherLongNameThatShouldNotBeUsed as
otherName} from 'module'
// default export: name is not required
export default function (radius) { shortName()
return PI * radius * radius; [Link](otherName)
}
And finally, you can mix import aliases with the normal member import:
Section 57.3: Importing named members from another
module import {thisIsWayTooLongOfAName as shortName, PI} from 'module'
shortName()
Given that the module from the Defining a Module section exists in the file [Link], you can import from that
[Link](PI)
module and use its exported members:
import {doSomething, MyClass, PI} from './test' Section 57.6: Importing with side eects
doSomething() Sometimes you have a module that you only want to import so its top-level code gets run. This is useful for polyfills,
other globals, or configuration that only runs once when your module is imported.
const mine = new MyClass()
[Link]() Given a file named [Link]:
[Link](PI)
[Link]('Initializing...')
The somethingPrivate() method was not exported from the test module, so attempting to import it will fail:
You can use it like this:
Section 57.4: Importing an entire module Section 57.7: Exporting multiple named members
In addition to importing named members from a module or a module's default export, you can also import all
const namedMember1 = ...
members into a namespace binding.
const namedMember2 = ...
const namedMember3 = ...
import * as test from './test'
export { namedMember1, namedMember2, namedMember3 }
[Link]()
All exported members are now available on the test variable. Non-exported members are not available, just as
they are not available with named member imports.
Note: The path to the module './test' is resolved by the loader and is not covered by the ECMAScript specification
- this could be a string to any resource (a path - relative or absolute - on a filesystem, a URL to a network resource,
or any other string identifier).
[Link] – JavaScript® Notes for Professionals 323 [Link] – JavaScript® Notes for Professionals 324
Chapter 58: Screen Chapter 59: Variable coercion/conversion
Section 58.1: Getting the screen resolution Section 59.1: Double Negation (!!x)
To get the physical size of the screen (including window chrome and menubar/launcher): The double-negation !! is not a distinct JavaScript operator nor a special syntax but rather just a sequence of two
negations. It is used to convert the value of any type to its appropriate true or false Boolean value depending on
var width = [Link], whether it is truthy or falsy.
height = [Link];
!!1 // true
Section 58.2: Getting the “available” area of the screen !!0
!!undefined
//
//
false
false
!!{} // true
To get the “available” area of the screen (i.e. not including any bars on the edges of the screen, but including
!![] // true
window chrome and other windows:
The first negation converts any value to false if it is truthy and to true if is falsy. The second negation then operates
var availableArea = {
on a normal Boolean value. Together they convert any truthy value to true and any falsy value to false.
pos: {
x: [Link],
y: [Link] However, many professionals consider the practice of using such syntax unacceptable and recommend simpler to
}, read alternatives, even if they're longer to write:
size: {
width: [Link], x !== 0 // instead of !!x in case x is a number
height: [Link] x != null // instead of !!x in case x is an object, a string, or an undefined
}
};
Usage of !!x is considered poor practice due to the following reasons:
Section 58.3: Page width and height 1. Stylistically it may look like a distinct special syntax whereas in fact it is not doing anything other than two
consecutive negations with implicit type conversion.
To get current page width and height (for any browser), e.g. when programming responsiveness: 2. It is better to provide information about types of values stored in variables and properties through the code.
For example, x !== 0 says that x is probably a number, whereas !!x does not convey any such advantage to
function pageWidth() { readers of the code.
return [Link] != null? [Link] : [Link] &&
3. Usage of Boolean(x) allows for similar functionality, and is a more explicit conversion of type.
[Link] ? [Link] : [Link] != null
? [Link] : null;
} Section 59.2: Implicit conversion
function pageHeight() { JavaScript will try to automatically convert variables to more appropriate types upon use. It's usually advised to do
return [Link] != null? [Link] : [Link] &&
conversions explicitly (see other examples), but it's still worth knowing what conversions take place implicitly.
[Link] ? [Link] : [Link] !=
null? [Link] : null;
} "1" + 5 === "15" // 5 got converted to string.
1 + "5" === "15" // 1 got converted to string.
1 - "5" === -4 // "5" got converted to a number.
Section 58.4: Window innerWidth and innerHeight Properties alert({}) // alerts "[object Object]", {} got converted to string.
!0 === true // 0 got converted to boolean
Get the window height and width if ("hello") {} // runs, "hello" got converted to boolean.
new Array(3) === ",,"; // Return true. The array is converted to string - [Link]();
Section 58.5: Getting color information about the screen !"0" === false // "0" got converted to true, then reversed.
!"false" === false // "false" converted to true, then reversed.
[Link] – JavaScript® Notes for Professionals 325 [Link] – JavaScript® Notes for Professionals 326
Boolean("true") === true parseInt('0', 10) will convert the string ('0') into a number (0), don't forget the second argument, which is radix.
Boolean("false") === true If not given, parseInt could convert string to wrong number.
Boolean(-1) === true
Boolean(1) === true
Boolean(0) === false Section 59.5: Converting a number to a string
Boolean("") === false
Boolean("1") === true String(0) === '0'
Boolean("0") === true
Boolean({}) === true String(0) will convert the number (0) into a string ('0').
Boolean([]) === true
Values that get converted to false as booleans are called falsy (and all others are called truthy). See Comparison [] "" 0 true
Operations. [3] "3" 3 true
['a'] "a" NaN true
Section 59.4: Converting a string to a number ['a','b'] "a,b" NaN true
{} "[object Object]" NaN true
Number('0') === 0
function(){} "function(){}" NaN true
Number('0') will convert the string ('0') into a number (0) Bold values highlight conversion that programmers may find surprising
A shorter, but less clear, form: To convert explicitly values you can use String() Number() Boolean()
+'0' === 0
Section 59.7: Convert an array to a string
The unary + operator does nothing to numbers, but converts anything else to a number.
[Link](separator) can be used to output an array as a string, with a configurable separator.
Interestingly, +(-12) === -12.
Default (separator = ","):
parseInt('0', 10) === 0
["a", "b", "c"].join() === "a,b,c"
[Link] – JavaScript® Notes for Professionals 327 [Link] – JavaScript® Notes for Professionals 328
With a string separator: all that must be done to convert it.
[1, 2, 3, 4].join(" + ") === "1 + 2 + 3 + 4" Section 59.12: Float to Integer
With a blank separator: To convert a float to an integer, JavaScript provides multiple methods.
["B", "o", "b"].join("") === "Bob" The floor function returns the first integer less than or equal to the float.
This way may seem to be useless because you are using anonymous function to accomplish something that you The ceil function returns the first integer greater than or equal to the float.
can do it with join(); But if you need to make something to the strings while you are converting the Array to String,
[Link](5.3); // 6
this can be useful.
Section 59.9: Converting a number to a boolean Notice the difference between truncation (trunc) and floor:
A shorter, but less clear, form: Section 59.13: Convert string to float
!!0 === false parseFloat accepts a string as an argument which it converts to a float/
Boolean(myString)
!!myString
All strings except the empty string (of length zero) are evaluated to true as booleans.
[Link] – JavaScript® Notes for Professionals 329 [Link] – JavaScript® Notes for Professionals 330
Chapter 60: Destructuring assignment // Is equivalent to
let p = [Link]('phone') ? [Link] : '123-456-789'; // '123-456-789'
Destructuring is a pattern matching technique that is added to JavaScript recently in ECMAScript 6. Section 60.2: Destructuring function arguments
It allows you to bind a group of variables to a corresponding set of values when their pattern matches to the right Pull properties from an object passed into a function. This pattern simulates named parameters instead of relying
hand-side and the left hand-side of the expression. on argument position.
let person = {
name: 'Bob',
age: 25
Section 60.3: Nested Destructuring
};
We are not limited to destructuring an object/array, we can destructure a nested object/array.
let { name: firstName } = person;
Nested Object Destructuring
// Is equivalent to
let firstName = [Link]; // 'Bob' var obj = {
a: {
c: 1,
Destructuring with default values:
d: 3
},
let person = { b: 2
name: 'Bob', };
age: 25
}; var {
a: {
let { phone = '123-456-789' } = person; c: x,
d: y
// Is equivalent to },
let phone = [Link]('phone') ? [Link] : '123-456-789'; // '123-456-789' b: z
} = obj;
Destructuring and renaming with default values
[Link](x, y, z); // 1,3,2
let person = {
name: 'Bob', Nested Array Destructuring
age: 25
}; var arr = [1, 2, [3, 4], 5];
[Link] – JavaScript® Notes for Professionals 331 [Link] – JavaScript® Notes for Professionals 332
[Link](a, b, c, d); // 1 3 4 5 let { name, age, location } = person;
[Link]('I am ' + name + ', aged ' + age + ' and living in ' + location + '.');
Destructuring is not just limited to a single pattern, we can have arrays in it, with n-levels of nesting. Similarly we
// -> "I am John Doe aged 45 and living in Paris, France."
can destructure arrays with objects and vice-versa.
Arrays Within Object As you can see, three new variables were created: name, age and location and their values were grabbed from the
object person if they matched key names.
var obj = {
a: 1, Section 60.6: Default Value While Destructuring
b: [2, 3]
}; We often encounter a situation where a property we're trying to extract doesn't exist in the object/array, resulting
in a TypeError (while destructuring nested objects) or being set to undefined. While destructuring we can set a
var {
a: x1, default value, which it will fallback to, in case of it not being found in the object.
b: [x2, x3]
} = obj; var obj = {a : 1};
var {a : x , b : x1 = 10} = obj;
[Link](x1, x2, x3); // 1 2 3 [Link](x, x1); // 1, 10
var [x1, x2 , {a : x3}, x4] = arr; Section 60.7: Renaming Variables While Destructuring
[Link](x1, x2, x3, x4); Destructuring allows us to refer to one key in an object, but declare it as a variable with a different name. The
syntax looks like the key-value syntax for a normal JavaScript object.
Section 60.4: Destructuring Arrays
let user = {
const myArr = ['one', 'two', 'three'] name: 'John Smith',
const [ a, b, c ] = myArr id: 10,
email: 'johns@[Link]',
// a = 'one', b = 'two, c = 'three' };
var a = 1;
var b = 3;
[a, , b] = [1, 2, 3] // a = 1, b = 3
const person = {
name: 'John Doe',
age: 45,
location: 'Paris, France',
};
[Link] – JavaScript® Notes for Professionals 333 [Link] – JavaScript® Notes for Professionals 334
Chapter 61: WebSockets };
[Link]('Uint8:', view.getUint8(4), 'Float32:', view.getFloat32(0))
[Link] = function() {
Parameter Details
[Link](buffer);
url The server url supporting this web socket connection.
};
data The content to send to the host.
message The message received from the host.
Section 61.4: Making a secure web socket connection
WebSocket is protocol, which enables two-way communication between a client and server:
var sck = "[Link]
var wss = new WebSocket(sck);
The goal WebSocket is to provide a mechanism for browser-based applications that need two-way communication
with servers that does not rely on opening multiple HTTP connections. (RFC 6455)
This uses the wss instead of ws to make a secure web socket connection which make use of HTTPS instead of HTTP
WebSocket works over HTTP protocol.
//onopen : Event Listener - event is triggered when websockets readyState changes to open which means
now we are ready to send and receives messages from server
[Link] = function() {
//send is used to send the message to server
[Link](value);
};
bufferView.setFloat32(0, [Link]);
bufferView.setUint8(4, 127);
[Link] = 'arraybuffer';
[Link] = function(message) {
var view = new DataView([Link]);
[Link] – JavaScript® Notes for Professionals 335 [Link] – JavaScript® Notes for Professionals 336
Chapter 62: Arrow Functions after 1 second.
class Cow {
Arrow functions are a concise way of writing anonymous, lexically scoped functions in ECMAScript 2015 (ES6).
constructor() {
In JavaScript, functions may be anonymously defined using the "arrow" (=>) syntax, which is sometimes referred to makeSoundLater() {
as a lambda expression due to Common Lisp similarities. setTimeout(() => [Link]([Link]), 1000);
}
The simplest form of an arrow function has its arguments on the left side of => and the return value on the right }
side:
const betsy = new Cow();
This function can be immediately invoked by providing an argument to the expression: In the makeSoundLater() method, the this context refers to the current instance of the Cow object, so in the case
where I call [Link](), the this context refers to betsy.
(item => item + 1)(41) // -> 42
By using the arrow function, I preserve the this context so that I can make reference to [Link] when it comes
If an arrow function takes a single parameter, the parentheses around that parameter are optional. For example, time to print it out, which will properly print out "moo".
the following expressions assign the same type of function into constant variables:
If you had used a regular function in place of the arrow function, you would lose the context of being within the
const foo = bar => bar + 1; class, and not be able to directly access the sound property.
const bar = (baz) => baz + 1;
However, if the arrow function takes no parameters, or more than one parameter, a new set of parentheses must
Section 62.3: Arguments Object
encase all the arguments: Arrow functions do not expose an arguments object; therefore, arguments would simply refer to a variable in the
current scope.
(() => "foo")() // -> "foo"
(bar => { While the lack of an arguments object can be a limitation in some edge cases, rest parameters are generally a
const baz = 41;
suitable alternative.
return bar + baz;
})(1); // -> 42
const arguments = [true];
const foo = (...arguments) => [Link](arguments[0]);
If the arrow function's body consists only of an object literal, this object literal has to be enclosed in parentheses:
foo(false); // -> false
(bar => ({ baz: 1 }))(); // -> Object {baz: 1}
The extra parentheses indicate that the opening and closing brackets are part of the object literal, i.e. they are not
Section 62.4: Implicit Return
delimiters of the function body.
Arrow functions may implicitly return values by simply omitting the curly braces that traditionally wrap a function's
body if their body only contains a single expression.
Section 62.2: Lexical Scoping & Binding (Value of "this")
const foo = x => x + 1;
Arrow functions are lexically scoped; this means that their this Binding is bound to the context of the surrounding foo(1); // -> 2
scope. That is to say, whatever this refers to can be preserved by using an arrow function.
When using implicit returns, object literals must be wrapped in parenthesis so that the curly braces are not
Take a look at the following example. The class Cow has a method that allows for it to print out the sound it makes
mistaken for the opening of the function's body.
[Link] – JavaScript® Notes for Professionals 337 [Link] – JavaScript® Notes for Professionals 338
const foo = () => { bar: 1 } // foo() returns undefined
const foo = () => ({ bar: 1 }) // foo() returns {bar: 1} Chapter 63: Workers
Section 62.5: Arrow functions as a constructor Section 63.1: Web Worker
Arrow functions will throw a TypeError when used with the new keyword. A web worker is a simple way to run scripts in background threads as the worker thread can perform tasks
(including I/O tasks using XMLHttpRequest) without interfering with the user interface. Once created, a worker can
const foo = function () { send messages which can be different data types (except functions) to the JavaScript code that created it by posting
return 'foo'; messages to an event handler specified by that code (and vice versa.)
}
Workers can be created in a few ways.
const a = new foo();
The most common is from a simple URL:
const bar = () => {
return 'bar';
var webworker = new Worker("./path/to/[Link]");
}
const b = new bar(); // -> Uncaught TypeError: bar is not a constructor... It's also possible to create a Worker dynamically from a string using [Link]():
Section 62.6: Explicit Return var workerData = "function someFunction() {}; [Link]('More code');";
const foo = x => { The same method can be combined with [Link]() to create a worker from an existing function:
return x + 1;
} var workerFn = function() {
[Link]("I was run");
foo(1); // -> 2 };
A service worker is an event-driven worker registered against an origin and a path. It takes the form of a
JavaScript file that can control the web page/site it is associated with, intercepting and modifying
navigation and resource requests, and caching resources in a very granular fashion to give you complete
control over how your app behaves in certain situations (the most obvious one being when the network is
not available.)
Source: MDN
Few Things:
[Link] – JavaScript® Notes for Professionals 339 [Link] – JavaScript® Notes for Professionals 340
This code that will be executed in the Document context, (or) this JavaScript will be included in your page via a var webworker = new Worker("./path/to/[Link]");
<script> tag.
// Send information to worker
[Link]("Sample message");
// we check if the browser supports ServiceWorkers
if ('serviceWorker' in navigator) { // Listen for messages from the worker
navigator [Link]("message", function(event) {
.serviceWorker // `[Link]` contains the value or object sent from the worker
.register( [Link]("Message from worker:", [Link]); // ["foo", "bar", "baz"]
// path to the service worker file });
'[Link]'
)
// the registration is async and it returns a promise From the worker, in [Link]:
.then(function (reg) {
[Link]('Registration Successful'); // Send information to the main thread (parent window)
}); [Link](["foo", "bar", "baz"]);
}
// Listen for messages from the main thread
[Link]
[Link]("message", function(event) {
// `[Link]` contains the value or object sent from main
This is the service worker code and is executed in the ServiceWorker Global Scope. [Link]("Message from parent:", [Link]); // "Sample message"
});
[Link]('fetch', function (event) {
// do nothing here, just log all the network requests
Alternatively, you can also add event listeners using onmessage:
[Link]([Link]);
});
From the main thread (parent window):
You can call register() on every page load. If the SW is already registered, the browser provides you with Section 63.5: Terminate a worker
instance that is already running
The SW file can be any name. [Link] is common. Once you are done with a worker you should terminate it. This helps to free up resources for other applications on
The location of the SW file is important because it defines the SW's scope. For example, an SW file at the user’s computer.
/js/[Link] can only intercept fetch requests for files that begin with /js/. For this reason you usually see the
Main Thread:
SW file at the top-level directory of the project.
Since workers run in a separate thread from the one that created them, communication needs to happen via
Note: The terminate method is not available for service workers. It will be terminated when not in use, and
postMessage.
restarted when it's next needed.
Note: Because of the different export prefixes, some browsers have webkitPostMessage instead of postMessage. Worker Thread:
You should override postMessage to make sure workers "work" (no pun intended) in the most places possible:
// Have a worker terminate itself.
[Link] = ([Link] || [Link]); [Link]();
// Create a worker
[Link] – JavaScript® Notes for Professionals 341 [Link] – JavaScript® Notes for Professionals 342
Section 63.6: Populating your cache an explicit port has to be opened so multiple scripts can use it to communicate with the shared worker. (Note that
dedicated workers do this implicitly)
After your service worker is registered, the browser will try to install & later activate the service worker.
Main application
Install event listener
var myWorker = new SharedWorker('[Link]');
[Link]('install', function(event) { [Link](); // open the port connection
[Link]('installed');
}); [Link]([2,3]);
Caching [Link]
One can use this install event returned to cache the assets needed to run the app offline. Below example uses the [Link](); open the port connection to enable two-way communication
cache api to do the same.
[Link] = function(e) {
var port = [Link][0]; // get the port
[Link]('install', function(event) {
[Link](
[Link] = function(e) {
[Link]('v1').then(function(cache) {
[Link]('Worker received arguments:', [Link]);
return [Link]([
[Link]([Link][0] + [Link][1]);
/* Array of all the assets that needs to be cached */
}
'/css/[Link]',
}
'/js/[Link]',
'/images/[Link]'
]); Note that setting up this message handler in the worker thread also implicitly opens the port connection back to
}) the parent thread, so the call to [Link]() is not actually needed, as noted above.
);
});
A dedicated web worker is only accessible by the script that called it.
Main application:
[Link]:
[Link]('message', function(msg) {
[Link]('Worker received arguments:', [Link]);
[Link]([Link][0] + [Link][1]);
});
Shared Workers
A shared worker is accessible by multiple scripts — even if they are being accessed by different windows, iframes or
even workers.
Creating a shared worker is very similar to how to create a dedicated one, but instead of the straight-forward
communication between the main thread and the worker thread, you'll have to communicate via a port object, i.e.,
[Link] – JavaScript® Notes for Professionals 343 [Link] – JavaScript® Notes for Professionals 344
Chapter 64: requestAnimationFrame // start the animation
[Link](eachFrame);
</script>
Parameter Details
</body>
"A parameter specifying a function to call when it's time to update your animation for the next
callback </html>
repaint." ([Link]
Section 64.1: Use requestAnimationFrame to fade in element Section 64.2: Keeping Compatibility
Of course, just like most things in browser JavaScript, you just can't count on the fact that everything will be the
View jsFiddle: [Link]
same everywhere. In this case, requestAnimationFrame might have a prefix on some platforms and are named
Copy + Pasteable code below:
differently, such as webkitRequestAnimationFrame. Fortunately, there's a really easy way to group all the known
<html> differences that could exist down to 1 function:
<body>
<h1>This will fade in at 60 frames per second (or as close to possible as your hardware [Link] = (function(){
allows)</h1> return [Link] ||
[Link] ||
<script> [Link] ||
// Fade in over 2000 ms = 2 seconds. function(callback){
var FADE_DURATION = 2.0 * 1000; [Link](callback, 1000 / 60);
};
// -1 is simply a flag to indicate if we are rendering the very 1st frame })();
var startTime=-1.0;
Note that the last option (which fills in when no existing support was found) will not return an id to be used in
// Function to render current frame (whatever frame that may be)
function render(currTime) { cancelAnimationFrame. There is, however an efficient polyfill that was written which fixes this.
var head1 = [Link]('h1')[0];
[Link] – JavaScript® Notes for Professionals 345 [Link] – JavaScript® Notes for Professionals 346
setTimeout(pause,1000);
Chapter 65: Creational Design Patterns
Design patterns are a good way to keep your code readable and DRY. DRY stands for don't repeat yourself.
Below you could find more examples about the most important design patterns.
Factory functions do not require the use of the new keyword, but can still be used to initialize an object, like a
constructor.
Often, factory functions are used as API wrappers, like in the cases of jQuery and [Link], so users do not need
to use new.
The following is the simplest form of factory function; taking arguments and using them to craft a new object with
the object literal:
function cowFactory(name) {
return {
name: name,
talk: function () {
[Link]('Moo, my name is ' + [Link]);
},
};
}
It is easy to define private properties and methods in a factory, by including them outside of the returned object.
This keeps your implementation details encapsulated, so you can only expose the public interface to your object.
function cowFactory(name) {
function formalName() {
return name + ' the cow';
}
return {
talk: function () {
[Link]('Moo, my name is ' + formalName());
},
};
}
The last line will give an error because the function formalName is closed inside the cowFactory function. This is a
closure.
Factories are also a great way of applying functional programming practices in JavaScript, because they are
functions.
[Link] – JavaScript® Notes for Professionals 347 [Link] – JavaScript® Notes for Professionals 348
Section 65.2: Factory with Composition [Link]();
[Link]();
// outputs: Fred says Hello
// outputs: Fred is moving slowly
'Prefer composition over inheritance' is an important and popular programming principle, used to assign behaviors to
var snowy = rabbit('Snowy', 'white');
objects, as opposed to inheriting many often unneeded behaviors. [Link](); // outputs: Snowy is moving slowly
[Link](); // outputs: Snowy is moving quickly
Behaviour factories [Link](); // ERROR: [Link] is not a function
This gives us a clean solution for hiding the main logic and only exposing an interface we wish other parts of our
var mover = function (state) {
return { application to use.
moveSlowly: function () {
[Link]([Link] + ' is moving slowly'); var Module = (function(/* pass initialization data if necessary */) {
}, // Private data is stored within the closure
moveQuickly: function () { var privateData = 1;
[Link]([Link] + ' is moving quickly');
} // Because the function is immediately invoked,
}; // the return value becomes the public API
}; var api = {
getPrivateData: function() {
return privateData;
Object factories
},
Version ≥ 6
getDoublePrivateData: function() {
var person = function (name, age) {
return [Link]() * 2;
var state = {
}
name: name,
};
age: age,
return api;
noise: 'Hello'
})(/* pass initialization data if necessary */);
};
Revealing Module Pattern
return [Link]( // Merge our 'behaviour' objects
{}, The Revealing Module pattern is a variant in the Module pattern. The key differences are that all members (private
speaker(state), and public) are defined within the closure, the return value is an object literal containing no function definitions,
mover(state)
and all references to member data are done through direct references rather than through the returned object.
);
};
var Module = (function(/* pass initialization data if necessary */) {
var rabbit = function (name, colour) { // Private data is stored just like before
var state = { var privateData = 1;
name: name,
colour: colour // All functions must be declared outside of the returned object
}; var getPrivateData = function() {
return privateData;
return [Link]( };
{},
mover(state) var getDoublePrivateData = function() {
); // Refer directly to enclosed members rather than through the returned object
}; return getPrivateData() * 2;
};
[Link] – JavaScript® Notes for Professionals 349 [Link] – JavaScript® Notes for Professionals 350
};
getDoublePrivateData: getDoublePrivateData
Section 65.4: Prototype Pattern
})(/* pass initialization data if necessary */);
The prototype pattern focuses on creating an object that can be used as a blueprint for other objects through
Revealing Prototype Pattern prototypal inheritance. This pattern is inherently easy to work with in JavaScript because of the native support for
prototypal inheritance in JS which means we don't need to spend time or effort imitating this topology.
This variation of the revealing pattern is used to separate the constructor to the methods. This pattern allow us to
use the javascript language like a objected oriented language: Creating methods on the prototype
// The prototype is used to separate the construct and the methods [Link]();
[Link] = function() { // => Hello, John!
// It is an example of a public method because is revealed in the return statement
var setCurrent = function() {
//Here the variables current and length are used as private class properties Prototypal Inheritance
for (var i = 0; i < [Link]; i++) {
$([Link]).addClass('active'); Inheriting from a 'parent object' is relatively easy via the following pattern
}
} [Link] = [Link]([Link]);
return { setCurrent: setCurrent }; [Link] = ChildObject;
}();
Where ParentObject is the object you wish to inherit the prototyped functions from, and ChildObject is the new
// Example of parameterless constructor
[Link] = function() {} Object you wish to put them on.
[Link] = function() { If the parent object has values it initializes in its constructor you need to call the parents constructor when
// It is a example of an private method because is not revealed in the return statement initializing the child.
var reload = function(data) {
// do something You do that using the following pattern in the ChildObject constructor.
},
// It the only public method, because it the only function referenced in the return statement
function ChildObject(value) {
getPage = function(link) {
[Link](this, value);
var a = $(link);
}
[Link] = function() {
return 'Your ' + [Link] + ' has arrived!';
}
[Link] – JavaScript® Notes for Professionals 351 [Link] – JavaScript® Notes for Professionals 352
[Link] = function() {
return [Link]() + ' ' + [Link]();
Section 65.6: Abstract Factory Pattern
}
The Abstract Factory Pattern is a creational design pattern that can be used to define specific instances or classes
var delivery = new RoomService('John', 'pizza'); without having to specify the exact object that is being created.
return {
// public methods and variables
publicMethod: function() {
[Link]('I am a public method');
},
publicVariable: 'I am a public variable'
};
}
return {
// Get the Singleton instance if it exists
// or create one if doesn't
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
Usage:
[Link] – JavaScript® Notes for Professionals 353 [Link] – JavaScript® Notes for Professionals 354
Chapter 66: Detecting browser [Link]= (function(){
var ua= [Link], tem,
M= [Link](/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
Browsers, as they have evolved, offered more features to JavaScript. But often these features are not available in all if(/trident/[Link](M[1])){
tem= /\brv[ :]+(\d+)/[Link](ua) || [];
browsers. Sometimes they may be available in one browser, but yet to be released on other browsers. Other times,
return 'IE '+(tem[1] || '');
these features are implemented differently by different browsers. Browser detection becomes important to ensure }
that the application you develop runs smoothly across different browsers and devices. if(M[1]=== 'Chrome'){
tem= [Link](/\b(OPR|Edge)\/(\d+)/);
Section 66.1: Feature Detection Method }
if(tem!= null) return [Link](1).join(' ').replace('OPR', 'Opera');
Credit to Rob W
The four conditional blocks following the user agent matching code are meant to account for differences in the user
agents of different browsers. For example, in case of opera, since it uses Chrome rendering engine, there is an
additional step of ignoring that part.
[Link] – JavaScript® Notes for Professionals 355 [Link] – JavaScript® Notes for Professionals 356
Chapter 67: Symbols of the symbol that can be used in a debug message) using the toString method or the String constructor.
Symbol is a new primitive type in ES6. Symbols are used mainly as property keys, and one of its main
characteristics is that they are unique, even if they have the same description. This means they will never have a
name clash with any other property key that is a symbol or string.
obj[MY_PROP_KEY] = "ABC";
[Link](obj[MY_PROP_KEY]);
Providing an optional parameter (description) when creating primitive symbols can be used for debugging but
not to access the symbol itself (but see the [Link]() example for a way to register/lookup global shared
symbols).
let a = [Link]('A');
The next time you call [Link]('A'), the same symbol will be returned instead of a new one (in contrast to
Symbol('A') which would create a new, unique symbol that happens to have the same description).
but
Instead, they have to be explicitly converted into a string when necessary, (for example, to get a textual description
[Link] – JavaScript® Notes for Professionals 357 [Link] – JavaScript® Notes for Professionals 358
Chapter 68: Transpiling Section 68.2: Start using ES6/7 with Babel
Browser support for ES6 is growing, but to be sure your code will work on environments that don't fully support it,
Transpiling is the process of interpreting certain programming languages and translating it to a specific target you can use Babel, the ES6/7 to ES5 transpiler, try it out!
language. In this context, transpiling will take compile-to-JS languages and translate them into the target language
of JavaScript. If you would like to use ES6/7 in your projects without having to worry about compatibility, you can use Node and
Babel CLI
Section 68.1: Introduction to Transpiling
Examples Quick setup of a project with Babel for ES6/7 support
// Conventional ES5 anonymous function syntax 4. Create a scripts folder to store your .js files, and then a dist/scripts folder where the transpiled fully
[1,2,3].map(function(n) { compatible files will be stored.
return n + 1;
5. Create a .babelrc file in the root folder of your project, and write this on it
});
{
CoffeeScript to JavaScript (via built-in CoffeeScript compiler): "presets": ["es2015"]
}
This CoffeeScript
6. Edit your [Link] file (created when you ran npm init) and add the build script to the scripts
# Existence: property:
alert "I knew it!" if elvis?
{
is interpreted and translated to JavaScript: ...
"scripts": {
... ,
if (typeof elvis !== "undefined" && elvis !== null) {
"build": "babel scripts --out-dir dist/scripts"
alert("I knew it!");
},
}
...
}
How do I transpile?
7. Enjoy programming in ES6/7
Most compile-to-JavaScript languages have a transpiler built-in (like in CoffeeScript or TypeScript). In this case, you 8. Run the following to transpile all your files to ES5
may just need to enable the language's transpiler via config settings or a checkbox. Advanced settings can also be
set in relation to the transpiler. ~ npm run build
For ES6/ES2016-to-ES5 transpiling, the most prominent transpiler being used is Babel. For more complex projects you might want to take a look at Gulp or Webpack
[Link] – JavaScript® Notes for Professionals 359 [Link] – JavaScript® Notes for Professionals 360
Chapter 69: Automatic Semicolon Insertion 1. When, as the program is parsed from left to right, a token (called the offending token) is
encountered that is not allowed by any production of the grammar, then a semicolon is
- ASI automatically inserted before the offending token if one or more of the following conditions is true:
The offending token is separated from the previous token by at least one LineTerminator.
Section 69.1: Avoid semicolon insertion on return statements The offending token is }.
The JavaScript coding convention is to place the starting bracket of blocks on the same line of their declaration: 2. When, as the program is parsed from left to right, the end of the input stream of tokens is
encountered and the parser is unable to parse the input token stream as a single complete
if (...) { ECMAScript Program, then a semicolon is automatically inserted at the end of the input stream.
3. When, as the program is parsed from left to right, a token is encountered that is allowed by some
}
production of the grammar, but the production is a restricted production and the token would be
function (a, b, ...) { the first token for a terminal or nonterminal immediately following the annotation "[no
LineTerminator here]" within the restricted production (and therefore such a token is called a
} restricted token), and the restricted token is separated from the previous token by at least one
LineTerminator, then a semicolon is automatically inserted before the restricted token.
Instead of in the next line:
However, there is an additional overriding condition on the preceding rules: a semicolon is never inserted
if (...) automatically if the semicolon would then be parsed as an empty statement or if that semicolon would
{ become one of the two semicolons in the header of a for statement (see 12.6.3).
}
Source: ECMA-262, Fifth Edition ECMAScript Specification:
function (a, b, ...)
{
Section 69.3: Statements aected by automatic semicolon
} insertion
This has been adopted to avoid semicolon insertion in return statements that return objects: empty statement
var statement
function foo() expression statement
{
do-while statement
return // A semicolon will be inserted here, making the function return nothing
continue statement
{
foo: 'foo' break statement
}; return statement
} throw statement
foo(); // undefined
Examples:
function properFoo() {
When the end of the input stream of tokens is encountered and the parser is unable to parse the input token
return {
foo: 'foo' stream as a single complete Program, then a semicolon is automatically inserted at the end of the input stream.
};
} a = b
++c
properFoo(); // { foo: 'foo' } // is transformed to:
a = b;
In most languages the placement of the starting bracket is just a matter of personal preference, as it has no real ++c;
impact on the execution of the code. In JavaScript, as you've seen, placing the initial bracket in the next line can lead x
to silent errors. ++
y
[Link] – JavaScript® Notes for Professionals 361 [Link] – JavaScript® Notes for Professionals 362
[Link]("Hello, World")
[1,2,3].join() Chapter 70: Localization
// is transformed to:
[Link]("Hello, World")[(1, 2, 3)].join(); Paramater Details
weekday "narrow", "short", "long"
Return statement: era "narrow", "short", "long"
year "numeric", "2-digit"
return
"something"; month "numeric", "2-digit", "narrow", "short", "long"
// is transformed to day "numeric", "2-digit"
return;
hour "numeric", "2-digit"
"something";
minute "numeric", "2-digit"
second "numeric", "2-digit"
timeZoneName "short", "long"
[Link] – JavaScript® Notes for Professionals 363 [Link] – JavaScript® Notes for Professionals 364
Chapter 71: Geolocation }
default:
return "UNKNOWN_ERROR";
[Link](watchId);
[Link] – JavaScript® Notes for Professionals 365 [Link] – JavaScript® Notes for Professionals 366
Chapter 72: IndexedDB // Transactions use events, just like database open requests. Let's listen for success
[Link] = function() {
[Link]("All done!");
[Link]("by_name", "name"); // Create a new transaction, we'll use the default "readonly" mode and the things store
} var transaction = [Link](["things"]);
};
// Transactions use events, just like database open requests. Let's listen for success
// Handle any errors [Link] = function() {
[Link] = function() { [Link]("All done!");
[Link]("Something went wrong when we tried to request the database!"); };
};
// And make sure we handle errors
[Link] = function() {
Section 72.2: Adding objects [Link]("Something went wrong with our transaction: ", [Link]);
};
Anything that needs to happen with data in an IndexedDB database happens in a transaction. There are a few
// Now that everything is set up, let's get our things store and load some objects!
things to note about transactions that are mentioned in the Remarks section at the bottom of this page.
var store = [Link]("things");
[Link] – JavaScript® Notes for Professionals 367 [Link] – JavaScript® Notes for Professionals 368
// Let's listen so we can see if everything went well
[Link] = function(event) {
// All done, let's log our object to the console
Chapter 73: Modularization Techniques
Section 73.1: ES6 Modules
[Link]([Link]);
};
Version ≥ 6
// That was pretty long for a basic retrieval. If we just want to get just
// the one object and don't care about errors, we can shorten things a lot In ECMAScript 6, when using the module syntax (import/export), each file becomes its own module with a private
[Link]("things").objectStore("things") namespace. Top-level functions and variables do not pollute the global namespace. To expose functions, classes,
.get("coffee_cup"). => [Link]([Link]); and variables for other modules to import, you can use the export keyword.
Section 72.4: Testing for IndexedDB availability Note: Although this is the official method for creating JavaScript modules, it is not supported by any major
browsers right now. However, ES6 Modules are supported by many transpilers.
You can test for IndexedDB support in the current environment by checking for the presence of the
export function greet(name) {
[Link] property:
[Link]("Hello %s!", name);
}
if ([Link]) {
// IndexedDB is available var myMethod = function(param) {
} return "Here's what you said: " + param;
};
export {myMethod}
Using Modules
greet("Bob");
This imports only the myMethod method from our [Link] file.
[Link]("Alice");
[Link] – JavaScript® Notes for Professionals 369 [Link] – JavaScript® Notes for Professionals 370
1. An IIFE (Immediately-Invoked Function Expression) that checks for the module loader that is being Passing the dependent modules as arguments to the factory function
implemented by the user. This will take two arguments; root (a this reference to the global scope) and
factory (the function where we declare our module). The key thing here is that a module can have a dependency and not hold everything up while waiting for it to load,
without the developer having to write complicated code.
2. An anonymous function that creates our module. This is passed as the second argument to the IIFE portion
of the pattern. This function is passed any number of arguments to specify the dependencies of the module. Here's an example of AMD:
Section 73.3: Immediately invoked function expressions (IIFE) Modules can also skip the name and be anonymous. When that's done, they're usually loaded by file name.
Immediately invoked function expressions can be used to create a private scope while producing a public API. define(["jquery", "lodash"], function($, _) { /* factory */ });
AMD is a module definition system that attempts to address some of the common issues with other systems like Here's an example of CommonJS, we'll load Lodash and [Link]' fs module:
CommonJS and anonymous closures.
// Load fs and lodash, we can use them anywhere inside the module
AMD addresses these issues by: var fs = require("fs"),
_ = require("lodash");
Registering the factory function by calling define(), instead of immediately executing it
Passing dependencies as an array of module names, which are then loaded, instead of using globals var myPrivateFn = function(param) {
return "Here's what you said: " + param;
Only executing the factory function once all the dependencies have been loaded and executed
};
[Link] – JavaScript® Notes for Professionals 371 [Link] – JavaScript® Notes for Professionals 372
// Here we export a public `myMethod` that other modules can use
[Link] = function(param) {
return myPrivateFn(param);
Chapter 74: Proxy
};
Parameter Details
target The target object, actions on this object (getting, setting, etc...) will be routed through the handler
You can also export a function as the entire module using [Link]:
handler An object that can define "traps" for intercepting actions on the target object (getting, setting, etc...)
[Link] = function() {
return "Hello!";
A Proxy in JavaScript can be used to modify fundamental operations on objects. Proxies were introduced in ES6. A
}; Proxy on an object is itself an object, that has traps. Traps may be triggered when operations are performed on the
Proxy. This includes property lookup, function calling, modifying properties, adding properties, et cetera. When no
applicable trap is defined, the operation is performed on the proxied object as if there was no Proxy.
In this example, we modify property lookup so that not only the value, but also the type of that value is returned.
We use Reflect to ease this.
let handler = {
get(target, property) {
if () {
return {
value: undefined,
type: 'undefined'
};
}
let value = [Link](target, property);
return {
value: value,
type: typeof value
};
}
};
let handler = {
set(target, prop, value){ // Note that ES6 object syntax is used
if('string' === typeof value){
target[prop] = value + " went through proxy";
}
}
};
[Link] = "ExampleValue";
[Link](object);
// logs: { example: "ExampleValue went through proxy" }
[Link] – JavaScript® Notes for Professionals 373 [Link] – JavaScript® Notes for Professionals 374
// you could also access the object via [Link]
Chapter 75: .postMessage() and
MessageEvent
Parameters
message
targetOrigin
transfer optional
Normally, two different pages, can only directly communicate with each other using JavaScript when they are under
the same origin, even if one of them is embedded into another (e.g. iframes) or one is opened from inside the
other (e.g. [Link]()). With .postMessage(), you can work around this restriction while still staying safe.
You can only use .postMessage() when you have access to both pages' JavaScript code. Since the receiver
needs to validate the sender and process the message accordingly, you can only use this method to communicate
between two scripts you have access to.
We will build an example to send messages to a child window and have the messages be displayed on the child
window. The parent/sender page will be assumed to be [Link] and child/receiver page will be
assumed to be [Link] for the example.
Sending messages
In order to send messages to another window, you need to have a reference to its window object. [Link]()
returns the reference object of the newly opened window. For other methods to obtain a reference to a window
object, see the explanation under otherWindow parameter here.
Add a textarea and a send button that will be used to send messages to child window.
<textarea id="text"></textarea>
<button id="btn">Send Message</button>
Send the text of textarea using .postMessage(message, targetOrigin) when the button is clicked.
[Link]("click", function () {
sendMessage([Link]);
[Link] = "";
});
function sendMessage(message) {
if (!message || ![Link]) return;
[Link]([Link]({
message: message,
time: new Date()
[Link] – JavaScript® Notes for Professionals 375 [Link] – JavaScript® Notes for Professionals 376
}), '[Link] Click here for a JS Fiddle showcasing its usage.
}
In order send and receive JSON objects instead of a simple string, [Link]() and [Link]() methods
can be used. A Transfarable Object can be given as the third optional parameter of the .postMessage(message,
targetOrigin, transfer) method, but browser support is still lacking even in modern browsers.
For this example, since our receiver is assumed to be [Link] page, we enter its url as the
targetOrigin. The value of this parameter should match the origin of the childWindow object for the message to
be send. It is possible to use * as a wildcard but is highly recommended to avoid using the wildcard and always
set this parameter to receiver's specific origin for security reasons.
The code under this part should be put in the receiver page, which is [Link] for our example.
In order to receive messages, the message event of the window should be listened.
[Link]("message", receiveMessage);
When a message is received there are a couple of steps that should be followed to assure security as much as
possible.
The sender should always be validated to make sure the message is received from a trusted sender. After that, the
message itself should be validated to make sure nothing malicious is received. After these two validations, the
message can be processed.
function receiveMessage(ev) {
//Check [Link] to see if it is a trusted sender.
//If you have a reference to the sender, validate [Link]
//We only want to receive messages from [Link] our trusted sender page.
if ([Link] !== "[Link] || [Link] !== [Link])
return;
[Link] – JavaScript® Notes for Professionals 377 [Link] – JavaScript® Notes for Professionals 378
Chapter 76: WeakMap Section 76.5: Removing an element with the key
To remove an element with a specified key, use the .delete() method. It returns true if the element existed and
Section 76.1: Creating a WeakMap object has been removed, otherwise false.
WeakMap object allows you to store key/value pairs. The difference from Map is that keys must be objects and are const obj1 = {},
weakly referenced. This means that if there aren't any other strong references to the key, the element in WeakMap obj2 = {};
can be removed by garbage collector.
const weakmap = new WeakMap([[obj1, 7]]);
[Link]([Link](obj1)); // true
WeakMap constructor has an optional parameter, which can be any iterable object (for example Array) containing
[Link]([Link](obj1)); // false
key/value pairs as two-element arrays. [Link]([Link](obj2)); // false
To get a value associated to the key, use the .get() method. If there's no value associated to the key, it returns Here is a demo of weakmap. I use a very large object as value to show that weak reference does not contribute to
undefined. reference count.
const obj1 = {}, // manually trigger garbage collection to make sure that we are in good status.
obj2 = {}; > [Link]();
undefined
const weakmap = new WeakMap([[obj1, 7]]);
[Link]([Link](obj1)); // 7 // check initial memory use,heapUsed is 4M or so
[Link]([Link](obj2)); // undefined > [Link]();
{ rss: 21106688,
heapTotal: 7376896,
Section 76.3: Assigning a value to the key heapUsed: 4153936,
external: 9059 }
To assign a value to the key, use the .set() method. It returns the WeakMap object, so you can chain .set() calls.
> let wm = new WeakMap();
undefined
const obj1 = {},
obj2 = {};
> const b = new Object();
undefined
const weakmap = new WeakMap();
[Link](obj1, 1).set(obj2, 2);
> [Link]();
[Link]([Link](obj1)); // 1
undefined
[Link]([Link](obj2)); // 2
// heapUsed is still 4M or so
Section 76.4: Checking if an element with the key exists > [Link]();
{ rss: 20537344,
heapTotal: 9474048,
To check if an element with a specified key exits in a WeakMap, use the .has() method. It returns true if it exits,
heapUsed: 3967272,
and otherwise false. external: 8993 }
[Link] – JavaScript® Notes for Professionals 379 [Link] – JavaScript® Notes for Professionals 380
> [Link]();
{ rss: 62652416,
heapTotal: 51437568,
Chapter 77: WeakSet
Section 77.1: Creating a WeakSet object
heapUsed: 45911664,
external: 8951 }
// b reference to null The WeakSet object is used for storing weakly held objects in a collection. The difference from Set is that you can't
> b = null; store primitive values, like numbers or string. Also, references to the objects in the collection are held weakly, which
null means that if there is no other reference to an object stored in a WeakSet, it can be garbage collected.
// garbage collection
The WeakSet constructor has an optional parameter, which can be any iterable object (for example an array). All of
> [Link]();
undefined its elements will be added to the created WeakSet.
[Link] – JavaScript® Notes for Professionals 381 [Link] – JavaScript® Notes for Professionals 382
Chapter 78: Escape Sequences Characters with codes between 0 and 255 can be represented with an escape sequence where \x is followed by the
2-digit hexadecimal character code. For example, the non-breaking space character has code 160 or A0 in base 16,
and so it can be written as \xa0.
Section 78.1: Entering special characters in strings and
regular expressions var str = "ONE\xa0LINE"; // ONE and LINE with a non-breaking space between them
Most printable characters can be included in string or regular expression literals just as they are, e.g. For hex digits above 9, the letters a to f are used, in lowercase or uppercase without distinction.
var str = "ポケモン"; // a valid string var regExp1 = /[\x00-xff]/; // matches any character between U+0000 and U+00FF
var regExp = /[Α-Ωα-ω]/; // matches any Greek letter without diacritics var regExp2 = /[\x00-xFF]/; // same as above
\\x0a
\\u000a
For hex digits above 9, the letters a to f are used, in lowercase or uppercase without distinction. Hexadecimal codes
\\u{a} new in ES6, only in strings
shorter than 4 digits must be left-padded with zeros: \u007A for the small letter "z".
\\012 forbidden in string literals in strict mode and in template strings
Curly bracket Unicode escape sequences
\\cj only in regular expressions Version ≥ 6
Section 78.2: Escape sequence types ES6 extends Unicode support to the full code range from 0 to 0x10FFFF. In order to escape characters with code
greater than 216 - 1, a new syntax for escape sequences was introduced:
Single character escape sequences
\u{???}
Some escape sequences consist of a backslash followed by a single character.
Where the code in curly braces is hexadecimal representation of the code point value, e.g.
For example, in alert("Hello\nWorld");, the escape sequence \n is used to introduce a newline in the string
parameter, so that the words "Hello" and "World" are displayed in consecutive lines. alert("Look! \u{1f440}"); // Look! ????
[Link] – JavaScript® Notes for Professionals 383 [Link] – JavaScript® Notes for Professionals 384
/\105scape/.test("Fun with Escape Sequences"); // true
Chapter 79: Behavioral Design Patterns
In strict mode, octal escape sequences are not allowed inside strings and will produce a syntax error. It is worth to
note that \0, unlike \00 or \000, is not considered an octal escape sequence, and is thus still allowed inside strings Section 79.1: Observer pattern
(even template strings) in strict mode.
The Observer pattern is used for event handling and delegation. A subject maintains a collection of observers. The
Control escape sequences subject then notifies these observers whenever an event occurs. If you've ever used addEventListener then you've
utilized the Observer pattern.
Some escape sequences are only recognized inside regular expression literals (not in strings). These can be used to
escape characters with codes between 1 and 26 (U+0001–U+001A). They consist of a single letter A–Z (case makes function Subject() {
no difference) preceded by \c. The alphabetic position of the letter after \c determines the character code. [Link] = []; // Observers listening to the subject
[Link] = function(observer) {
For example, in the regular expression
// Add an observer if it isn't already being tracked
if ([Link](observer) === -1) {
`/\cG/` [Link](observer);
}
The letter "G" (the 7th letter in the alphabet) refers to the character U+0007, and thus };
[Link] = function(message) {
// Send a message to all observers
[Link](function(observer) {
[Link](message);
});
};
}
function Observer() {
[Link] = function(message) {
// Every observer must implement this function
};
}
Example usage:
function Employee(name) {
[Link] = name;
// Output:
[Link] – JavaScript® Notes for Professionals 385 [Link] – JavaScript® Notes for Professionals 386
// Bob: There is a meeting at 4pm })();
// Jane: There is a meeting at 4pm
function run() {
var yoko = new Participant("Yoko");
Section 79.2: Mediator Pattern var john = new Participant("John");
var paul = new Participant("Paul");
Think of the mediator pattern as the flight control tower that controls planes in the air: it directs this plane to land var ringo = new Participant("Ringo");
now, the second to wait, and the third to take off, etc. However no plane is ever allowed to talk to its peers.
var chatroom = new Chatroom();
This is how mediator works, it works as a communication hub among different modules, this way you reduce [Link](yoko);
[Link](john);
module dependency on each other, increase loose coupling, and consequently portability.
[Link](paul);
[Link](ringo);
This Chatroom example explains how mediator patterns works:
[Link]("All you need is love.");
// each participant is just a module that wants to talk to other modules(other participants) [Link]("I love you John.");
var Participant = function(name) { [Link]("Ha, I heard that!");
[Link] = name;
[Link] = null; [Link]();
}; }
// each participant has method for talking, and also listening to other participants
[Link] = {
send: function(message, to) { Section 79.3: Command
[Link](message, this, to);
}, The command pattern encapsulates parameters to a method, current object state, and which method to call. It is
receive: function(message, from) { useful to compartmentalize everything needed to call a method at a later time. It can be used to issue a "command"
[Link]([Link] + " to " + [Link] + ": " + message);
and decide later which piece of code to use to execute the command.
}
};
There are three components in this pattern:
// chatroom is the Mediator: it is the hub where participants send messages to, and receive messages
from 1. Command Message - the command itself, including the method name, parameters, and state
var Chatroom = function() { 2. Invoker - the part which instructs the command to execute its instructions. It can be a timed event, user
var participants = {}; interaction, a step in a process, callback, or any way needed to execute the command.
3. Receiver - the target of the command execution.
return {
[Link] – JavaScript® Notes for Professionals 387 [Link] – JavaScript® Notes for Professionals 388
Invoker if( preferredBeverage( bevToOrder ) {
[Link]; //false, because "Beer" isn't the final collection item
return bevToOrder; //"Beer"
[Link]();
}
}
Can invoke:
As a Generator
immediately
in response to an event
class FibonacciIterator {
in a sequence of execution constructor() {
as a callback response or in a promise [Link] = 1;
at the end of an event loop [Link] = 1;
}
in any other needed way to invoke a method
next() {
var current = [Link] + [Link];
Receiver
[Link] = [Link];
[Link] = current;
class Instructions { return current;
DoThis( stringArg, numArg, objectArg, arrayArg ) { }
[Link]( `${stringArg}, ${numArg}, ${objectArg}, ${arrayArg}` ); }
}
} var fib = new FibonacciIterator();
[Link](); //2
A client generates a command, passes it to an invoker that either executes it immediately or delays the command, [Link](); //3
[Link](); //5
and then the command acts upon a receiver. The command pattern is very useful when used with companion
patterns to create messaging patterns.
In ECMAScript 2015
In ECMAScript 2015 iterators are a built-in as a method that returns done and value. done is true when the iterator
is at the end of the collection
function preferredBeverage(beverage){
if( beverage == "Beer" ){
return true;
} else {
return false;
}
}
var withPepperoni = new BeverageForPizza(["Cola", "Water", "Beer", "Orange Juice"]);
for( var bevToOrder of withPepperoni ){
[Link] – JavaScript® Notes for Professionals 389 [Link] – JavaScript® Notes for Professionals 390
Chapter 80: Server-sent events [Link]("heartbeat", function(event) {
var status = [Link];
if (status=='OK') {
Example:
Events have names with which they are categorized and sent, and a listener must be setup to listen to each such
event by name. the default event name is message and in order to listen to it you must use the appropriate event
listener, .onmessage
[Link] = function(event) {
var data = [Link]([Link]);
// do something with data
}
The above function will run every time the server will push an event to the client. Data is sent as text/plain, if you
send JSON data you may want to parse it.
name: The name related to the name of the channel the server is emitting events to.
callback: The callback function runs every time an event bound to the channel is emitted, the function provides the
event as an argument.
The following example shows a heartbeat event stream from the server, the server sends events on the heartbeat
channel and this routine will always run when an event in accepted.
[Link] – JavaScript® Notes for Professionals 391 [Link] – JavaScript® Notes for Professionals 392
Chapter 81: Async functions (async/await) }
await (getUnicorn().getSize());
async and await build on top of promises and generators to express asynchronous actions inline. This makes Here we attempt to call getSize() method of the Promise object, which isn't what we want.
asynchronous or callback code much easier to maintain.
Instead, we should use brackets to denote that we first want to wait for the unicorn, and then call getSize()
Functions with the async keyword return a Promise, and can be called with that syntax. method of the result:
Inside an async function the await keyword can be applied to any Promise, and will cause all of the function body async function asyncFunction() {
after the await to be executed after the promise resolves. (await getUnicorn()).getSize();
}
Section 81.1: Introduction Of course. the previous version could be valid in some cases, for example, if the getUnicorn() function was
A function defined as async is a function that can perform asynchronous actions but still look synchronous. The synchronous, but the getSize() method was asynchronous.
way it's done is using the await keyword to defer the function while it waits for a Promise to resolve or reject.
Section 81.3: Async functions compared to Promises
Note: Async functions are a Stage 4 ("Finished") proposal on track to be included in the ECMAScript 2017 standard.
async functions do not replace the Promise type; they add language keywords that make promises easier to call.
For instance, using the promise-based Fetch API: They are interchangeable:
[Link] – JavaScript® Notes for Professionals 393 [Link] – JavaScript® Notes for Professionals 394
const responseCurrent = await fetch('[Link]'); // fetch [Link] from server [Link](async(e) => {
const unicorn = await [Link](); // parse the response as JSON const i = await somePromiseFn(e);
const responseNew = await fetch('new/unicorn', { // send a request to 'new/unicorn' [Link](i);
method: 'post', // using the POST method });
body: [Link]({unicorn}) // pass the unicorn to the request body [Link]('this will print first');
}); })();
const json = await [Link]();
return [Link] // return success property of response
This happens because the callback async function can only pause itself, not the parent async function.
} catch (err) {
[Link]('Error creating unicorn:', err);
}
You could write an asyncForEach function that returns a promise and then you could something like
}
await asyncForEach(async (e) => await somePromiseFn(e), data ) Basically you return a promise
that resolves when all the callbacks are awaited and done. But there are better ways of doing this, and
This async variant of newUnicorn() appears to return a Promise, but really there were multiple await keywords.
that is to just use a loop.
Each one returned a Promise, so really we had a collection of promises rather than a chain.
In fact we can think of it as a function* generator, with each await being a yield new Promise. However, the You can use a for-of loop or a for/while loop, it doesn't really matter which one you pick.
results of each promise are needed by the next to continue the function. This is why the additional keyword async
is needed on the function (as well as the await keyword when calling the promises) as it tells JavaScript to (async() => {
automatically creates an observer for this iteration. The Promise returned by async function newUnicorn() data = [1, 2, 3, 4, 5];
resolves when this iteration completes. for (let e of data) {
const i = await somePromiseFn(e);
Practically, you don't need to consider that; await hides the promise and async hides the generator iteration. [Link](i);
}
[Link]('this will print last');
You can call async functions as if they were promises, and await any promise or any async function. You don't need
})();
to await an async function, just as you can execute a promise without a .then().
But there's another catch. This solution will wait for each call to somePromiseFn to complete before iterating over
You can also use an async IIFE if you want to execute that code immediately:
the next one.
(async () => { This is great if you actually want your somePromiseFn invocations to be executed in order but if you want them to
await makeCoffee() run concurrently, you will need to await on [Link].
[Link]('coffee is ready!')
})() (async() => {
data = [1, 2, 3, 4, 5];
Section 81.4: Looping with async await const p = await [Link]([Link](async(e) => await somePromiseFn(e)));
[Link](...p);
})();
When using async await in loops, you might encounter some of these problems.
[Link] receives an array of promises as its only parameter and returns a promise. When all of the promises
If you just try to use await inside forEach, this will throw an Unexpected token error.
in the array are resolved, the returned promise is also resolved. We await on that promise and when it's resolved
(async() => { all our values are available.
data = [1, 2, 3, 4, 5];
[Link](e => { The above examples are fully runnable. The somePromiseFn function can be made as an async echo function with a
const i = await somePromiseFn(e); timeout. You can try out the examples in the babel-repl with at least the stage-3 preset and look at the output.
[Link](i);
}); function somePromiseFn(n) {
})(); return new Promise((res, rej) => {
setTimeout(() => res(n), 250);
This comes from the fact that you've erroneously seen the arrow function as a block. The await will be in the });
context of the callback function, which is not async. }
The interpreter protects us from making the above error, but if you add async to the forEach callback no errors get
thrown. You might think this solves the problem, but it won't work as expected. Section 81.5: Less indentation
Example: With promises:
[Link] – JavaScript® Notes for Professionals 395 [Link] – JavaScript® Notes for Professionals 396
.then(doAnother)
.then(doSomeMore)
.catch(handleErrors)
Chapter 82: Async Iterators
}
An async function is one that returns a promise. await yields to the caller until the promise resolves and then
continues with the result.
With async functions:
An iterator allows the collection to be looped through with a for-of loop.
async function doTheThing() {
try { An async iterator is a collection where each iteration is a promise which can be awaited using a for-await-of loop.
const doOneThing();
const another = await doAnother(one);
Async iterators are a stage 3 proposal. They are in Chrome Canary 60 with --harmony-async-iteration
return await doSomeMore(another);
} catch (err) {
handleErrors(err); Section 82.1: Basics
}
} A JavaScript Iterator is an object with a .next() method, which returns an IteratorItem, which is an object with
value : <any> and done : <boolean>.
Note how the return is at the bottom, and not at the top, and you use the language's native error-handling
mechanics (try/catch). A JavaScript AsyncIterator is an object with a .next() method, which returns a Promise<IteratorItem>, a promise
for the next value.
Section 81.6: Simultaneous async (parallel) operations To create an AsyncIterator, we can use the async generator syntax:
Often you will want to perform asynchronous operations in parallel. There is direct syntax that supports this in the
/**
async/await proposal, but since await will wait for a promise, you can wrap multiple promises together in
* Returns a promise which resolves after time had passed.
[Link] to wait for them:
*/
const delay = time => new Promise(resolve => setTimeout(resolve, time));
// Not in parallel
async function* delayedRange(max) {
async function getFriendPosts(user) { for (let i = 0; i < max; i++) {
friendIds = await [Link]("friends", {user}, {id: 1}); await delay(1000);
friendPosts = []; yield i;
for (let id in friendIds) { }
friendPosts = [Link]( await [Link]("posts", {user: id}) ); }
}
// etc.
The delayedRange function will take a maximum number, and returns an AsyncIterator, which yields numbers
}
from 0 to that number, in 1 second intervals.
This will do each query to get each friend's posts serially, but they can be done simultaneously:
Usage:
// In parallel
for await (let number of delayedRange(10)) {
[Link](number);
async function getFriendPosts(user) {
}
friendIds = [Link]("friends", {user}, {id: 1});
friendPosts = await [Link]( [Link](id =>
[Link]("posts", {user: id}) The for await of loop is another piece of new syntax, available only inside of async functions, as well as async
); generators. Inside the loop, the values yielded (which, remember, are Promises) are unwrapped, so the Promise is
// etc. hidden away. Within the loop, you can deal with the direct values (the yielded numbers), the for await of loop will
}
wait for the Promises on your behalf.
This will loop over the list of IDs to create an array of promises. await will wait for all promises to be complete. The above example will wait 1 second, log 0, wait another second, log 1, and so on, until it logs 9. At which point the
[Link] combines them into a single promise, but they are done in parallel. AsyncIterator will be done, and the for await of loop will exit.
[Link] – JavaScript® Notes for Professionals 397 [Link] – JavaScript® Notes for Professionals 398
Chapter 83: How to make iterator usable Chapter 84: Tail Call Optimization
inside async callback function Section 84.1: What is Tail Call Optimization (TCO)
When using async callback we need to consider scope. Especially if inside a loop. This simple article shows what
TCO is only available in strict mode
not to do and a simple working example.
As always check browser and JavaScript implementations for support of any language features, and as with any
Section 83.1: Erroneous code, can you spot why this usage of JavaScript feature or syntax, it may change in the future.
key will lead to bugs?
It provides a way to optimise recursive and deeply nested function calls by eliminating the need to push function
var pipeline = {}; state onto the global frame stack, and avoiding having to step down through each calling function by returning
// (...) adding things in pipeline directly to the initial calling function.
The problem is that there is only one instance of var key. All callbacks will share the same key instance. At the time When b() return to a() a()'s frame is popped from the frame stack. It immediately return to the global frame and
thus does not use any of the states save on the stack.
the callback will fire, the key will most likely have been incremented and not pointing to the element we are
receiving the stats for.
TCO recognises that the call from a() to b() is at the tail of function a() and thus there is no need to push a()'s
state onto the frame stack. When b(0) returns rather than returning to a() it returns directly to the global frame.
Section 83.2: Correct Writing Further optimising by eliminating the intermediate steps.
var pipeline = {}; TCO allows for recursive functions to have indefinite recursion as the frame stack will not grow with each recursive
// (...) adding things in pipeline
call. Without TCO recursive function had a limited recursive depth.
var processOneFile = function(key) {
[Link](pipeline[key].path, function(err, stats) {
Note TCO is a JavaScript engine implementation feature, it cannot be implemented via a transpiler if the
if (err) {
// clear that one browser does not support it. There is no additional syntax in the spec required to implement TCO and
delete pipeline[key]; thus there is concern that TCO may break the web. Its release into the world is cautious and may require
return; browser/engine specific flags to be set for the perceivable future.
}
// (...)
pipeline[key].count++;
}); Section 84.2: Recursive loops
};
Tail Call Optimisation makes it possible to safely implement recursive loops without concern for call stack overflow
// verify it is not growing or the overhead of a growing frame stack.
for(var key in pipeline) {
processOneFileInPipeline(key); function indexOf(array, predicate, i = 0) {
} if (0 <= i && i < [Link]) {
if (predicate(array[i])) { return i; }
By creating a new function, we are scoping key inside a function so all callback have their own key instance. return indexOf(array, predicate, i + 1); // the tail call
}
}
indexOf([1,2,3,4,5,6,7], x => x === 5); // returns index of 5 which is 4
[Link] – JavaScript® Notes for Professionals 399 [Link] – JavaScript® Notes for Professionals 400
Chapter 85: Bitwise Operators - Real if(n & 1) {
[Link]("ODD!");
In reality, speed of arithmetic is unlikely to significantly impact how long your code takes to run, unless you are
doing on the order of 100s of millions of computations. But C programmers love this sort of thing!
function isEven(n) {
return n % 2 == 0;
}
function isOdd(n) {
if (isEven(n)) {
return false;
} else {
return true;
}
}
You can do the parity check much more effective and simple:
[Link] – JavaScript® Notes for Professionals 401 [Link] – JavaScript® Notes for Professionals 402
Chapter 86: Tilde ~ let c = ~~0;
let d = ~~1;
let e = ~~2;
// c is now 0
// d is now 1
// e is now 2
The ~ operator looks at the binary representation of the values of the expression and does a bitwise negation
operation on it. g2(n) will essentially round positive numbers down and negative numbers up.
Any digit that is a 1 in the expression becomes a 0 in the result. Any digit that is a 0 in the expression becomes a 1 let a = ~~-2.5; // a is now -2
let b = ~~-1.5; // b is now -1
in the result.
let c = ~~0.5; // c is now 0
let d = ~~1.5; // d is now 1
Section 86.1: ~ Integer let e = ~~2.5; // e is now 2
The following example illustrates use of the bitwise NOT (~) operator on integer numbers.
Section 86.3: Converting Non-numeric values to Numbers
let number = 3;
~~ Could be used on non-numeric values. A numeric expression will be first converted to a number and then
let complement = ~number;
performed bitwise NOT operation on it.
Result of the complement number equals to -4;
If expression cannot be converted to numeric value, it will convert to 0.
Expression Binary value Decimal value
true and false bool values are exceptions, where true is presented as numeric value 1 and false as 0
3 00000000 00000000 00000000 00000011 3
~3 11111111 11111111 11111111 11111100 -4
let a = ~~"-2"; // a is now -2
let b = ~~"1"; // b is now -1
To simplify this, we can think of it as function f(n) = -(n+1). let c = ~~"0"; // c is now 0
let d = ~~"true"; // d is now 0
let a = ~-2; // a is now 1 let e = ~~"false"; // e is now 0
let b = ~-1; // b is now 0 let f = ~~true; // f is now 1
let c = ~0; // c is now -1 let g = ~~false; // g is now 0
let d = ~1; // d is now -2 let h = ~~""; // h is now 0
let e = ~2; // e is now -3
or
Result of the complement number equals to -4;
if ([Link]('a') >= 0) {}
Expression Binary value Decimal value
can be re-written as
3 00000000 00000000 00000000 00000011 3
if (~[Link]('a')) {}
~~3 00000000 00000000 00000000 00000011 3
3.5 00000000 00000011.1 3.5
~~3.5 00000000 00000011 3
Section 86.5: ~ Decimal
The following example illustrates use of the bitwise NOT (~) operator on decimal numbers.
To simplify this, we can think of it as functions f2(n) = -(-(n+1) + 1) and g2(n) = -(-(integer(n)+1) + 1).
To keep the example simple, decimal number 3.5 will be used, cause of it's simple representation in binary format.
f2(n) will leave the integer number as it is.
[Link] – JavaScript® Notes for Professionals 403 [Link] – JavaScript® Notes for Professionals 404
Result of the complement number equals to -4;
Chapter 87: Using JavaScript to get/set
Expression
3.5
Binary value Decimal value
00000000 00000010.1 3.5
CSS custom variables
~3.5 11111111 11111100 -4
Section 87.1: How to get and set CSS variable property values
To simplify this, we can think of it as function f(n) = -(integer(n)+1).
To get a value use the .getPropertyValue() method
let a = ~-2.5; // a is now 1
let b = ~-1.5; // b is now 0 [Link]("--var")
let c = ~0.5; // c is now -1
let d = ~1.5; // c is now -2 To set a value use the .setProperty() method.
let e = ~2.5; // c is now -3
[Link]("--var", "NEW_VALUE")
[Link] – JavaScript® Notes for Professionals 405 [Link] – JavaScript® Notes for Professionals 406
Chapter 88: Selection API Chapter 89: File API, Blobs and FileReaders
Parameter Details Property/Method Description
If the node is a Text node, it is the number of characters from the beginning of startNode to where the error A error that occurred while reading the file.
startOffset range begins. Otherwise, it is the number of child nodes between the beginning of startNode to where readyState Contains the current state of the FileReader.
the range begins.
result Contains the file contents.
If the node is a Text node, it is the number of characters from the beginning of startNode to where the
endOffset range ends. Otherwise, it is the number of child nodes between the beginning of startNode to where onabort Triggered when the operation is aborted.
the range ends. onerror Triggered when an error is encountered.
onload Triggered when the file has loaded.
Section 88.1: Get the text of the selection onloadstart Triggered when the file loading operation has started.
onloadend Triggered when the file loading operation has ended.
let sel = [Link]();
onprogress Triggered whilst reading a Blob.
let text = [Link]();
[Link](text); // logs what the user selected abort() Aborts the current operation.
readAsArrayBuffer(blob) Starts reading the file as an ArrayBuffer.
Alternatively, since the toString member function is called automatically by some functions when converting the readAsDataURL(blob) Starts reading the file as a data url/uri.
object to a string, you don't always have to call it yourself. Starts reading the file as a text file. Not able to read binary files. Use
readAsText(blob[, encoding])
readAsArrayBuffer instead.
[Link]([Link]());
Next, we're going to add a change listener on the file-input. This examples defines the listener via JavaScript, but it
could also be added as attribute on the input element. This listener gets triggered every time a new file has been
selected. Within this callback, we can read the file that was selected and perform further actions (like creating an
image with the contents of the selected file):
[Link] – JavaScript® Notes for Professionals 407 [Link] – JavaScript® Notes for Professionals 408
[Link]('upload').addEventListener('change', showImage); function getFile(event) {
var files = [Link]
function showImage(evt) { , file = files[0];
var files = [Link];
[Link]('Name of the file', [Link]);
if ([Link] === 0) { [Link]('Size of the file', [Link]);
[Link]('No files selected'); }
return;
} You can also get easily the following attributes: lastModified (Timestamp), lastModifiedDate (Date), and type (File
Type)
var reader = new FileReader();
[Link] = function(event) {
var img = new Image(); Section 89.5: Selecting multiple files and restricting file types
[Link] = function() {
[Link](img); The HTML5 file API allows you to restrict which kind of files are accepted by simply setting the accept attribute on a
}; file input, e.g.:
[Link] = [Link];
};
<input type="file" accept="image/jpeg">
[Link](files[0]);
}
Specifying multiple MIME types separated by a comma (e.g. image/jpeg,image/png) or using wildcards (e.g.
image/* for allowing all types of images) give you a quick and powerful way to restrict the type of files you want to
Section 89.3: Slice a file select. Here's an example for allowing any image or video:
The [Link]() method is used to create a new Blob object containing the data in the specified range of bytes of
<input type="file" accept="image/*,video*">
the source Blob. This method is usable with File instances too, since File extends Blob.
Here we slice a file in a specific amount of blobs. This is useful especially in cases where you need to process files By default, the file input lets the user select a single file. If you want to enable multiple file selection, simply add the
that are too large to read in memory all in once. We can then read the chunks one by one using FileReader. multiple attribute:
[Link]('newFile').addEventListener('change', getFile);
[Link] – JavaScript® Notes for Professionals 409 [Link] – JavaScript® Notes for Professionals 410
Chapter 90: Notifications API let notification = new Notification(title, options);
setTimeout(() => {
[Link]()
Section 90.1: Requesting Permission to send notifications }, 4000);
We use [Link] to ask the user if he/she wants to receive notifications from our website. The above code will spawn a notification and close it after 4 seconds.
[Link] = function(event) {
Since Firefox 47 The .requestPermission method can also return a promise when handling the user's decision for
[Link]("you click me and this is my event object: ", event);
granting permission }
new Notification('Hello', { body: 'Hello, world!', icon: 'url to an .ico image' });
Hello
Hello, world!
You can utilize the setTimeout function to auto-close the notification sometime in the future.
[Link] – JavaScript® Notes for Professionals 411 [Link] – JavaScript® Notes for Professionals 412
Chapter 91: Vibration API Chapter 92: Battery Status API
Modern mobile devices include hardware for vibrations. The Vibration API offers Web apps the ability to access this Section 92.1: Battery Events
hardware, if it exists, and does nothing if the device doesn't support it.
// Get the battery API
Section 91.1: Single vibration [Link]().then(function(battery) {
[Link]('chargingchange', function(){
[Link]( 'New charging state: ', [Link] );
Vibrate the device for 100ms:
});
[Link] – JavaScript® Notes for Professionals 413 [Link] – JavaScript® Notes for Professionals 414
Chapter 93: Fluent API list(text) {
const list = new List(text, []);
[Link](list);
[Link] = list;
JavaScript is great for designing fluent API - a consumer-oriented API with focus on developer experience. Combine
return this;
with language dynamic features for optimal results. }
[Link] – JavaScript® Notes for Professionals 415 [Link] – JavaScript® Notes for Professionals 416
Chapter 94: Web Cryptography API Section 94.3: Generating RSA key pair and converting to PEM
format
Section 94.1: Creating digests (e.g. SHA-256) In this example you will learn how to generate RSA-OAEP key pair and how to convert private key from this key pair
to base64 so you can use it with OpenSSL etc. Please note that this process can also be used for public key you just
// Convert string to ArrayBuffer. This step is only necessary if you wish to hash a string, not if have to use prefix and suffix below:
you already got an ArrayBuffer such as an Uint8Array.
var input = new TextEncoder('utf-8').encode('Hello world!');
-----BEGIN PUBLIC KEY-----
-----END PUBLIC KEY-----
// Calculate the SHA-256 digest
[Link]('SHA-256', input)
// Wait for completion NOTE: This example is fully tested in these browsers: Chrome, Firefox, Opera, Vivaldi
.then(function(digest) {
// digest is an ArrayBuffer. There are multiple ways to proceed. function arrayBufferToBase64(arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
// If you want to display the digest as a hexadecimal string, this will work: var byteString = '';
var view = new DataView(digest); for(var i=0; i < [Link]; i++) {
var hexstr = ''; byteString += [Link](byteArray[i]);
for(var i = 0; i < [Link]; i++) { }
var b = view.getUint8(i); var b64 = [Link](byteString);
hexstr += '0123456789abcdef'[(b & 0xf0) >> 4];
hexstr += '0123456789abcdef'[(b & 0x0f)]; return b64;
} }
[Link](hexstr);
function addNewLines(str) {
// Otherwise, you can simply create an Uint8Array from the buffer: var finalString = '';
var digestAsArray = new Uint8Array(digest); while([Link] > 0) {
[Link](digestAsArray); finalString += [Link](0, 64) + '\n';
}) str = [Link](64);
// Catch errors }
.catch(function(err) {
[Link](err); return finalString;
}); }
The current draft suggests to provide at least SHA-1, SHA-256, SHA-384 and SHA-512, but this is no strict requirement function toPem(privateKey) {
var b64 = addNewLines(arrayBufferToBase64(privateKey));
and subject to change. However, the SHA family can still be considered a good choice as it will likely be supported in
var pem = "-----BEGIN PRIVATE KEY-----\n" + b64 + "-----END PRIVATE KEY-----";
all major browsers.
return pem;
Section 94.2: Cryptographically random data }
[Link] – JavaScript® Notes for Professionals 417 [Link] – JavaScript® Notes for Professionals 418
[Link](pem); And now you're done! You can use your imported key in WebCrypto API.
}).catch(function(err) {
[Link](err);
});
});
That's it! Now you have a fully working and compatible RSA-OAEP Private Key in PEM format which you can use
wherever you want. Enjoy!
NOTE: This process can also be used for public key, you only need to change prefix and suffix to:
This example assumes that you have your RSA key pair generated in PEM.
function removeLines(str) {
return [Link]("\n", "");
}
function base64ToArrayBuffer(b64) {
var byteString = [Link](b64);
var byteArray = new Uint8Array([Link]);
for(var i=0; i < [Link]; i++) {
byteArray[i] = [Link](i);
}
return byteArray;
}
function pemToArrayBuffer(pem) {
var b64Lines = removeLines(pem);
var b64Prefix = [Link]('-----BEGIN PRIVATE KEY-----', '');
var b64Final = [Link]('-----END PRIVATE KEY-----', '');
return base64ToArrayBuffer(b64Final);
}
[Link](
"pkcs8",
pemToArrayBuffer(yourprivatekey),
{
name: "RSA-OAEP",
hash: {name: "SHA-256"} // or SHA-512
},
true,
["decrypt"]
).then(function(importedPrivateKey) {
[Link](importedPrivateKey);
}).catch(function(err) {
[Link](err);
});
[Link] – JavaScript® Notes for Professionals 419 [Link] – JavaScript® Notes for Professionals 420
Chapter 95: Security issues When I search for cute puppies, nothing happens!
This is a collection of common JavaScript security issues, like XSS and eval injection. This collection also contains Than Alice successfully gets Bob to run her script while Bob is logged on to his account.
how to mitigate these security issues.
Mitigation:
Section 95.1: Reflected Cross-site scripting (XSS) 1. Escape all angle brackets in searches before returning the search term when no results are found.
2. Don't return the search term when no results are found.
Let's say Joe owns a website that allows you to log on, view puppy videos, and save them to your account. 3. Add a Content Security Policy that refuses to load active content from other domains
Your search (brown puppies), didn't match anything. Try again. Alice goes to Bob's website, creates an account, and goes to her profile settings. She sets her profile description to
I'm actually too lazy to write something here.
On the backend, that message is displayed like this: When her friends view her profile, this code gets run on the server:
if(!searchResults){ if([Link]){
webPage += "<div>Your search (<b>" + searchQuery + "</b>), didn't match anything. Try again."; page += "<div>" + [Link] + "</div>";
} }else{
page += "<div>This person doesn't have a profile description.</div>";
}
However, when Alice searches for <h1>headings</h1>, she gets this back:
Than Alice sets her profile description to <b>I like HTML</b>. When she visits her profile, instead of seeing
Raw HTML:
Your search (<b><h1>headings</h1></b>) didn't match anything. Try again. <b>I like HTML</b>
And:
Then Alice sets her profile to
Whenever someone visits her profile, they get Alice's script run on Bob's website while logged on as their account.
Mitigation
Bob,
[Link] – JavaScript® Notes for Professionals 421 [Link] – JavaScript® Notes for Professionals 422
Section 95.3: Persistent Cross-site scripting from JavaScript could do:
string literals 1. Remove itself from the DOM so that it can't be traced
Let's say that Bob owns a site that lets you post public messages. 2. Steal users' session cookies and enable the script author to log in as and impersonate them
3. Show a fake "Your session has expired. Please log in again." message that sends the user's password to the
The messages are loaded by a script that looks like this: script author.
4. Register a malicious service worker that runs a malicious script on every page visit to that website.
addMessage("Message 1"); 5. Put up a fake paywall demanding that users pay money to access the site that actually goes to the script
addMessage("Message 2");
author.
addMessage("Message 3");
addMessage("Message 4");
addMessage("Message 5"); Please, don't think that XSS won't harm your website and its visitors.
addMessage("Message 6");
Section 95.5: Evaled JSON injection
The addMessage function adds a posted message to the DOM. However, in an effort to avoid XSS, any HTML in
messages posted is escaped. Let's say that whenever someone visits a profile page in Bob's website, the following URL is fetched:
Uncaught SyntaxError: missing ) after argument list Than that data is parsed & inserted:
Why? Because the generated script looks like this: var data = eval("(" + resp + ")");
[Link]("#name").innerText = [Link];
[Link]("#description").innerText = [Link];
addMessage("My mom said: "Life is good. Pie makes it better. "");
If you don't think that's a problem, paste that in your console and see what happens.
Section 95.4: Why scripts from other people can harm your
website and its visitors Mitigation
If you don't think that malicious scripts can harm your site, you are wrong. Here is a list of what a malicious script Use [Link] instead of eval to get JSON. In general, don't use eval, and definitely don't use eval with
[Link] – JavaScript® Notes for Professionals 423 [Link] – JavaScript® Notes for Professionals 424
something a user could control. Eval creates a new execution context, creating a performance hit.
Chapter 96: Same Origin Policy & Cross-
Properly escape " and \ in user data before putting it in JSON. If you just escape the ", than this will happen:
Origin Communication
Hello! \"});alert(1);({
Same-Origin policy is used by web browsers to prevent scripts to be able to access remote content if the remote
address has not the same origin of the script. This prevents malicious scripts from performing requests to other
Will be converted to:
websites to obtain sensitive data.
"Hello! \\"});alert(1);({"
The origin of two addresses is considered the same if both URLs have the same protocol, hostname and port.
Oops. Remember to escape both the \ and ", or just use [Link].
Section 96.1: Safe cross-origin communication with messages
The [Link]() method together with its relative event handler [Link] can be safely used
to enable cross-origin communication.
The postMessage() method of the target window can be called to send a message to another window, which will be
able to intercept it with its onmessage event handler, elaborate it, and, if necessary, send a response back to the
sender window using postMessage() again.
Content of [Link]
Content of [Link]
Content of main_site_script.js:
Content of other_site_script.js:
[Link] – JavaScript® Notes for Professionals 425 [Link] – JavaScript® Notes for Professionals 426
[Link]('message', function(evt) { myfunc({"example_field":true})
However, it is (in some situations) indeed possible to retrieve data from other sources using the following methods.
Please do note that some of them may present hacks or workarounds instead of solutions production system
should rely on.
Method 1: CORS
Most public APIs today allow developers to send data bidirectionally between client and server by enabling a
feature called CORS (Cross-Origin Resource Sharing). The browser will check if a certain HTTP header (Access-
Control-Allow-Origin) is set and that the requesting site's domain is listed in the header's value. If it is, then the
browser will allow establishing AJAX connections.
However, because developers cannot change other servers' response headers, this method can't always be relied
on.
Method 2: JSONP
JSON with Padding is commonly blamed to be a workaround. It is not the most straightforward method, but it still
gets the job done. This method takes advantage of the fact that script files can be loaded from any domain. Still, it is
crucial to mention that requesting JavaScript code from external sources is always a potential security risk and this
should generally be avoided if there's a better solution available.
The data requested using JSONP is typically JSON, which happens to fit the syntax used for object definition in
JavaScript, making this method of transport very simple. A common way to let websites use the external data
obtained via JSONP is to wrap it inside a callback function, which is set via a GET parameter in the URL. Once the
external script file loads, the function will be called with the data as its first parameter.
<script>
function myfunc(obj){
[Link](obj.example_field);
}
</script>
<script src="[Link]
[Link] – JavaScript® Notes for Professionals 427 [Link] – JavaScript® Notes for Professionals 428
Chapter 97: Error Handling Caught error: Invalid something
URIError - creates an instance representing an error that occurs when encodeURI() or decodeURI() are
Version ≥ 6
passed invalid parameters.
Exceptions are to synchronous code what rejections are to promise-based asynchronous code. If an exception is
thrown in a promise handler, its error will be automatically caught and used to reject the promise instead. If you are implementing error handling mechanism you can check which kind of error you are catching from code.
[Link](5) try {
.then(result => { throw new TypeError();
throw new Error("I don't like five"); }
}) catch (e){
.then(result => { if(e instanceof Error){
[Link]("Promise resolved: " + result); [Link]('instance of general Error constructor');
}) }
.catch(error => {
[Link]("Promise rejected: " + error); if(e instanceof TypeError) {
}); [Link]('type error');
}
}
Promise rejected: Error: I don't like five In such case e will be an instance of TypeError. All error types extend the base constructor Error, therefore it's also
Version > 7 an instance of Error.
The async functions proposal—expected to be part of ECMAScript 2017—extends this in the opposite direction. If Keeping that in mind shows us that checking e to be an instance of Error is useless in most cases.
you await a rejected promise, its error is raised as an exception:
Section 97.4: Order of operations plus advanced thoughts
async function main() {
try { Without a try catch block, undefined functions will throw errors and stop execution:
await [Link](new Error("Invalid something"));
} catch (error) {
undefinedFunction("This will not get executed");
[Link]("Caught error: " + error);
[Link]("I will never run because of the uncaught error!");
}
}
main(); Will throw an error and not run the second line:
You need a try catch block, similar to other languages, to ensure you catch that error so code can continue to
[Link] – JavaScript® Notes for Professionals 429 [Link] – JavaScript® Notes for Professionals 430
execute: Also, you shouldn't wrap every variable and function in a try/catch block, because these are simple examples that
will only ever occur once until you fix them. However, for objects, functions and other variables that you know exist,
try { but you don't know whether their properties or sub-processes or side-effects will exist, or you expect some error
undefinedFunction("This will not get executed");
states in some circumstances, you should abstract your error handling in some sort of manner. Here is a very basic
} catch(error) {
[Link]("An error occurred!", error);
example and implementation.
} finally {
[Link]("The code-block has finished"); Without a protected way to call untrusted or exception throwing methods:
}
[Link]("I will run because we caught the error!"); function foo(a, b, c) {
[Link](a, b, c);
throw new Error("custom error!");
Now, we've caught the error and can be sure that our code is going to execute
}
try {
// An error occurred! ReferenceError: undefinedFunction is not defined(…) foo(1, 2, 3);
// The code-block has finished } catch(e) {
// I will run because we caught the error! try {
foo(4, 5, 6);
What if an error occurs in our catch block!? } catch(e2) {
[Link]("We had to nest because there's currently no other way...");
}
try {
[Link](e);
undefinedFunction("This will not get executed");
}
} catch(error) {
// 1 2 3
otherUndefinedFunction("Uh oh... ");
// 4 5 6
[Link]("An error occurred!", error);
// We had to nest because there's currently no other way...
} finally {
[Link]("The code-block has finished"); // Error: custom error!(…)
}
[Link]("I won't run because of the uncaught error in the catch block!"); And with protection:
We won't process the rest of our catch block, and execution will halt except for the finally block. function foo(a, b, c) {
[Link](a, b, c);
// The code-block has finished throw new Error("custom error!");
}
// Uncaught ReferenceError: otherUndefinedFunction is not defined(…)
function protectedFunction(fn, ...args) {
try {
You could always nest your try catch blocks.. but you shouldn't because that will get extremely messy.. [Link](this, args);
} catch (e) {
try { [Link]("caught error: " + [Link] + " -> " + [Link]);
undefinedFunction("This will not get executed"); }
} catch(error) { }
try {
otherUndefinedFunction("Uh oh... "); protectedFunction(foo, 1, 2, 3);
} catch(error2) { protectedFunction(foo, 4, 5, 6);
[Link]("Too much nesting is bad for my heart and soul...");
} // 1 2 3
[Link]("An error occurred!", error); // caught error: Error -> custom error!
} finally { // 4 5 6
[Link]("The code-block has finished"); // caught error: Error -> custom error!
}
[Link]("I will run because we caught the error!"); We catch errors and still process all the expected code, though with a somewhat different syntax. Either way will
work, but as you build more advanced applications you will want to start thinking about ways to abstract your error
Will catch all errors from the previous example and log the following: handling.
So, how can we catch all errors!? For undefined variables and functions: you can't.
[Link] – JavaScript® Notes for Professionals 431 [Link] – JavaScript® Notes for Professionals 432
Chapter 98: Global error handling in new Image().src = '/exampleErrorReporting?stack=' + encodeURIComponent(stack);
browsers // window.DEBUG_ENVIRONMENT a configurable property that may be set to true somewhere else for
debugging and testing purposes.
if (window.DEBUG_ENVIRONMENT) {
Parameter Details alert('Client-side script failed: ' + stack);
}
Some browsers will call the event handler with just one argument, an Event object. However,
}
eventOrMessage other browsers, especially the older ones and older mobile ones will supply a String message as
a first argument.
If a handler is called with more than 1 argument, the second argument usually is an URL of a
url
JavaScript file that is the source of the problem.
If a handler is called with more than 1 argument, the third argument is a line number inside the
lineNumber
JavaScript source file.
If a handler is called with more than 1 argument, the fourth argument is the column number
colNumber
inside the JavaScript source file.
If a handler is called with more than 1 argument, the fifth argument is sometimes an Error object
error
describing the problem.
// Some browsers (at least Firefox) don't report line and column numbers
// when event is handled through [Link]('error', fn). That's why
// a more reliable approach is to set an event listener via direct assignment.
[Link] = function (eventOrMessage, url, lineNumber, colNumber, error) {
if (hasLoggedOnce || !eventOrMessage) {
// It does not make sense to report an error if:
// 1. another one has already been reported -- the page has an invalid state and may produce
way too many errors.
// 2. the provided information does not make sense (!eventOrMessage -- the browser didn't
supply information for some reason.)
return;
}
hasLoggedOnce = true;
if (typeof eventOrMessage !== 'string') {
error = [Link];
url = [Link] || [Link];
lineNumber = [Link] || [Link];
colNumber = [Link] || [Link];
eventOrMessage = [Link] || [Link] || [Link] ||
[Link];
}
if (error && [Link]) {
eventOrMessage = [eventOrMessage, '; Stack: ', [Link], '.'].join('');
}
var jsFile = (/[^/]+\.js/[Link](url || '') || [])[0] || 'inlineScriptOrDynamicEvalCode',
stack = [eventOrMessage, ' Occurred in ', jsFile, ':', lineNumber || '?', ':', colNumber ||
'?'].join('');
// shortening the message a bit so that it is more likely to fit into browser's URL length limit
(which is 2,083 in some browsers)
stack = [Link](/https?\:\/\/[^/]+/gi, '');
// calling the server-side handler which should probably register the error in a database or a
log file
[Link] – JavaScript® Notes for Professionals 433 [Link] – JavaScript® Notes for Professionals 434
Chapter 99: Debugging 1. Press F12 to open Developer Tools
2. Switch to the Sources tab (Chrome) or Debugger tab (Firefox)
3. Press Ctrl + P and type the name of your JavaScript file
Section 99.1: Interactive interpreter variables 4. Press Enter to open it.
Note that these only work in the developer tools of certain browsers. Internet Explorer or Edge
$_ gives you the value of whatever expression was evaluated last. 1. Press F12 to open Developer Tools
2. Switch to the Debugger tab.
"foo" // "foo" 3. Use the folder icon near the upper-left corner of the window to open a file-selection pane; you can find your
$_ // "foo" JavaScript file there.
Safari
$0 refers to the DOM element currently selected in the Inspector. So if <div id="foo"> is highlighted:
¹ alias to either [Link] or [Link] 1. Click the Debug button on the left or Ctrl + Shift + D
2. If not already done, create a launch configuration file ([Link]) by pressing the gear icon.
Section 99.2: Breakpoints 3. Run the code from VSC by pressing the green play button or hit F5 .
Tip: You can also utilise the conditional breakpoints in browser's dev tools. These help in skipping unnecessary
1. From code, using the debugger; statement.
breaks in execution. Example scenario: you want to examine a variable in a loop exactly at 5th iteration.
2. From the browser, using the Developer Tools.
3. From an Integrated Development Environment (IDE).
Debugger Statement
You can place a debugger; statement anywhere in your JavaScript code. Once the JS interpreter reaches that line, it
will stop the script execution, allowing you to inspect variables and step through your code.
Developer Tools
Section 99.3: Using setters and getters to find what changed
a property
The second option is to add a breakpoint directly into the code from the browser's Developer Tools.
Let's say you have an object like this:
Opening the Developer Tools
Chrome or Firefox var myObject = {
[Link] – JavaScript® Notes for Professionals 435 [Link] – JavaScript® Notes for Professionals 436
name: 'Peter' You can use different console methods to highlight your output in different ways. Other methods are also useful for
}
more advanced debugging.
Later in your code, you try to access [Link] and you get George instead of Peter. You start wondering who For more documentation, information on compatibility, and instructions on how to open your browser's console,
changed it and where exactly it was changed. There is a way to place a debugger (or something else) on every set see the Console topic.
(every time someone does [Link] = 'something'):
Note: if you need to support IE9, either remove [Link] or wrap its calls as follows, because console is
var myObject = { undefined until the Developer Tools are opened:
_name: 'Peter',
set name(name){debugger;this._name=name}, if (console) { //IE9 workaround
get name(){return this._name} [Link]("test");
} }
Note that we renamed name to _name and we are going to define a setter and a getter for name.
Section 99.5: Automatically pausing execution
set name is the setter. That is a sweet spot where you can place debugger, [Link](), or anything else you
In Google Chrome, you can pause execution without needing to place breakpoints.
need for debugging. The setter will set the value for name in _name. The getter (the get name part) will read the
value from there. Now we have a fully functional object with debugging functionality.
Pause on Exception: While this button is toggled on, if your program hits an unhandled exception, the
Most of the time, though, the object that gets changed is not under our control. Fortunately, we can define setters program will pause as if it had hit a breakpoint. The button can be found near Execution Controls and is useful for
and getters on existing objects to debug them. locating errors.
// First, save the name to _name, because we are going to use name for setter/getter You can also pause execution when an HTML tag (DOM node) is modified, or when its attributes are changed. To do
otherObject._name = [Link]; that, right click the DOM node on the Elements tab and select "Break on...".
[Link] – JavaScript® Notes for Professionals 437 [Link] – JavaScript® Notes for Professionals 438
Section 99.8: Stepping through code Chapter 100: Unit Testing JavaScript
Once you've paused execution on a breakpoint, you may want to follow execution line-by-line to observe what
happens. Open your browser's Developer Tools and look for the Execution Control icons. (This example uses the Section 100.1: Unit Testing Promises with Mocha, Sinon, Chai
icons in Google Chrome, but they'll be similar in other browsers.) and Proxyquire
Resume: Unpause execution. Shorcut: F8 (Chrome, Firefox) Here we have a simple class to be tested that returns a Promise based on the results of an external
ResponseProcessor that takes time to execute.
Step Over: Run the next line of code. If that line contains a function call, run the whole function and move to
the next line, rather than jumping to wherever the function is defined. Shortcut : F10 (Chrome, Firefox, IE/Edge), For simplicity we'll assume that the processResponse method won't ever fail.
F6 (Safari)
import {processResponse} from '../utils/response_processor';
Step Into: Run the next line of code. If that line contains a function call, jump into the function and pause there. const ping = () => {
Shortcut : F11 (Chrome, Firefox, IE/Edge), F7 (Safari) return new Promise((resolve, _reject) => {
const response = processResponse(data);
resolve(response);
Step Out: Run the rest of the current function, jump back to where the function was called from, and pause at
});
the next statement there. Shortcut : Shift + F11 (Chrome, Firefox, IE/Edge), F8 (Safari) }
Use these in conjunction with the Call Stack, which will tell you which function you're currently inside of, which [Link] = ping;
function called that function, and so forth.
To test this we can leverage the following tools.
See Google's guide on "How to Step Through the Code" for more details and advice.
1. mocha
Links to browser shortcut key documentation:
2. chai
3. sinon
Chrome
4. proxyquire
Firefox
5. chai-as-promised
IE
Edge
I use the following test script in my [Link] file.
Safari
"test": "NODE_ENV=test mocha --compilers js:babel-core/register --require
./test/unit/test_helper.js --recursive test/**/*_spec.js"
This allows me to use es6 syntax. It references a test_helper that will look like
[Link](sinonChai);
[Link](chaiAsPromised);
sinonStubPromise(sinon);
Proxyquire allows us to inject our own stub in the place of the external ResponseProcessor. We can then use sinon
to spy on that stub's methods. We use the extensions to chai that chai-as-promised injects to check that the
ping() method's promise is fullfilled, and that it eventually returns the required response.
let formattingStub = {
wrapResponse: () => {}
[Link] – JavaScript® Notes for Professionals 439 [Link] – JavaScript® Notes for Professionals 440
} let pingWrapper = proxyquire('../src/pingWrapper', {
'./ping': pingStub
let ping = proxyquire('../../../src/api/ping', { });
'../utils/formatting': formattingStub
}); describe('pingWrapper', () => {
let pingSpy;
describe('ping', () => { const response = 'some response';
let wrapResponseSpy, pingResult;
const response = 'some response'; beforeEach(() => {
pingSpy = [Link](pingStub, 'ping').returnsPromise();
beforeEach(() => { [Link](response);
wrapResponseSpy = [Link](formattingStub, 'wrapResponse').returns(response); pingWrapper();
pingResult = ping(); });
})
afterEach(() => {
afterEach(() => { [Link]();
[Link](); });
})
it('wraps the ping', () => {
it('returns a fullfilled promise', () => { expect(pingSpy).[Link](response);
expect(pingResult).[Link]; });
}) });
Now instead let's assume you wish to test something that uses the response from ping. function assert( outcome, description ) {
var passFail = outcome ? 'pass' : 'fail';
[Link](passFail, ': ', description);
import {ping} from './ping';
return outcome;
};
const pingWrapper = () => {
[Link]((response) => {
// do something with the response The popular assertion method above shows us one quick and easy way to assert a value in most web browsers and
}); interpreters like [Link] with virtually any version of ECMAScript.
}
A good unit test is designed to test a discreet unit of code; usually a function.
[Link] = pingWrapper;
As before, Proxyquire allows us to inject our own stub in the place of the external dependency, in this case the In the example above, the return value from the function add(x, y) or 5 + 20 is clearly 25, so our assertion of 24
ping method we tested previously. We can then use sinon to spy on that stub's methods and leverage sinon-stub- should fail, and the assert method will log a "fail" line.
promise to allow us to returnsPromise. This promise can then be resolved or rejected as we wish in the test, in
If we simply modify our expected assertion outcome, the test will succeed and the resulting output would look
order to test the wrapper's response to that.
something like this.
import {expect} from 'chai';
import sinon from 'sinon'; assert( result == 25, 'add(5, 20) should return 25...');
import proxyquire from 'proxyquire';
console output:
let pingStub = {
ping: () => {} > pass: should return 25...
};
This simple assertion can assure that in many different cases, your "add" function will always return the expected
[Link] – JavaScript® Notes for Professionals 441 [Link] – JavaScript® Notes for Professionals 442
result and requires no additional frameworks or libraries to work.
Chapter 101: Evaluating JavaScript
A more rigorous set of assertions would look like this (using var result = add(x,y) for each assertion):
Parameter Details
assert( result == 0, 'add(0, 0) should return 0...'); string The JavaScript to be evaluated.
assert( result == -1, 'add(0, -1) should return -1...');
assert( result == 1, 'add(0, 1) should return 1...'); In JavaScript, the eval function evaluates a string as if it were JavaScript code. The return value is the result of the
evaluated string, e.g. eval('2 + 2') returns 4.
And console output would be this:
eval is available in the global scope. The lexical scope of the evaluation is the local scope unless invoked indirectly
> pass: should return 0... (e.g. var geval = eval; geval(s);).
> pass: should return -1...
> pass: should return 1...
The use of eval is strongly discouraged. See the Remarks section for details.
We can now safely say that add(x,y)… should return the sum of two integers. We can roll these up into
something like this:
Section 101.1: Evaluate a string of JavaScript statements
var x = 5;
function test__addsIntegers() {
var str = "if (x == 5) {[Link]('z is 42'); z = 42;} else z = 0; ";
// number of assertions to be reduced and added as Booleans The use of eval is strongly discouraged. See the Remarks section for details.
var assertions = [
}
var res = a + b + c;
}
200
4
27
The use of eval is strongly discouraged. See the Remarks section for details.
[Link] – JavaScript® Notes for Professionals 443 [Link] – JavaScript® Notes for Professionals 444
Chapter 102: Linters - Ensuring code case '*':
case 'x':
quality {
result = a * b;
break;
JSHint is an open source tool which detects errors and potential problems in JavaScript code. // JSHint disable error for variable not defined, because it is defined in another file
/* jshint -W117 */
To lint your JavaScript you have two options. globalVariable = '[Link]';
/* jshint +W117 */
1. Go to [Link] and paste your code in there on line text editor.
2. Install JSHint in your IDE. More configuration options are documented at [Link]
Atom: linter-jshint (must have Linter plugin installed)
Sublime Text: JSHint Gutter and/or Sublime Linter Section 102.2: ESLint / JSCS
Vim: [Link] or [Link]
Visual Studio: VSCode JSHint ESLint is a code style linter and formatter for your style guide much like JSHint. ESLint merged with JSCS in April of
2016. ESLint does take more effort to set up than JSHint, but there are clear instructions on their website for getting
A benefit of adding it to your IDE is that you can create a JSON configuration file named .jshintrc that will be used started.
when linting your program. This is convent if you want to share configurations between projects.
A sample configuration for ESLint is as follows:
Example .jshintrc file
{
{ "rules": {
"-W097": false, // Allow "use strict" at document level "semi": ["error", "always"], // throw an error when semicolons are detected
"browser": true, // defines globals exposed by modern browsers "quotes": ["error", "double"] // throw an error when double quotes are detected
[Link] }
"curly": true, // requires you to always put curly braces around blocks in loops and }
conditionals [Link]
"devel": true, // defines globals that are usually used for logging poor-man's debugging:
A sample configuration file where ALL rules are set to off, with descriptions for what they do can be found here.
console, alert, etc. [Link]
// List global variables (false means read only)
"globals": { Section 102.3: JSLint
"globalVar": true
}, JSLint is the trunk from which JSHint branched. JSLint takes a much more opinionated stance on how to write
"jquery": true, // This option defines globals exposed by the jQuery JavaScript library.
JavaScript code, pushing you towards only using the parts Douglas Crockford deems to be its "good parts", and
"newcap": false,
// List any global functions or const vars
away from any code that Crockford believes to have a better solution. The following StackOverflow thread may help
"predef": [ you decide which linter is right for you. While there are differences (here are some brief comparisons between it
"GlobalFunction", and JSHint / ESLint), each option is extremely customizable.
"GlobalFunction2"
], For a more information about configuring JSLint check out NPM or github.
"undef": true, // warn about undefined vars
"unused": true // warn about unused vars
}
switch(operation)
{
case '+'
{
result = a + b;
break;
}
[Link] – JavaScript® Notes for Professionals 445 [Link] – JavaScript® Notes for Professionals 446
Chapter 103: Anti-patterns Chapter 104: Performance Tips
Section 103.1: Chaining assignments in var declarations JavaScript, like any language, requires us to be judicious in the use of certain language features. Overuse of some
features can decrease performance, while some techniques can be used to increase performance.
Chaining assignments as part of a var declaration will create global variables unintentionally.
Section 104.1: Avoid try/catch in performance-critical
For example:
functions
(function foo() {
Some JavaScript engines (for example, the current version of [Link] and older versions of Chrome before
var a = b = 0;
})() Ignition+turbofan) don't run the optimizer on functions that contain a try/catch block.
[Link]('a: ' + a);
[Link]('b: ' + b); If you need to handle exceptions in performance-critical code, it can be faster in some cases to keep the try/catch in
a separate function. For example, this function will not be optimized by some implementations:
Will result in:
function myPerformanceCriticalFunction() {
Uncaught ReferenceError: a is not defined try {
'b: 0' // do complex calculations here
} catch (e) {
[Link](e);
In the above example, a is local but b becomes global. This is because of the right to left evaluation of the = }
operator. So the above code actually evaluated as }
var a = (b = 0); However, you can refactor to move the slow code into a separate function (that can be optimized) and call it from
inside the try block.
The correct way to chain var assignments is:
// This function can be optimized
var a, b; function doCalculations() {
a = b = 0; // do complex calculations here
}
Or:
// Still not always optimized, but it's not doing much so the performance doesn't matter
function myPerformanceCriticalFunction() {
var a = 0, b = a; try {
doCalculations();
This will make sure that both a and b will be local variables. } catch (e) {
[Link](e);
}
}
Note that optimizations like this should be made carefully and with actual evidence based on profiling your code. As
JavaScript engines get better, it could end up hurting performance instead of helping, or making no difference at all
(but complicating the code for no reason). Whether it helps, hurts, or makes no difference can depend on a lot of
factors, so always measure the effects on your code. That's true of all optimizations, but especially micro-
optimizations like this that depend on low-level details of the compiler/runtime.
The issue here is that every update in the DOM interface causes the browser to re-render the screen. If an update
[Link] – JavaScript® Notes for Professionals 447 [Link] – JavaScript® Notes for Professionals 448
changes the layout of an element in the page, the entire page layout needs to be re-computed, and this is very Performance interface that represents timing-related performance information for the given page (only available in
performance-heavy even in the simplest of cases. The process of re-drawing a page is known as reflow and can browsers).
cause a browser to run slowly or even become unresponsive.
[Link] on [Link] gives you timing information as [seconds, nanoseconds] tuples. Called without argument
The consequence of updating the document too frequently is illustrated with the following example of adding items it returns an arbitrary time but called with a previously returned value as argument it returns the difference
to a list. between the two executions.
Consider the following document containing a <ul> element: Console timers [Link]("labelName") starts a timer you can use to track how long an operation takes. You
give each timer a unique label name, and may have up to 10,000 timers running on a given page. When you call
<!DOCTYPE html> [Link]("labelName") with the same name, the browser will finish the timer for given name and output
<html>
the time in milliseconds, that elapsed since the timer was started. The strings passed to time() and timeEnd() must
<body>
<ul id="list"></ul>
match otherwise the timer will not finish.
</body>
</html> [Link] function [Link]() returns current Timestamp in milliseconds, which is a Number representation of
time since 1 January 1970 00:00:00 UTC until now. The method now() is a static method of Date, therefore you
We add 5000 items to the list looping 5000 times (you can try this with a larger number on a powerful computer to always use it as [Link]().
increase the effect).
Example 1 using: [Link]()
var list = [Link]("list");
for(var i = 1; i <= 5000; i++) {
In this example we are going to calculate the elapsed time for the execution of our function, and we are going to
[Link] += `<li>item ${i}</li>`; // update 5000 times use the [Link]() method that returns a DOMHighResTimeStamp, measured in milliseconds, accurate to
} one thousandth of a millisecond.
In this case, the performance can be improved by batching all 5000 changes in one single DOM update. let startTime, endTime;
Most performance tips are very dependent of the current state of JS engines and are expected to be only relevant In this example we are going to calculate the elapsed time for the initialization of a big array (1 million values), and
at a given time. The fundamental law of performance optimization is that you must first measure before trying to we are going to use the [Link]() method
optimize, and measure again after a presumed optimization.
let t0 = [Link](); //stores current Timestamp in milliseconds since 1 January 1970 00:00:00 UTC
To measure code execution time, you can use different time measurement tools like: let arr = []; //store empty array
for (let i = 0; i < 1000000; i++) { //1 million iterations
[Link](i); //push current i value
[Link] – JavaScript® Notes for Professionals 449 [Link] – JavaScript® Notes for Professionals 450
} function checkCache(val) {
[Link]([Link]() - t0); //print elapsed time between stored t0 and now if (val in cache) {
[Link]('It was in the cache :D');
return cache[val]; // return cached
Example 3 using: [Link]("label") & [Link]("label")
} else {
cache[val] = factorial(val); // we cache it
In this example we are doing the same task as in Example 2, but we are going to use the [Link]("label") &
return cache[val]; // and then return it
[Link]("label") methods }
[Link]("t"); //start new timer for label name: "t" /* Other alternatives for checking are:
let arr = []; //store empty array || [Link](val) or !!cache[val]
for(let i = 0; i < 1000000; i++) { //1 million iterations || but wouldn't work if the results of those
[Link](i); //push current i value || executions were falsy values.
} */
[Link]("t"); //stop the timer for label name: "t" and print elapsed time }
let start = [Link](); /* We return the function that checks, not the one
|| that computes because it happens to be recursive,
// long execution here, maybe asynchronous || if it weren't you could avoid creating an extra
|| function in this self-invoking closure function.
let diff = [Link](start); */
// returns for example [ 1, 2325 ] return checkCache;
[Link](`Operation took ${diff[0] * 1e9 + diff[1]} nanoseconds`); }());
// logs: Operation took 1000002325 nanoseconds
We could hard code our own dictionary from 1 to god-knows-what number with their corresponding factorials but,
function memoize(func) {
I'm not sure if I advise that! Let's create a memoizer, shall we? let cache = {};
var fact = (function() { // You can opt for not naming the function
var cache = {}; // Initialise a memory cache object function memoized(...args) {
const argsKey = [Link](args);
// Use and return this function to check if val is cached
[Link] – JavaScript® Notes for Professionals 451 [Link] – JavaScript® Notes for Professionals 452
// The same alternatives apply for this example p = new P();
if (argsKey in cache) { if (index > 5000000) {
[Link](argsKey + ' was/were in cache :D'); p.x = "some_string";
return cache[argsKey]; }
} else {
cache[argsKey] = [Link](null, args); // Cache it return p;
return cache[argsKey]; // And then return it });
} big_array.reduce((sum, p)=> sum + [Link], 0);
} }
return p;
const newFunction = memoize(oldFunction);
});
big_array.reduce((sum, p)=> sum + [Link], 0);
// Assuming new oldFunction just sums/concatenates:
}
newFunction('meaning of life', 42);
// -> "meaning of life42"
(function perform(){
newFunction('meaning of life', 42); // again
var start = [Link]();
// => ["meaning of life",42] was/were in cache :D
f1();
// -> "meaning of life42"
var duration = [Link]() - start;
Section 104.5: Initializing object properties with null [Link]('duration of f1 ' + duration);
All modern JavaScript JIT compilers trying to optimize code based on expected object structures. Some tip from
start = [Link]();
mdn. f2();
duration = [Link]() - start;
Fortunately, the objects and properties are often "predictable", and in such cases their underlying [Link]('duration of f2 ' + duration);
structure can also be predictable. JITs can rely on this to make predictable accesses faster. })()
Time for some testing. In my test, I'm creating a big array of some class instances with a for loop. Within the loop,
I'm assigning the same string to all object's "x" property before array initialization. If constructor initializes "x" As we can see, the performance improvements are very different between the two.
property with null, array always processes better even if it's doing extra statement.
Section 104.6: Reuse objects rather than recreate
This is code:
Example A
function f1() {
var i,a,b,len;
var P = function () {
a = {x:0,y:0}
[Link] = 1
function test(){ // return object created each call
};
return {x:0,y:0};
var big_array = new Array(10000000).fill(1).map((x, index)=> {
}
[Link] – JavaScript® Notes for Professionals 453 [Link] – JavaScript® Notes for Professionals 454
function test1(a){ // return object supplied }
a.x=0;
a.y=0;
For every iteration in for loop, the engine will lookup items, lookup the length attribute within items, lookup items
return a;
}
again, lookup the value at index i of items, and then finally lookup global_variable, first trying the local scope
before checking the global scope.
for(i = 0; i < 100; i ++){ // Loop A
b = test(); A performant rewrite of the above function is:
}
function foo(){
for(i = 0; i < 100; i ++){ // Loop B var local_variable = 0;
b = test1(a); for (var i=0, li=[Link]; i<li; i++) {
} local_variable += items[i];
}
Loop B is 4 (400%) times faster than Loop A return local_variable;
}
It is very inefficient to create a new object in performance code. Loop A calls function test() which returns a new
object every call. The created object is discarded every iteration, Loop B calls test1() that requires the object For every iteration in the rewritten for loop, the engine will lookup li, lookup items, lookup the value at index i,
returns to be supplied. It thus uses the same object and avoids allocation of a new object, and excessive GC hits. and lookup local_variable, this time only needing to check the local scope.
(GC were not included in the performance test)
Section 104.8: Be consistent in use of Numbers
Example B
var i,a,b,len; If the engine is able to correctly predict you're using a specific small type for your values, it will be able to optimize
a = {x:0,y:0} the executed code.
function test2(a){
return {x : a.x * 10,y : a.x * 10}; In this example, we'll use this trivial function summing the elements of an array and outputting the time it took:
}
function test3(a){
// summing properties
a.x= a.x * 10;
var sum = (function(arr){
a.y= a.y * 10;
var start = [Link]();
return a;
var sum = 0;
}
for (var i=0; i<[Link]; i++) {
for(i = 0; i < 100; i++){ // Loop A
sum += arr[i];
b = test2({x : 10, y : 10});
}
}
var diffSum = [Link](start);
for(i = 0; i < 100; i++){ // Loop B
[Link](`Summing took ${diffSum[0] * 1e9 + diffSum[1]} nanoseconds`);
a.x = 10;
return sum;
a.y = 10;
})(arr);
b = test3(a);
}
Let's make an array and sum the elements:
Loop B is 5 (500%) times faster than loop A
var N = 12345,
arr = [];
Section 104.7: Prefer local variables to globals, attributes, for (var i=0; i<N; i++) arr[i] = [Link]();
and indexed values
Result:
JavaScript engines first look for variables within the local scope before extending their search to larger scopes. If the
variable is an indexed value in an array, or an attribute in an associative array, it will first look for the parent array
Summing took 384416 nanoseconds
before it finds the contents.
This has implications when working with performance-critical code. Take for instance a common for loop: Now, let's do the same but with only integers:
[Link] – JavaScript® Notes for Professionals 455 [Link] – JavaScript® Notes for Professionals 456
Summing took 180520 nanoseconds Chapter 105: Memory eciency
Summing integers took half the time here. Section 105.1: Drawback of creating true private method
Engines don't use the same types you have in JavaScript. As you probably know, all numbers in JavaScript are One drawback of creating private method in JavaScript is memory-inefficient because a copy of the private method
IEEE754 double precision floating point numbers, there's no specific available representation for integers. But will be created every time a new instance is created. See this simple example.
engines, when they can predict you only use integers, can use a more compact and faster to use representation, for
example, short integers. function contact(first, last) {
[Link] = first;
[Link] = last;
This kind of optimization is especially important for computation or data intensive applications.
[Link];
// private method
var formatPhoneNumber = function(number) {
// format phone number based on input
};
// public method
[Link] = function(number) {
[Link] = formatPhoneNumber(number);
};
}
When you create few instances, they all have a copy of formatPhoneNumber method
Thus, would be great to avoid using private method only if it's necessary.
[Link] – JavaScript® Notes for Professionals 457 [Link] – JavaScript® Notes for Professionals 458
Appendix A: Reserved Keywords false protected
ECMAScript 5 / 5.1
Certain words - so-called keywords - are treated specially in JavaScript. There's a plethora of different kinds of
keywords, and they have changed in different versions of the language. There was no change since ECMAScript 3.
Section A.1: Reserved Keywords ECMAScript 5 removed int, byte, char, goto, long, final, float, short, double, native, throws, boolean, abstract,
volatile, transient, and synchronized; it added let and yield.
JavaScript has a predefined collection of reserved keywords which you cannot use as variables, labels, or
A—F F—P P—Z
function names.
break finally public
ECMAScript 1
case for return
Version = 1
A—E E—R S—Z catch function static
break export super class if super
case extends switch const implements switch
catch false this continue import this
class finally throw debugger in throw
const for true default instanceof true
continue function try delete interface try
debugger if typeof do let typeof
default import var else new var
delete in void enum null void
do new while export package while
else null with extends private with
enum return false protected yield
ECMAScript 2
implements, let, private, public, interface, package, protected, static, and yield are disallowed in
Added 24 additional reserved keywords. (New additions in bold). strict mode only.
[Link] – JavaScript® Notes for Professionals 459 [Link] – JavaScript® Notes for Professionals 460
present, but they might at some future time, so they cannot be used as identifiers. Syntax
enum Identifier ::
IdentifierName but not ReservedWord
The following are only reserved when they are found in strict mode code:
By specification, a ReservedWord is:
implements package public
interface private `static'
Section 7.6.1
let protected
With regards to reserved words there is a small distinctions between the "Identifiers" used for the likes of variable or ObjectLiteral :
function names and the "Identifier Names" allowed as properties of composite data types. { }
{ PropertyNameAndValueList }
For example the following will result in an illegal syntax error: { PropertyNameAndValueList , }
PropertyName :
Uncaught SyntaxError: Unexpected token break IdentifierName
StringLiteral
NumericLiteral
However the name is deemed valid as a property of an object (as of ECMAScript 5+):
As you can see, a PropertyName may be an IdentifierName, thus allowing ReservedWords to be PropertyNames.
var obj = { That conclusively tells us that, by specification, it is allowed to have ReservedWords such as class and var as
break: true
PropertyNames unquoted just like string literals or numeric literals.
};
[Link]([Link]);
To read more, see Section 7.6 - Identifier Names and Identifiers.
To quote from this answer: Note: the syntax highlighter in this example has spotted the reserved word and still highlighted it. While the
example is valid JavaScript developers can get caught out by some compiler / transpiler, linter and minifier tools
From the ECMAScript® 5.1 Language Specification:
that argue otherwise.
Section 7.6
Identifier Names are tokens that are interpreted according to the grammar given in the “Identifiers”
section of chapter 5 of the Unicode standard, with some small modifications. An Identifier is an
IdentifierName that is not a ReservedWord (see 7.6.1).
[Link] – JavaScript® Notes for Professionals 461 [Link] – JavaScript® Notes for Professionals 462
Credits Armfoot
AstroCB
Chapter 62
Chapter 1
Aswin Chapter 21
Thank you greatly to all the people from Stack Overflow Documentation who helped provide this content, Atakan Goktepe Chapter 5
more changes can be sent to web@[Link] for new content to be published or updated ATechieThought Chapter 1
Ates Goral Chapters 3, 35 and 42
16807 Chapter 104 Awal Garg Chapters 41 and 42
2426021684 Chapters 1, 7, 12, 42 and 59 azz Chapter 10
4444 Chapter 23 Badacadabra Chapter 25
4m1r Chapter 100 baga Chapter 5
A.J Chapter 61 balpha Chapter 12
A.M.K Chapters 5, 12, 40, 63, 72 and 73 Bamieh Chapter 12
Aadit M Shah Chapter 29 BarakD Chapter 22
Abdelaziz Mokhnache Chapter 1 Barmar Chapter 14
Abhishek Chapter 65 Basilin Joe Chapter 28
Abhishek Singh Chapter 48 Beau Chapter 5
Adam Heath Chapter 59 Bekim Bacaj Chapter 1
adius Chapter 31 Ben Chapter 12
adriennetacke Chapter 68 Ben McCormick Chapter 60
Aeolingamenfel Chapter 62 Benjadahl Chapter 19
afzalex Chapter 42 Bennett Chapter 70
Ahmed Ayoub Chapter 12 bfavaretto Chapter 1
aikeru Chapter 14 Bit Byte Chapter 89
Ajedi32 Chapter 16 Black Chapter 1
Akshat Mahajan Chapter 53 Blindman67 Chapters 10, 12, 14, 28, 41, 56, 84 and 104
Ala Eddine JEBALI Chapters 1, 24 and 56 bloodyKnuckles Chapter 63
Alberto Nicoletti Chapters 13, 14 and 43 Blubberguy22 Chapter 11
Alejandro Nanez Chapter 12 Blue Sheep Chapters 14 and 104
Alex Chapter 63 BluePill Chapter 7
Alex Filatov Chapters 14, 35 and 67 Blundering Philosopher Chapters 1 and 42
Alex Logan Chapter 5 bobylito Chapter 42
Alexander O'Mara Chapter 1 Boopathi Rajaa Chapters 22, 41, 50 and 63
Alexandre N. Chapters 1 and 42 Borja Tur Chapters 13 and 19
aluxian Chapter 81 Chapters 1, 12 and 42
Božo Stojković
amflare Chapter 20
Brandon Buck Chapter 1
Aminadav Chapters 1, 35 and 104
Brendan Doherty Chapter 50
Andrew Burgess Chapter 55
brentonstrine Chapter 19
Andrew Myers Chapter 4
Brett DeWoody Chapter 12
Andrew Sklyarevsky Chapters 59 and 98
Brett Zamir Chapters 1 and 4
Andrew Sun Chapter 59
Brian Liu Chapter 105
Andrey Chapter 14
bwegs Chapters 1, 56 and 62
Angel Politis Chapters 36 and 47
C L K Kissane Chapter 5
Angela Amarapala Chapter 26
Callan Heard Chapter 50
Angelos Chalaris Chapters 13, 37 and 46
CamJohnson26 Chapter 50
Ani Menon Chapters 1 and 36
catalogue_number Chapter 1
Anirudh Modi Chapters 12, 19, 50, 60 and 62
cchamberlain Chapter 5
Anirudha Chapter 103
CD.. Chapters 12 and 13
Anko Chapter 1
cdm Chapter 58
Ankur Anand Chapter 1
cdrini Chapters 19 and 55
Anurag Singh Bisht Chapter 87
Cerbrus Chapters 1, 5, 14, 17, 40, 42, 99 and 103
Ara Yeressian Chapter 42
cFreed Chapter 10
Araknid Chapters 11 and 30
Charlie H Chapters 10, 14, 35 and 54
arbybruce Chapter 33
Chong Lip Phang Chapter 50
[Link] – JavaScript® Notes for Professionals 463 [Link] – JavaScript® Notes for Professionals 464
choz Chapter 19 DVJex Chapter 99
Chris Chapters 10 and 22 DzinX Chapter 12
Christian Chapter 2 Ehsan Sajjad Chapter 99
Christian Landgren Chapter 13 Eirik Birkeland Chapter 19
Christoph Chapter 1 Ekin Chapters 37 and 67
Christophe Marois Chapter 42 eltonkamami Chapters 18, 19, 31, 62 and 99
Christopher Ronning Chapter 27 Emissary Chapters 5, 17, 104 and 106
Claudiu Chapters 7 and 42 Emre Bolat Chapter 106
Cliff Burton Chapters 13 and 19 Erik Minarini Chapter 42
Code Uniquely Chapter 18 Ethan Chapter 62
codemano Chapter 12 et_l Chapters 13 and 65
code_monk Chapter 12 Evan Bechtol Chapter 42
CodingIntrigue Chapters 7, 12, 13, 50, 57 and 69 Everettss Chapters 1, 19 and 57
Colin Chapter 10 Explosion Pills Chapter 81
cone56 Chapter 92 Fab313 Chapter 22
Conlin Durbin Chapter 27 fracz Chapters 12 and 42
CPHPython Chapters 5, 12, 19, 50, 56 and 62 Frank Tan Chapter 60
Creative John Chapter 24 FrankCamara Chapter 12
CroMagnon Chapters 27 and 48 FredMaggiowski Chapter 13
csander Chapters 6, 8, 18, 38, 43, 56 and 85 fson Chapters 42 and 81
cswl Chapters 15 and 81 Gabriel Furstenheim Chapter 41
Daksh Gupta Chapters 1 and 62 Gabriel L. Chapter 42
Damon Chapters 11, 12, 19 and 62 Gaurang Tandon Chapter 14
Dan Pantry Chapter 42 Gavishiddappa Gadagi Chapter 19
Daniel Chapter 12 gca Chapter 10
Daniel Herr Chapters 11, 12, 18, 30, 35, 41, 42 and 55 gcampbell Chapter 7
Daniel LIn Chapter 79 geekonaut Chapters 61, 63 and 89
daniellmb Chapters 1 and 42 georg Chapter 42
daniphilia Chapter 102 George Bailey Chapters 12, 13, 30 and 90
DarkKnight Chapters 19 and 60 GingerPlusPlus Chapter 99
dauruy Chapter 12 gman Chapters 1, 5 and 29
Dave Sag Chapters 42 and 100 gnerkus Chapter 11
David Archibald Chapter 1 GOTO 0 Chapters 7, 67 and 78
David G. Chapters 1 and 42 Grundy Chapter 10
David Knipe Chapter 56 Guybrush Threepwood Chapter 22
Davis Chapters 14, 19, 59 and 62 H. Pauwelyn Chapters 1 and 65
DawnPaladin Chapters 5, 59 and 99 hairboat Chapter 19
Deepak Bansal Chapter 99 Hans Strausl Chapters 3 and 12
Denys Séguret Chapter 104 hansmaad Chapter 12
Derek 朕會功夫 Chapter 35 Hardik Kanjariya ツ Chapters 12, 14, 46 and 47
DevDig Chapter 62 harish gadiya Chapter 104
Devid Farinelli Chapters 1 and 99 haykam Chapters 1, 5, 7 and 101
devlin carnate Chapter 42 Hayko Koryun Chapter 14
Diego Molina Chapter 59 HC_ Chapter 64
dns_nx Chapter 12 HDT Chapter 43
Domenic Chapters 12 and 49 Hendry Chapter 91
DontVoteMeDown Chapter 1 Henrique Barcelos Chapters 42 and 56
Downgoat Chapters 73 and 96 Hi I'm Frogatto Chapter 7
Dr. Cool Chapter 90 hiby Chapter 33
Dr. J. Testington Chapter 12 hindmost Chapters 14 and 29
Drew Chapter 14 hirnwunde Chapter 5
dunnza Chapter 42 hirse Chapter 36
Durgpal Singh Chapters 19 and 42 HopeNick Chapters 15 and 85
[Link] – JavaScript® Notes for Professionals 465 [Link] – JavaScript® Notes for Professionals 466
Hunan Rostomyan Chapter 12 Just a student Chapters 5 and 74
I am always right Chapter 83 K48 Chapters 1, 9, 10, 33, 42 and 99
Iain Ballard Chapter 50 kamoroso94 Chapters 8, 14, 19 and 64
Ian Chapters 10, 19 and 35 kanaka Chapter 61
iBelieve Chapters 55 and 57 kapantzak Chapters 20 and 62
Igor Raush Chapters 10, 41, 42, 57 and 62 Karuppiah Chapter 1
Inanc Gumus Chapters 1, 5 and 81 Kayce Basques Chapter 63
inetphantom Chapter 1 Keith Chapters 81 and 82
Ishmael Smyrnow Chapter 12 Kemi Chapter 69
Isti115 Chapter 12 kevguy Chapters 62 and 63
iulian Chapter 15 Kevin Katzke Chapter 10
Ivan Chapter 36 Kevin Law Chapter 19
ivarni Chapter 22 khawarPK Chapter 10
JF Chapters 14, 58, 59, 89 and 90 Kit Grose Chapter 54
jabacchetta Chapter 62 Knu Chapters 10, 11, 13, 14, 18, 35, 36, 97 and 99
James Donnelly Chapter 32 Kousha Chapter 10
James Long Chapter 12 Kyle Blake Chapters 10 and 12
Jamie Chapter 10 L Bahr Chapters 10, 37, 66 and 102
Jan Pokorný Chapter 13 [Link] Chapter 42
Jason Park Chapter 12 Li357 Chapter 106
Jay Chapters 19 and 22 Liam Chapter 17
JBCP Chapters 3 and 42 Lisa Gagarina Chapter 65
jbmartinez Chapter 19 LiShuaiyuan Chapter 35
jchavannes Chapter 30 Little Child Chapter 41
jchitel Chapter 42 little pootis Chapter 1
JCOC611 Chapter 40 Louis Barranqueiro Chapters 13, 35 and 65
JDB Chapter 19 Luís Hendrix Chapters 10, 60 and 104
Jean Lourenço Chapter 19 Luc125 Chapters 7 and 12
Jef Chapter 106 luisfarzati Chapter 42
Chapters 1, 10, 12, 13, 14, 19, 22, 27, 33, 35, 36, 50, 51, 53, 54, 55, 62, 71, 94 M. Erraysy Chapter 12
Jeremy Banks
and 97 Maciej Gurban Chapters 12 and 65
Jeremy J Starcher Chapter 12 Madara Uchiha Chapters 19, 20, 59, 60, 81 and 82
Jeroen Chapters 1 and 11 maheeka Chapter 9
JimmyLv Chapter 81 maioman Chapters 19 and 42
Jinw Chapter 79 Marco Bonelli Chapters 3, 53 and 96
jisoo Chapter 12 Marco Scabbiolo Chapters 3, 10, 13, 17, 20, 27, 30, 42, 46, 56, 57, 68, 69, 81 and 90
jitendra varshney Chapter 1 Marina K. Chapters 10 and 104
Jivings Chapters 10, 35, 50 and 55 mark Chapters 19 and 56
jkdev Chapters 3, 10, 12, 18, 30, 35, 36, 39 and 56 Mark Schultheiss Chapters 5 and 99
JKillian Chapter 31 mash Chapter 10
jmattheis Chapter 1 MasterBob Chapters 1, 19, 24, 25 and 81
John Chapter 13 Matas Vaitkevicius Chapters 1, 6 and 42
John Archer Chapter 99 Mathias Bynens Chapter 1
John C Chapter 8 Matt Lishman Chapter 57
John Oksasoglu Chapter 28 Matt S Chapter 31
John Slegers Chapters 1, 8, 12, 35, 42, 53 and 62 Mattew Whitt Chapter 42
John Syrinek Chapters 29 and 68 Matthew Crumley Chapters 18, 67, 84 and 104
Jonas W. Chapter 13 mauris Chapters 33 and 56
Jonathan Lam Chapters 1, 7, 29 and 45 Max Alcala Chapters 12, 19, 41 and 56
Jonathan Walters Chapters 18, 27 and 31 Maximillian Laumeister Chapter 42
Joseph Chapters 19 and 42 Md. Mahbubul Haque Chapter 13
Joshua Kleveter Chapters 1 and 25 MEGADEVOPS Chapter 1
Junbang Huang Chapter 76 MegaTom Chapter 11
[Link] – JavaScript® Notes for Professionals 467 [Link] – JavaScript® Notes for Professionals 468
Meow Chapters 7, 11, 14, 19, 59 and 62 Ozan Chapter 75
metal03326 Chapters 92 and 99 oztune Chapters 5, 18, 55 and 57
Michal Pietraszko Chapter 17 [Link] Chapter 62
Michał Perłakowski Chapters 1, 35, 38, 43, 76, 77 and 81 PageYe Chapter 10
Michiel Chapter 12 Pankaj Upadhyay Chapter 62
Mijago Chapter 97 Parvez Rahaman Chapters 30 and 72
Mike C Chapters 10, 11, 12, 13, 18, 19, 37, 57 and 65 patrick96 Chapter 42
Mike McCaughan Chapters 3, 8, 9, 12, 13, 15 and 42 Paul S. Chapters 7, 10, 19, 27, 31 and 62
Mikhail Chapters 5, 7, 12, 14, 33, 39, 45, 55 and 58 Pawel Dubiel Chapters 17 and 59
Mikki Chapter 97 PedroSouki Chapters 23 and 65
Mimouni Chapters 1 and 12 pensan Chapter 14
miquelarranz Chapter 89 Peter Bielak Chapter 94
Mobiletainment Chapter 89 Peter G Chapter 5
Mohamed El Chapter 55 Peter LaBanca Chapter 1
monikapatel Chapter 5 Peter Olson Chapter 13
Morteza Tourani Chapter 12 Peter Seliger Chapter 22
Motocarota Chapter 42 phaistonian Chapter 12
Mottie Chapters 10, 12, 14 and 18 Phil Chapter 13
murrayju Chapter 81 pietrovismara Chapter 89
n4m31ess_c0d3r Chapter 10 Pinal Chapters 19, 42 and 55
Nachiketha Chapter 63 pinjasaur Chapter 4
Naeem Shaikh Chapters 42 and 69 PitaJ Chapter 65
nalply Chapters 10 and 42 Pranav C Balan Chapter 12
Naman Sancheti Chapters 1 and 50 programmer5000 Chapter 95
nasoj1100 Chapter 12 ProllyGeek Chapters 20, 65 and 79
Nathan Tuggy Chapter 7 pzp Chapters 8, 30 and 71
naveen Chapter 65 Qianyue Chapters 12, 60 and 62
ndugger Chapters 17, 19, 22 and 62 QoP Chapters 12, 19, 22, 35, 42 and 57
Neal Chapters 12, 13, 19, 22, 27, 36 and 62 Quartz Fog Chapters 31 and 54
Nelson Teixeira Chapter 12 Quill Chapters 7 and 42
nem035 Chapters 10, 12, 20, 60 and 65 Racil Hilan Chapter 34
nhahtdh Chapter 31 Rafael Dantas Chapter 12
Nhan Chapters 12 and 35 Rahul Arora Chapters 20 and 29
ni8mr Chapters 10 and 18 Rajaprabhu Aravindasamy Chapter 13
nicael Chapters 11, 42, 44 and 99 Rajesh Chapter 10
Nicholas Montaño Chapter 102 Rakitić Chapter 1
Nick Chapter 1 RamenChef Chapter 14
Nick Larsen Chapter 61 Randy Chapters 19 and 50
NickHTTPS Chapter 63 Raphael Schweikert Chapter 10
Nikita Kurtin Chapters 99 and 104 rfsbsb Chapter 67
Nikola Lukic Chapters 58 and 101 richard Chapter 37
Nina Scholz Chapters 12 and 40 Richard Hamilton Chapters 7, 10, 12, 14, 31, 48 and 99
Nisarg Chapter 66 Richard Turner Chapter 62
npdoty Chapter 71 riyaz Chapter 42
nseepana Chapter 104 Roamer Chapter 42
Nuri Tasdemir Chapters 42 and 62 Rohit Jindal Chapters 30 and 40
nus Chapter 19 Rohit Kumar Chapter 57
nylki Chapter 1 Rohit Shelhalkar Chapter 5
Oriol Chapter 10 Roko C. Buljan Chapters 4, 7, 12, 14, 33, 44, 45, 89 and 106
Ortomala Lokni Chapter 10 rolando Chapters 12, 13, 18 and 19
orvi Chapters 1 and 18 rolfedh Chapter 19
Oscar Jara Chapter 10 Ronen Ness Chapters 12, 19, 32 and 43
Ovidiu Dolha Chapter 93 ronnyfm Chapter 1
[Link] – JavaScript® Notes for Professionals 469 [Link] – JavaScript® Notes for Professionals 470
royhowie Chapter 35 teppic Chapter 42
Ruhul Amin Chapter 41 Thomas Leduc Chapter 31
rvighne Chapters 13, 19, 22, 45 and 88 Thriggle Chapters 1 and 19
Ry Chapter 31 Ties Chapter 74
S Willis Chapter 8 tiffon Chapter 101
sabithpocker Chapter 7 Tim Chapter 30
Sagar V Chapters 19, 29 and 61 Tim Rijavec Chapter 86
Sammy I. Chapter 20 Tiny Giant Chapter 36
Sandro Chapter 12 tjfwalker Chapter 11
SarathChandra Chapter 11 tnga Chapter 1
Saroj Sasmal Chapter 1 Tolen Chapter 1
Scimonster Chapter 24 Tomás Cañibano Chapters 7 and 59
Sean Vieira Chapter 27 Tomboyo Chapter 17
SeanKendle Chapter 1 tomturton Chapter 65
SeinopSys Chapters 1 and 96 ton Chapter 56
SEUH Chapter 61 Tot Zam Chapter 36
SgtPooki Chapter 97 towerofnix Chapter 38
shaedrich Chapter 70 transistor09 Chapter 33
shaN Chapter 90 Traveling Tech Guy Chapter 12
Shawn Chapter 60 Travis Acton Chapter 1
Shog9 Chapters 19 and 59 Trevor Clarke Chapters 8, 14 and 46
Shrey Gupta Chapter 12 trincot Chapters 19 and 35
Sibeesh Venu Chapter 56 Tschallacka Chapter 65
sielakos Chapters 12, 19 and 50 Tushar Chapters 1 and 31
Siguza Chapter 40 user2314737 Chapters 8, 12, 14, 19, 35, 50, 59 and 104
simonv Chapter 29 user3882768 Chapter 11
SirPython Chapter 5 Vaclav Chapter 12
smallmushroom Chapter 18 VahagnNikoghosian Chapters 12 and 104
Spencer Wieczorek Chapters 7, 10, 15 and 65 Vasiliy Levykin Chapters 3, 10 and 19
spirit Chapter 35 Ven Chapters 1, 10 and 42
splay Chapters 7, 10 and 40 Victor Bjelkholm Chapter 5
Sreekanth Chapter 89 VisioN Chapters 12 and 52
ssc Chapter 1 Vlad Nicula Chapter 62
stackoverfloweth Chapter 13 Vladimir Gabrielyan Chapter 42
Stephen Leppik Chapter 40 wackozacko Chapters 42 and 60
Steve Greatrex Chapter 42 WebBrother Chapter 65
Stewartside Chapter 14 whales Chapters 8 and 18
Stides Chapter 60 Will Chapter 62
still_learning Chapters 14 and 94 Wladimir Palant Chapters 5, 10, 42 and 62
styfle Chapter 20 Wolfgang Chapter 30
sudo bangbang Chapter 42 wuxiandiejia Chapters 7, 12 and 43
Sumit Chapter 11 XavCo7 Chapters 1, 11, 12, 13, 18, 40, 50, 63, 64, 71, 90 and 92
Sumner Evans Chapters 99 and 102 xims Chapter 1
Sumurai8 Chapters 8, 10, 13, 14, 17, 35 and 56 YakovL Chapter 56
Sunny R Gupta Chapter 56 ymz Chapter 19
svarog Chapters 7, 17, 43, 80 and 90 Yosvel Quintero Chapters 1, 5, 12, 13, 14, 17, 22, 34, 35, 42 and 104
Sverri M. Olsen Chapter 1 Yumiko Chapter 33
SZenC Chapters 1, 10, 11, 13, 14, 18, 19, 30, 31, 32, 36, 59, 62, 80 and 97 Yury Fedorov Chapters 1 and 42
Tacticus Chapter 96 Zack Harley Chapter 56
tandrewnichols Chapter 19 Zaga Chapter 31
Tanmay Nehete Chapter 19 Zaz Chapter 42
Taras Lukavyi Chapter 59 zb' Chapter 42
tcooc Chapter 42 zer00ne Chapter 12
[Link] – JavaScript® Notes for Professionals 471 [Link] – JavaScript® Notes for Professionals 472
ZeroBased_IX
Zhegan
Chapter 12
Chapter 35 You may also like
zhirzh Chapters 12, 14 and 19
Zirak Chapter 56
[Link] Chapter 42
zur4ik Chapters 19 and 62
zurfyx Chapter 70
Zze Chapter 1