JavaScript
#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: AJAX 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.atan2 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 Internet Explorer 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 Firefox 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: Web Storage 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: WebSockets 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 Web Worker 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:
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 Document Object Model. 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 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; } } }); 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:
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 Google Chrome, 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
$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
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
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!