├── LICENSE ├── README.md ├── _config.yml └── _layouts └── default.html /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Nuhil Mehdy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Welcome to Javascript Handbook 2 | JavaScript, often abbreviated as JS, is a high-level, dynamic, weakly typed, object-based, multi-paradigm, and interpreted programming language. 3 | 4 | ## Comments 5 | --- 6 | Single line comments start with `//`. For multi-line commands, you use `/* ... */` 7 | 8 | ```js 9 | // This is a single line comment 10 | 11 | /* 12 | And this is 13 | a multi-line 14 | comment 15 | */ 16 | ``` 17 | 18 | > JavaScript is case-sensitive. This means that `Hello()` is not the same as `HELLO()` or `hello()` 19 | 20 | ## Variables 21 | --- 22 | You can create variables using `var`, `let`, `const` (the last two ones are available only in ES6). Variable names can't start with a number or contain spaces. They can contain letters, numbers, underscores, or $. Variable names are case sensitive. 23 | 24 | ```js 25 | // This is how you define a variable 26 | // `x` will be `undefined` 27 | var x; 28 | 29 | // Declare a constant (the convention is to use CAPS for constants) 30 | const FOO = 42; 31 | 32 | // Declare another two variables, using `var` and `let` 33 | var hello = 'world'; 34 | let bar = 'baz'; 35 | ``` 36 | Variables don't have a type. As long as they are not constants, you can change their data: 37 | 38 | ```js 39 | let foo = 42; 40 | foo = 'bar'; 41 | foo 42 | // => 'bar' 43 | ``` 44 | 45 | > In JavaScript the use of semicolons is optional, as a new line indicates the end of the statement. 46 | 47 | ### `let` vs `var` 48 | They are pretty similar, but unlike `var`, `let` declares a block scope local variable, optionally initializing it to a value. `let` allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. The `var` keyword which defines a variable to an entire function regardless of block scope. 49 | 50 | ```js 51 | var a = 42; 52 | if (true) { 53 | var b = 7; 54 | let c = 123; 55 | } 56 | 57 | // Obviously, we can access the `a` variable 58 | console.log(a); 59 | // => 42 60 | 61 | // We can access `b` as well, even it was assigned in the 62 | // if block (see below what happens if the expressions is 63 | // false). 64 | console.log(b); 65 | // => 7 66 | 67 | // We cannot access `c` here because it was declared using 68 | // `let`, inside of the `if` block, therefore it's only 69 | // accessible in the `if` block. 70 | console.log(c); 71 | // => Error: c is not defined 72 | ``` 73 | 74 | > JavaScript is a loosely typed language. This means that you can use the same variable for different types of information 75 | 76 | Notice how in the first example below, we get the final value of `i` (because we print it after one second). In the other examples `let` does that for us, the `i` value inside of the `setTimeout` (after one second) is the current value of i when the `setTimeout` was called. 77 | 78 | ```js 79 | for (var i = 0; i < 7; ++i) { 80 | setTimeout(function () { 81 | console.log(i); 82 | // => 8 83 | // => 8 84 | // => 8 85 | // => 8 86 | // => 8 87 | // => 8 88 | // => 8 89 | // => 8 90 | }, 1000); 91 | } 92 | 93 | for (let i = 0; i < 7; ++i) { 94 | setTimeout(function () { 95 | console.log(i); 96 | // => 0 97 | // => 1 98 | // => 2 99 | // => 3 100 | // => 4 101 | // => 5 102 | // => 6 103 | // => 7 104 | }, 1000); 105 | } 106 | ``` 107 | 108 | > A literal is a hard coded value. 109 | 110 | ### `const` 111 | One time initialisation. You can use it for variables which values remain the same. 112 | 113 | ```js 114 | const PI = 3.14; 115 | 116 | PI = 3; 117 | // => TypeError: Assignment to constant variable. 118 | ``` 119 | 120 | Note, this won't freeze the objects: 121 | 122 | ```js 123 | // Create an object 124 | const myObj = { foo: 'bar' }; 125 | 126 | // Update the `foo` field 127 | myObj.foo = 42; 128 | 129 | // Add a new field 130 | myObj.hello = 'world'; 131 | 132 | myObj 133 | // => { foo: 42, hello: 'world' } 134 | 135 | // Though, if you try to reset the whole thing, you can't 136 | myObj = {}; 137 | // => TypeError: Assignment to constant variable. 138 | ``` 139 | 140 | ## `if` statemenets 141 | --- 142 | ```js 143 | let foo = 42; 144 | 145 | if (foo > 40) { 146 | // do something 147 | } else { 148 | // do something else 149 | } 150 | ``` 151 | 152 | ## Switches 153 | --- 154 | ```js 155 | let planet = 'Earth'; 156 | 157 | switch (planet) { 158 | case "Mercury": 159 | case "Venus": 160 | console.log("Too hot here."); 161 | 162 | case 'Earth' : 163 | console.log("Welcome home!"); 164 | break; 165 | 166 | case 'Mars' : 167 | console.log("Welcome to the other home!"); 168 | break; 169 | 170 | case "Jupiter": 171 | case "Saturn": 172 | case "Uranus": 173 | case "Neptune": 174 | case "Pluto": 175 | console.log("You may get gold here."); 176 | break; 177 | 178 | default: 179 | console.log("Seems you found another planet."); 180 | break; 181 | } 182 | ``` 183 | 184 | ## Loops 185 | --- 186 | This will print all the integers from 1 to 42. 187 | 188 | ### `for` 189 | 190 | ```js 191 | for (var i = 1; i <= 42; ++i) { 192 | console.log(i); 193 | } 194 | ``` 195 | 196 | Using `for ... in ...` can be used to iterate object keys: 197 | ```js 198 | var name = { 199 | first: "Johnny", 200 | last: "B." 201 | }; 202 | 203 | for (var key in name) { 204 | if (name.hasOwnProperty(key)) { 205 | console.log(key, name[key]); 206 | // "first", "Johnny" 207 | // "last", "B." 208 | } 209 | } 210 | ``` 211 | 212 | In ES6 there is a `for ... of` ... as well. It's pretty neat since it iterates any iterable objects (arrays, strings etc). 213 | ```js 214 | let numbers = [-1, 7, 42, 64]; 215 | for (let num of numbers) { 216 | console.log(num); 217 | } 218 | // -1 219 | // 7 220 | // 42 221 | // 64 222 | 223 | var country = "Bangladesh"; 224 | 225 | for(let letter of country) { 226 | console.log(letter); 227 | } 228 | 229 | // B 230 | // a 231 | // n 232 | // g 233 | // l 234 | // a 235 | // d 236 | // e 237 | // s 238 | // h 239 | ``` 240 | 241 | ### `while` 242 | ```js 243 | var i = 1; 244 | while (i <= 42) { 245 | console.log(i); 246 | ++i; 247 | } 248 | ``` 249 | 250 | ### `do - while` 251 | ```js 252 | var i = 0; 253 | do { 254 | ++i; 255 | console.log(i); 256 | } while (i < 42); 257 | ``` 258 | 259 | ## Data Types 260 | --- 261 | Primitive types are types provided by the system, in this case by JavaScript. Primitive type for JavaScript are Booleans, numbers and text. In addition to the primitive types, users may define their own classes. The following ones, are primitives: 262 | 263 | ### Primitive 264 | * Booleans: `false`, `true` 265 | * Numbers: `42`, `3.14`, `0b11010`, `0x16`, `NaN` 266 | * Strings: `'Earth'`, `"Mars"` 267 | * Special Values: `undefined`, `null` 268 | * Symbol (new in ECMAScript 6). A unique and immutable primitive value and may be used as the key of an Object property 269 | 270 | ### Object 271 | Object refers to a data structure containing data and instructions for working with the data. 272 | 273 | ## Strings 274 | --- 275 | To make a new string, you can make a variable and give it a value of `new String()`. 276 | ```js 277 | var foo = new String(); 278 | ``` 279 | But, most developers skip that part and use a string literal: 280 | ```js 281 | var foo = "my string"; 282 | ``` 283 | ### Properties and methods of the String() object 284 | 285 | **concat(text)** 286 | The concat() function joins two strings. 287 | ```js 288 | var foo = "Hello"; 289 | var bar = foo.concat(" World!") 290 | alert(bar); // Hello World! 291 | ``` 292 | **length** 293 | Returns the length as an integer. 294 | ```js 295 | var foo = "Hello!"; 296 | alert(foo.length); 297 | ``` 298 | **indexOf** 299 | Returns the first occurrence of a string inside of itself, starting with 0. If the search string cannot be found, -1 is returned. The indexOf() method is case sensitive. 300 | ```js 301 | var foo = "Hello, World! How do you do?"; 302 | alert(foo.indexOf(' ')); // 6 303 | 304 | 305 | var hello = "Hello world, welcome to the universe."; 306 | alert(hello.indexOf("welcome")); // 13 307 | ``` 308 | **lastIndexOf** 309 | Returns the last occurrence of a string inside of itself, starting with index 0.. If the search string cannot be found, -1 is returned. 310 | ```js 311 | var foo = "Hello, World! How do you do?"; 312 | alert(foo.lastIndexOf(' ')); // 24 313 | ``` 314 | **replace(text, newtext)** 315 | The replace() function returns a string with content replaced. Only the first occurrence is replaced. 316 | ```js 317 | var foo = "foo bar foo bar foo"; 318 | var newString = foo.replace("bar", "NEW!") 319 | alert(foo); // foo bar foo bar foo 320 | alert(newString); // foo NEW! foo bar foo 321 | ``` 322 | **slice(start[, end])** 323 | Slice extracts characters from the start position. 324 | ```js 325 | "hello".slice(1); // "ello" 326 | // When the end is provided, they are extracted up to, but not including the end position. 327 | 328 | "hello".slice(1, 3); // "el" 329 | // Slice allows you to extract text referenced from the end of the string by using negative indexing. 330 | 331 | "hello".slice(-4, -2); // "el" 332 | // Unlike substring, the slice method never swaps the start and end positions. If the start is after the end, slice will attempt to extract the content as presented, but will most likely provide unexpected results. 333 | 334 | "hello".slice(3, 1); // "" 335 | ``` 336 | 337 | **substr(start[, number of characters]** 338 | substr extracts characters from the start position, essentially the same as slice. 339 | ```js 340 | "hello".substr(1); // "ello" 341 | // When the number of characters is provided, they are extracted by count. 342 | 343 | "hello".substr(1, 3); // "ell" 344 | ``` 345 | 346 | **substring(start[, end])** 347 | substring extracts characters from the start position. 348 | ```js 349 | "hello".substring(1); // "ello" 350 | // When the end is provided, they are extracted up to, but not including the end position. 351 | 352 | "hello".substring(1, 3); // "el" 353 | // substring always works from left to right. If the start position is larger than the end position, substring will swap the values; although sometimes useful, this is not always what you want; different behavior is provided by slice. 354 | 355 | "hello".substring(3, 1); // "el" 356 | ``` 357 | 358 | **toLowerCase()** 359 | This function returns the current string in lower case. 360 | ```js 361 | var foo = "Hello!"; 362 | alert(foo.toLowerCase()); // hello! 363 | ``` 364 | **toUpperCase()** 365 | This function returns the current string in upper case. 366 | ```js 367 | var foo = "Hello!"; 368 | alert(foo.toUpperCase()); // HELLO! 369 | ``` 370 | 371 | **trim()** 372 | This function removes leading and trailing white spaces from the current string. 373 | ```js 374 | var foo = " This line has unnecessary spaces. "; 375 | alert(foo.trim()); // This line has unnecessary spaces. 376 | ``` 377 | 378 | **charAt(index)** 379 | This function returns the character at a given index of the current string. 380 | ```js 381 | var foo = "Bangladesh"; 382 | alert(foo.charAt(3)); // g 383 | ``` 384 | 385 | **parseInt(string[, radix])** 386 | This function parses a numercial string to integer. 387 | If the radix is specified it parses in the specified numeral system. 388 | Radix can be any integer between 2 and 36. 389 | ```js 390 | var foo = "23"; 391 | alert(parseInt(foo)); // 23 392 | var foo = "1001"; 393 | alert(parseInt(foo,2)); // 9 394 | ``` 395 | 396 | **parseFloat(string)** 397 | This function parses a numercial string to float. 398 | ```js 399 | var foo = "10.589"; 400 | alert(parseFloat(foo)); // 10.589 401 | var foo = "10"; 402 | alert(parseFloat(foo)); // 10 403 | ``` 404 | **Some ES6 workaround** 405 | 406 | ```js 407 | // Template Literals or interpolation 408 | let firstName = "Nuhil"; 409 | let lastName = "Mehdy"; 410 | 411 | console.log(`${firstName} ${lastName}`); 412 | ``` 413 | 414 | ```js 415 | let country = "Bangladesh"; 416 | 417 | console.log(country.repeat(3)); 418 | console.log(country.startsWith("Bangla")); 419 | console.log(country.endsWith("desh")); 420 | console.log(country.includes("de")); 421 | /* 422 | BangladeshBangladeshBangladesh 423 | true 424 | true 425 | true 426 | */ 427 | ``` 428 | 429 | ```js 430 | // Multiline string 431 | let country = `We 432 | Love 433 | Bangladesh`; 434 | 435 | console.log(country); 436 | /* 437 | We 438 | Love 439 | Bangladesh 440 | */ 441 | ``` 442 | 443 | ## Objects 444 | --- 445 | A complex type is an object, be it either standard or custom made. Its home is the heap and goes everywhere by reference (e.g. Array, Object). The common way to declare objects is by using the curly braces: 446 | ```js 447 | let myObj = { world: "Earth" }; 448 | // Or by 449 | // let myObj = new Object({ world: "Earth" }); 450 | ``` 451 | 452 | > Objects are compared by reference. That being said, we have this: 453 | 454 | ```js 455 | let firstObj = {}; 456 | let secondObj = {}; 457 | 458 | // Check if they are equal 459 | firstObj === secondObj 460 | // => false 461 | 462 | // Comparing an object with itself... 463 | firstObj === firstObj 464 | // => true 465 | 466 | // Let's point the secondObj to firstObj 467 | secondObj = firstObj 468 | 469 | // Now they are equal 470 | firstObj === secondObj 471 | // => true 472 | ``` 473 | 474 | Attention: you have no guarantee that adding the object keys in a specific order will get them in the same order. 475 | 476 | ```js 477 | var site = new Object(); // Required to not cause error in Internet Explorer 478 | site = {}; 479 | site.test = function(string) { 480 | alert("Hello World! " + string); 481 | site.string = string; 482 | } 483 | site.test("Boo!"); 484 | alert(site.string); 485 | ``` 486 | 487 | ### Iterating through Objects 488 | `for` `in` is perfect for iterating through an object. 489 | ```js 490 | const gimli = { 491 | name: "Gimli", 492 | race: "dwarf", 493 | weapon: "battle axe", 494 | }; 495 | 496 | // Iterate through properties of gimli 497 | for (let key in gimli) { 498 | console.log(gimli[key]); 499 | } 500 | 501 | /* 502 | Gimli 503 | dwarf 504 | battle axe 505 | */ 506 | ``` 507 | 508 | ```js 509 | // Initialize method on gimli object to return property keys 510 | Object.keys(gimli); 511 | 512 | // => ["name", "race", "weapon"] 513 | ``` 514 | 515 | ### ES6 Way of creating Objects 516 | A more cleaner way to add methods in object. 517 | ```js 518 | var addStuff = { 519 | name: "Adder", 520 | sum(num1, num2) { 521 | return num1 + num2; 522 | } 523 | } 524 | 525 | console.log(addStuff.name); 526 | // => Adder 527 | console.log(addStuff.sum(5, 10)); 528 | // => 15 529 | ``` 530 | 531 | ```js 532 | function createAnimal(name, owner){ 533 | return { 534 | // Properties 535 | name, 536 | owner, 537 | // Create a method 538 | getInfo(){ 539 | return `${this.name} is owned by ${this.owner}` 540 | }, 541 | // Objects can contain other objects 542 | address: { 543 | street: '123 Main St', 544 | city: 'Pittsburgh' 545 | } 546 | }; 547 | } 548 | 549 | var spot = createAnimal("Spot", "Doug"); 550 | 551 | // Execute method 552 | console.log(`${spot.getInfo()}`); 553 | 554 | // Access object in the object 555 | console.log(`${spot.name} is at ${spot.address.street}`); 556 | 557 | // Get properties and methods of object 558 | console.log(`${Object.getOwnPropertyNames(spot).join(" ")}`); 559 | 560 | /* 561 | Spot is owned by Doug 562 | Spot is at 123 Main St 563 | name owner getInfo address 564 | */ 565 | ``` 566 | 567 | ### Object Destructuring 568 | ```js 569 | function createAnimal(name, owner){ 570 | return { 571 | // Properties 572 | name, 573 | owner, 574 | // Create a method 575 | getInfo(){ 576 | return `${this.name} is owned by ${this.owner}` 577 | }, 578 | // Objects can contain other objects 579 | address: { 580 | street: '123 Main St', 581 | city: 'Pittsburgh' 582 | } 583 | }; 584 | } 585 | 586 | var spot = createAnimal("Spot", "Doug"); 587 | 588 | // You can store values from Objects with destructoring 589 | let { name, owner } = spot; 590 | console.log(`Name : ${name}`); 591 | 592 | // Get the inner class value 593 | let { address } = spot 594 | console.log(`Address : ${address.street}`); 595 | 596 | // You can destructor arrays as well 597 | let favNums = [2.718, .5772, 4.6692]; 598 | let [,,chaos] = favNums; 599 | console.log(`Chaos : ${chaos}`); 600 | 601 | // You can use rest items to grab part of an array 602 | let [, ...last2] = favNums; 603 | console.log(`2nd Num : ${last2[0]}`); 604 | 605 | // This can be used to switch values 606 | let val1 = 1, val2 = 2; 607 | [val1,val2] = [val2,val1]; 608 | console.log(`Val2 : ${val2}`); 609 | 610 | /* 611 | Name : Spot 612 | Address : 123 Main St 613 | Chaos : 4.6692 614 | 2nd Num : 0.5772 615 | Val2 : 1 616 | */ 617 | ``` 618 | 619 | ## Arrays 620 | --- 621 | All Arrays are untyped, so you can put everything you want in an Array. In addition to objects, the array data is ordered by indexes. Arrays are actually objects, having the indexes (numbers from `0` to `legnth - 1`) as keys. 622 | 623 | ```js 624 | let fruits = ["apples", "pears", "oranges"]; 625 | // Or by 626 | // var fruits = new Array("apples", "pears", "oranges"); 627 | 628 | fruits[1] 629 | // => "pears" 630 | ``` 631 | 632 | ### Arrays in ES6 way 633 | ```js 634 | // Array.of() is used to create arrays instead of the array 635 | // constructor 636 | let array1 = Array.of(1,2,3); 637 | 638 | // Create an object into an array 639 | let array2 = Array.from("word"); 640 | 641 | // You can use Array.from to manipulate values 642 | let array3 = Array.from(array1, (value) => value * 2); 643 | 644 | // Iterate over values 645 | for (let val of array1) { 646 | console.log(`Array1 Val : ${val}`); 647 | } 648 | 649 | for (let val of array2) { 650 | console.log(`Array2 Val : ${val}`); 651 | } 652 | 653 | for (let val of array3) { 654 | console.log(`Array3 Val : ${val}`); 655 | } 656 | 657 | /* 658 | Array1 Val : 1 659 | Array1 Val : 2 660 | Array1 Val : 3 661 | Array2 Val : w 662 | Array2 Val : o 663 | Array2 Val : r 664 | Array2 Val : d 665 | Array3 Val : 2 666 | Array3 Val : 4 667 | Array3 Val : 6 668 | */ 669 | ``` 670 | 671 | ### Some Array Operations 672 | ```js 673 | > let fruits = ["Apple"] 674 | 675 | // Add to the end of the array 676 | > fruits.push("Pear") 677 | 2 // < The new length of the array 678 | 679 | [ 'Apple', 'Pear' ] 680 | // ^ This was just added 681 | 682 | // Add to the start of the array 683 | > fruits.unshift("Orange") 684 | 3 // < The new length of the array 685 | 686 | [ 'Orange', 'Apple', 'Pear' ] 687 | // ^ This was just added 688 | 689 | // Access the element at index 1 (the second element) 690 | > fruits[1] 691 | 'Apple' 692 | 693 | // How many items do we have? 694 | > fruits.length 695 | 3 696 | 697 | // Turn the Apple into Lemon 698 | > fruits[1] = "Lemon" 699 | 'Lemon' 700 | 701 | [ 'Orange', 'Lemon', 'Pear' ] 702 | // ^ This was before an Apple 703 | 704 | // Insert at index 1 a new element 705 | > fruits.splice(1, 0, "Grapes") 706 | [] // < Splice is supposed to delete things (see below) 707 | // In this case we're deleting 0 elements and 708 | // inserting one. 709 | 710 | [ 'Orange', 'Grapes', 'Lemon', 'Pear' ] 711 | // ^ This was added. 712 | 713 | // Get the Lemon's index 714 | > fruits.indexOf("Lemon") 715 | 2 716 | 717 | // Delete the Lemon 718 | > fruits.splice(2, 1) 719 | [ 'Lemon' ] 720 | 721 | [ 'Orange', 'Grapes', 'Pear' ] 722 | // ^ Lemon is gone 723 | 724 | // Remove the last element 725 | > fruits.pop() 726 | 'Pear' 727 | 728 | [ 'Orange', 'Grapes' ] 729 | // ^ Pear is gone 730 | 731 | // Remove the first element 732 | > fruits.shift() 733 | 'Orange' 734 | 735 | [ 'Grapes' ] 736 | // ^ Orange is gone 737 | ``` 738 | 739 | **concat()** 740 | The `concat()` method returns the combination of two or more arrays. To use it, first you need two or more arrays to combine. 741 | ```js 742 | var arr1 = ["a","b","c"]; 743 | var arr2 = ["d","e","f"]; 744 | ``` 745 | Then, make a third array and set its value to `arr1.concat(arr2)`. 746 | ```js 747 | var arr3 = arr1.concat(arr2) //arr3 now is: ["a","b","c","d","e","f"] 748 | ``` 749 | 750 | **join() and split()** 751 | The `join()` method combines all the elements of an array into a single string, separated by a specified delimiter. If the delimiter is not specified, it is set to a comma. The `split()` is the opposite and splits up the contents of a string as elements of an array, based on a specified delimiter. 752 | 753 | To use `join()`, first make an array. 754 | ```js 755 | var abc = ["a","b","c"]; 756 | ``` 757 | Then, make a new variable and set it to `abc.join()`. 758 | 759 | ```js 760 | var a = abc.join(); //"a,b,c" 761 | ``` 762 | You can also set a delimiter. 763 | ```js 764 | var b = abc.join("; "); //"a; b; c" 765 | ``` 766 | To convert it back into an array with the String object's `split()` method. 767 | ```js 768 | var a2 = a.split(","); //["a","b","c"] 769 | var b2 = b.split("; "); //["a","b","c"] 770 | ``` 771 | 772 | ### Iterating over Arrays 773 | There are few ways to loop trough an array. 774 | 775 | ```js 776 | // Using for-loop 777 | var arr = [42, 7, -1] 778 | for (var index = 0; index < arr.length; ++index) { 779 | var current = arr[index]; 780 | /* Do something with `current` */ 781 | } 782 | 783 | // Others prefer defining an additional `length` variable: 784 | for (var index = 0, length = arr.length; index < length; ++index) { 785 | var current = arr[index]; 786 | /* ... */ 787 | } 788 | ``` 789 | 790 | **forEach** 791 | ```js 792 | // Another way i using `forEach`: 793 | arr.forEach((current, index, inputArray) => { 794 | /* Do something with `current` */ 795 | }); 796 | ``` 797 | 798 | **for of** 799 | ```js 800 | // Or using the for ... of: 801 | for (let current of arr) { 802 | /* current will be the current element */ 803 | } 804 | ``` 805 | 806 | ## Symbols 807 | --- 808 | A Symbol is like an enumerated type that can be used as identifiers and they can't be changed (immutable). 809 | ```js 810 | // Create a symbol that is used like a label in an array 811 | // You can provide a description in quotes 812 | let capital = Symbol("State Capital"); 813 | 814 | let pennsylvania = {}; 815 | pennsylvania[capital] = "Harrisburg"; 816 | console.log(`Capital of PA : ${pennsylvania[capital]}`); 817 | 818 | // => Capital of PA : Harrisburg 819 | ``` 820 | 821 | ## Sets 822 | --- 823 | List of values with no duplicates. 824 | ```js 825 | var randSet = new Set(); 826 | randSet.add(10); 827 | randSet.add("Word"); 828 | 829 | // Check to see if set contains a value 830 | console.log(`Has 10 : ${randSet.has(10)}`); 831 | 832 | // Get size of Set 833 | console.log(`Set Size : ${randSet.size}`); 834 | 835 | // Delete item from list 836 | randSet.delete(10); 837 | 838 | // Iterate a Set 839 | for (let val of randSet) 840 | console.log(`Set Val : ${val}`); 841 | 842 | /* 843 | Has 10 : true 844 | Set Size : 2 845 | Set Val : Word 846 | */ 847 | ``` 848 | 849 | ## Maps 850 | --- 851 | A collection of key/value pairs 852 | ```js 853 | var randMap = new Map(); 854 | randMap.set("key1", "Random String"); 855 | randMap.set("key2", 10); 856 | 857 | // Get values 858 | console.log(`key1 : ${randMap.get("key1")}`); 859 | console.log(`key2 : ${randMap.get("key2")}`); 860 | 861 | // Get size 862 | document.write(`Map Size : ${randMap.size}`); 863 | 864 | // Iterate Map 865 | randMap.forEach(function(value, key){ 866 | console.log(`${key} : ${value}`); 867 | 868 | /* 869 | key1 : Random String 870 | key2 : 10 871 | Map Size : 2 872 | key1 : Random String 873 | key2 : 10 874 | */ 875 | ``` 876 | 877 | ## Scope in Javascript 878 | --- 879 | In JavaScript, the scope is the current context of the code. It refers to the accessability of functions and variables, and their context. 880 | 881 | **Global scope** 882 | An entity like a function or a variable has global scope, if it is accessible from everywhere in the code. 883 | ```js 884 | var a = 99; 885 | 886 | function hello() { 887 | alert("Hello, " + a + "!"); 888 | } 889 | hello(); // prints the string "Hello, 99!" 890 | alert(a); // prints the number 99 891 | console.log("a = " + a); // prints "a = 99" to the console of the browser 892 | ``` 893 | 894 | **Local Scope** 895 | A local scope exists when an entity is defined in a certain code part, like a function. 896 | ```js 897 | var a = 99; 898 | 899 | function hello() { 900 | var x = 5; 901 | alert("Hello, " + (a + x) + "!"); 902 | } 903 | hello(); // prints the string "Hello, 104!" 904 | alert(a); // prints the number 99 905 | alert(x); // throws an exception 906 | ``` 907 | 908 | ## Functions 909 | --- 910 | There are a couple of ways to define functions in JavaScript. The common uses are: 911 | ```js 912 | function sum (a, b) { 913 | return a + b; 914 | } 915 | 916 | var sum = function (a, b) { 917 | return a + b; 918 | } 919 | ``` 920 | > In JavaScript, functions are first-class objects, because they can have properties and methods just like any other object. Also,can be dynamically created, destroyed, passed to a function, returned as a value, and have all the rights as other variables. 921 | 922 | ### Functions in ES6 923 | 924 | **Arrow Function** 925 | ```js 926 | // Using the arrow functions 927 | let sum = (a, b) => a + b; 928 | ``` 929 | Then you can call the function like: 930 | ``` 931 | let result = sum(40, 2); 932 | // => 42 933 | ``` 934 | Arrow function is amazing because they would make your `this` behave properly, i.e., `this` will have the same value as in the context of the function—it won’t mutate. 935 | ```js 936 | $('.btn').click((event) =>{ 937 | this.sendData() 938 | }) 939 | 940 | // Or for example 941 | var logUpperCase = function() { 942 | this.string = this.string.toUpperCase() 943 | return () => console.log(this.string) 944 | } 945 | 946 | logUpperCase.call({ string: 'es6 rocks' })() 947 | ``` 948 | 949 | **Default Value of Parameter** 950 | ```js 951 | // Default values are defined next to parameters 952 | function getSum(num1 = 1, num2 = 1){ 953 | console.log(`${num1} + ${num2} = ${num1+num2}`); 954 | 955 | // arguments[] only receives the value passed 956 | console.log(`${arguments[0]} + ${arguments[1]}`) 957 | } 958 | 959 | getSum(3); 960 | 961 | /* 962 | 3 + 1 = 4 963 | 3 + undefined 964 | */ 965 | ``` 966 | 967 | **Rest Parameters** 968 | ```js 969 | // Rest parameters, which are preceeded by ... 970 | // become an array 971 | // You can only have 1 rest parameter and it must 972 | // be defined last 973 | 974 | function getSumMore(...vals){ 975 | let sum = 0; 976 | for(let i = 0, len = vals.length; i < len; i++){ 977 | sum += vals[i]; 978 | } 979 | console.log(`The sum is ${sum}`); 980 | } 981 | 982 | getSumMore(1,2,3,4); 983 | 984 | // You can also pass arrays 985 | let vals = [1,2,3,4,5]; 986 | getSumMore(...vals); 987 | 988 | /* 989 | The sum is 10 990 | The sum is 15 991 | */ 992 | ``` 993 | 994 | ## Anonymous functions 995 | 996 | A function that was declared without any named identifier to refer to it. As such, an anonymous function is usually not accessible after its initial creation. 997 | 998 | > One common use for anonymous functions is as arguments to other functions. Another common use is as a closure. 999 | 1000 | **As an argument to other functions** 1001 | ```js 1002 | setTimeout(function() { 1003 | alert('hello'); 1004 | }, 1000); 1005 | ``` 1006 | 1007 | **As a closure** 1008 | ```js 1009 | (function() { 1010 | alert('foo'); 1011 | })(); 1012 | ``` 1013 | The surrounding parentheses are a wrapper for the anonymous function. The trailing parentheses initiate a call to the function and can contain arguments. Another way to write the previous example and get the same result: 1014 | ```js 1015 | (function(message) { 1016 | alert(message); 1017 | }('foo')); 1018 | ``` 1019 | 1020 | ## JavaScript Closures 1021 | --- 1022 | A closure is a function having access to the parent scope, even after the parent function has closed. Or a data structure storing a function together with an environment. 1023 | 1024 | ```js 1025 | var add = (function () { 1026 | var counter = 0; 1027 | return function () {return counter += 1;} 1028 | })(); 1029 | 1030 | add(); 1031 | add(); 1032 | add(); 1033 | 1034 | // the counter is now 3 1035 | ``` 1036 | In above example, the self-invoking function only runs once. It sets the counter to zero (0), and returns a function expression. This way add becomes a function. The "wonderful" part is that it can access the counter in the parent scope. This is called a JavaScript closure. It makes it possible for a function to have "private" variables. 1037 | 1038 | ## Functional Javascript 1039 | --- 1040 | 1041 | ### Reduce 1042 | Simply means to get some elements and then reduce them to produce a single element. 1043 | ```js 1044 | var myNumbers = [1, 2, 3, 4, 5]; 1045 | var sumOfAll = myNumbers.reduce(function (a, b) { 1046 | return a + b 1047 | }); 1048 | 1049 | console.log(sumOfAll); 1050 | ``` 1051 | 1052 | ```js 1053 | // A ES6 Version with the usage of Arrow function 1054 | let myNumbers = [1, 2, 3, 4, 5]; 1055 | let sumOfAll = myNumbers.reduce((a, b) => a + b); 1056 | 1057 | console.log(sumOfAll); 1058 | 1059 | // => 15 1060 | ``` 1061 | 1062 | ### Filter 1063 | Pulls out filtered elements that pass out a condition. 1064 | ```js 1065 | var myNumbers = [1, 2, 3, 4, 5]; 1066 | var evenNumbers = myNumbers.filter(value => value % 2 == 0); 1067 | 1068 | console.log(evenNumbers); 1069 | 1070 | // => [ 2, 4 ] 1071 | ``` 1072 | 1073 | ### Map 1074 | Performs a given action to every single elements that are passed to it. 1075 | ```js 1076 | var myNumbers = [1, 2, 3, 4, 5]; 1077 | var doubleNumbers = myNumbers.map(value => value * 2); 1078 | 1079 | console.log(doubleNumbers); 1080 | 1081 | // => [ 2, 4, 6, 8, 10 ] 1082 | ``` 1083 | 1084 | ## Constructors and Classes 1085 | --- 1086 | **Constructor** 1087 | The constructor is a function matching the name of the object, and, when called by the new operator, has the keyword this assigned to the newly created instance of the object. The new operator creates a new object based on a constructor and a prototype. 1088 | ```js 1089 | function CoinObject() { 1090 | this.value = 0; 1091 | } 1092 | var slug = new CoinObject(); // Creates a "slug" - a valueless coin (slug.value = 0). 1093 | ``` 1094 | 1095 | There are a couple of ways you can obtain a class-like functionality in JavaScript (earlier than ES6). 1096 | 1097 | ### Using Factory functions 1098 | --- 1099 | Creating an object and returning it. 1100 | 1101 | ```js 1102 | function Person (name) { 1103 | // Could be optional 1104 | var self = {}; 1105 | 1106 | // Public field 1107 | self.name = name; 1108 | 1109 | // Public method 1110 | self.getName = function () { 1111 | // `this` is the `self` 1112 | return this.name; 1113 | }; 1114 | 1115 | return self; 1116 | } 1117 | 1118 | var p = Person("Alice"); 1119 | console.log(p.getName()); 1120 | // => "Alice" 1121 | ``` 1122 | 1123 | **Getters & Setters** 1124 | ```js 1125 | var profile = { 1126 | name: "Nuhil", 1127 | age: 30, 1128 | 1129 | set setMyName(name) { 1130 | this.name = name; 1131 | }, 1132 | 1133 | get getMyName() { 1134 | return this.name; 1135 | } 1136 | }; 1137 | 1138 | profile.setMyName = "Nuhil Mehdy"; 1139 | console.log(profile.getMyName); 1140 | // => Nuhil Mehdy 1141 | ``` 1142 | 1143 | 1144 | ### Using `prototype`s 1145 | --- 1146 | A prototype for an object is the set of auto-created fields and methods. It cannot operate by itself, and relies on an existing constructor. When the object is created, the fields initialized in the prototype are copied to the newly created object. 1147 | ```js 1148 | function CoinObject() { 1149 | this.value = 0; 1150 | } 1151 | 1152 | CoinObject.prototype.diameter = 1; 1153 | slug = new CoinObject(); // A valueless coin (slug.value = 0), with diameter of 1 (slug.diameter = 1) 1154 | ``` 1155 | 1156 | By adding a method in the prototype object of a function, you're adding that method as a public method to all the instances of that class. 1157 | 1158 | ```js 1159 | function Person (name) { 1160 | this.name = name; 1161 | } 1162 | 1163 | Person.prototype.getName = function () { 1164 | // `this` is the `self` 1165 | return this.name; 1166 | }; 1167 | 1168 | var p = new Person("Bob"); 1169 | console.log(p.getName()); 1170 | // => "Bob" 1171 | ``` 1172 | 1173 | **Extending objects** 1174 | To demonstrate, an Animal constructor is used to create an object, a dog called Spot. After that creation, the constructor has a gender property added to it. That gender property is also accessible from the object for Spot. 1175 | ```js 1176 | function Animal (type, name) { 1177 | this.type = type || 'No type'; 1178 | this.name = name || 'No name'; 1179 | } 1180 | var dog = new Animal('dog', 'Spot'); 1181 | 1182 | // Add gender to the Animal object 1183 | Animal.prototype.gender = 'unspecified'; 1184 | // dog.gender is 'unspecified' 1185 | 1186 | dog.gender = 'male'; 1187 | // dog.gender is 'male'; 1188 | 1189 | delete(dog.gender); 1190 | // dog.gender is once again, 'unspecified' 1191 | ``` 1192 | 1193 | **Inheritance by prototypes** 1194 | The prototype of an object can be used to create fields and methods for an object. This prototype can be used for inheritance by assigning a new instance of the superclass to the prototype. 1195 | 1196 | ```js 1197 | function CoinObject() { 1198 | this.value = 0; 1199 | this.diameter = 1; 1200 | } 1201 | 1202 | function Penny() { 1203 | this.value = 1; 1204 | } 1205 | Penny.prototype = new CoinObject(); 1206 | 1207 | function Nickel() { 1208 | this.value = 5; 1209 | } 1210 | Nickel.prototype = new CoinObject(); 1211 | ``` 1212 | 1213 | **Access Control** 1214 | JavaScript does not provide a direct means to control access to internal variables, however, it is possible to restrict access to some variables. To declare and use a variable as private, there are two steps required: 1215 | * Declare a new variable within the constructor using the var statement. 1216 | * Create an anonymous function within the constructor, and assign it as a method for an object. 1217 | 1218 | ```js 1219 | function MyObject() { 1220 | this.publicNumber = 10; // Public field. 1221 | var privateNumber = 20; // Private variable. 1222 | 1223 | this.getPrivateNumber = function() { 1224 | return privateNumber; 1225 | } 1226 | } 1227 | 1228 | testObject = new MyObject(); 1229 | ``` 1230 | 1231 | **Access Super Class Method** 1232 | ```js 1233 | // Parent class as known as Factory function 1234 | function Vehicle(name) { 1235 | this.name = "Vehicle"; 1236 | } 1237 | 1238 | // Adding methods to its prototype 1239 | Vehicle.prototype = { 1240 | drive: function() { 1241 | return this.name + " drives forward"; 1242 | }, 1243 | stop: function() { 1244 | return this.name + " stops!"; 1245 | } 1246 | } 1247 | 1248 | // Child class 1249 | function Truck(name) { 1250 | this.name = name; 1251 | } 1252 | 1253 | // Inheritance from Parent class 1254 | Truck.prototype = new Vehicle(); 1255 | Truck.prototype.constructor = Truck; 1256 | 1257 | // Method overriding and ... 1258 | Truck.prototype.drive = function() { 1259 | // Calling Parent class's method 1260 | var driveMsg = Vehicle.prototype.drive.apply(this); 1261 | return driveMsg += " through a field!"; 1262 | } 1263 | 1264 | // Instance of Child class 1265 | var jeep = new Truck("Jeep"); 1266 | console.log(jeep.drive()); 1267 | // => Jeep drives forward through a field! 1268 | console.log(jeep.stop()); 1269 | // => Jeep stops! 1270 | ``` 1271 | 1272 | ## Classes in ES6 1273 | --- 1274 | ```js 1275 | class Person { 1276 | constructor (name) { 1277 | this.name = name; 1278 | } 1279 | getName () { 1280 | return this.name; 1281 | } 1282 | } 1283 | 1284 | var p = new Person("Carol"); 1285 | console.log(p.getName()); 1286 | // => "Bob" 1287 | ``` 1288 | 1289 | **Inherit classes in ES6** 1290 | ```js 1291 | class Musician extends Person { 1292 | constructor (name, instrument) { 1293 | // Call the base class 1294 | super(name); 1295 | 1296 | this.instrument = instrument; 1297 | } 1298 | 1299 | play () { 1300 | console.log(`${this.getName()} is playing ${this.instrument}`); 1301 | } 1302 | } 1303 | 1304 | var me = new Musician("Johnny B.", "piano"); 1305 | 1306 | // Get the name of the musician, who is also a person 1307 | console.log(me.getName()); 1308 | // => "Johnny B." 1309 | 1310 | me.play(); 1311 | // => "Johnny B. is playing piano." 1312 | ``` 1313 | 1314 | **Getters & Setters Example** 1315 | ```js 1316 | class Mammal{ 1317 | constructor(name){ 1318 | this._name = name; 1319 | } 1320 | 1321 | // Getter 1322 | get name() { 1323 | return this._name; 1324 | } 1325 | 1326 | // Setter 1327 | set name(name){ 1328 | this._name = name; 1329 | } 1330 | 1331 | // Static Mammal creator 1332 | static makeMammal(name){ 1333 | return new Mammal(name); 1334 | } 1335 | 1336 | getInfo(){ 1337 | return `${this.name} is a mammal`; 1338 | } 1339 | 1340 | } 1341 | 1342 | // Create an object 1343 | let monkey = new Mammal("Fred"); 1344 | 1345 | // Change name 1346 | monkey.name = "Mark"; 1347 | 1348 | // Call getter 1349 | console.log(`Mammal : ${monkey.name}`); 1350 | 1351 | // Create Mammal using static function 1352 | let chipmunk = Mammal.makeMammal("Chipper"); 1353 | console.log(`Mammal 2 : ${chipmunk.name}`); 1354 | 1355 | /* 1356 | Mammal : Mark 1357 | Mammal 2 : Chipper 1358 | */ 1359 | ``` 1360 | 1361 | A more detail example: 1362 | ```js 1363 | class Animal { 1364 | constructor(name){ 1365 | this.name = name; 1366 | } 1367 | 1368 | toString(){ 1369 | return "Animal is named " + this.name; 1370 | } 1371 | 1372 | // We can create static functions as well 1373 | static getAnimal(){ 1374 | return new Animal("No Name"); 1375 | } 1376 | 1377 | } 1378 | 1379 | class Dog extends Animal{ 1380 | constructor(name, owner){ 1381 | 1382 | // We can call the super class now 1383 | super(name); 1384 | this.owner = owner; 1385 | } 1386 | 1387 | toString(){ 1388 | 1389 | // You can call super class methods as well 1390 | return super.toString() + " \nDog is named " + this.name; 1391 | } 1392 | } 1393 | 1394 | var rover = new Dog("Rover", "Paul"); 1395 | 1396 | console.log(rover.name + " is owned by " + rover.owner); 1397 | 1398 | console.log(rover.toString()); 1399 | 1400 | // Call the static function 1401 | var bowser = Animal.getAnimal(); 1402 | console.log("Bowser info : " + bowser.toString()); 1403 | /* 1404 | Rover is owned by Paul 1405 | Animal is named Rover 1406 | Dog is named Rover 1407 | Bowser info : Animal is named No Name 1408 | */ 1409 | ``` 1410 | 1411 | ## Async vs Sync 1412 | --- 1413 | Sometimes you have to wait a little bit for things to be done: such as when making a cake, you have to work on it and you have to wait a while for it to be ready. Most familiar things in our lives are asynchronous. 1414 | 1415 | ### Sync 1416 | Usually, synchronous operations send the response directly, using the `return` keyword: 1417 | ```js 1418 | // Synchronous sum 1419 | function sum (a, b) { 1420 | return a + b; 1421 | } 1422 | var result = sum(40, 2); 1423 | // => 42 1424 | ``` 1425 | 1426 | ### Async 1427 | To have an async function, you need a source of async stuff. In this example, we will use the `setTimeout` function. It accepts a function as first argument (which is called callback function) and a number as second argument—representing the time delay after the function is called: 1428 | 1429 | ```js 1430 | function asyncSum(a, b, adder) { 1431 | console.log("I am working in other stuffs..."); 1432 | 1433 | setTimeout(function() { 1434 | let sum = a + b; 1435 | adder(sum); 1436 | }, 5000); 1437 | } 1438 | 1439 | asyncSum(10, 10, function(result) { 1440 | console.log(result); 1441 | }); 1442 | ``` 1443 | 1444 | ## Callbacks 1445 | --- 1446 | Callbacks are functions which are sent as an argument to another function and are invoked when something happens. 1447 | ```js 1448 | // An usual factory function 1449 | function Cake(type) { 1450 | self.type = type; 1451 | 1452 | self.getName = function() { 1453 | return this.type; 1454 | } 1455 | 1456 | return self; 1457 | } 1458 | 1459 | var busy = false; 1460 | 1461 | // The async function 1462 | function makeCake (type, callback) { 1463 | 1464 | if (busy) { 1465 | return callback(new Error("Busy with a cake."), new Cake(type)); 1466 | } 1467 | 1468 | busy = true; 1469 | 1470 | // fake the processing time by using setTimeout 1471 | setTimeout(function() { 1472 | callback(null, new Cake(type)); 1473 | busy = false; 1474 | }, 2000); 1475 | } 1476 | 1477 | // make use of that async function 1478 | makeCake("Apple", function(err, cake) { 1479 | if (err) { console.error(err); } 1480 | console.log("Made an " + cake.getName() + " cake!"); 1481 | }); 1482 | 1483 | // make another use of that async function 1484 | makeCake("Peach", function(err, cake) { 1485 | if (err) { console.error(err); } 1486 | console.log("Made a " + cake.getName() + " cake!"); 1487 | }); 1488 | ``` 1489 | 1490 | ## Promises 1491 | --- 1492 | 1493 | A Promise object represents an operation which has *produced or will **eventually** produce a value*. Promises provide a robust way to wrap the (possibly pending) result of asynchronous work, mitigating the problem of deeply nested callbacks (known as "callback hell"). 1494 | 1495 | **States and control flow** 1496 | A promise can be in one of three states: 1497 | * pending — The underlying operation has not yet completed, and the promise is pending fulfillment. 1498 | * fulfilled — The operation has finished, and the promise is fulfilled with a value. This is analogous to returning a value from a synchronous function. 1499 | * rejected — An error has occurred during the operation, and the promise is rejected with a reason. This is analogous to throwing an error in a synchronous function. 1500 | 1501 | ```js 1502 | // A Promise that is handled immediately 1503 | var p1 = Promise.resolve('Resolve Me'); 1504 | 1505 | // then takes 2 optional arguments being first a callback 1506 | // for a success and another for failure 1507 | p1.then((res) => console.log(`${res}`)); 1508 | 1509 | // => Resolve Me 1510 | ``` 1511 | 1512 | A promise is said to be settled (or resolved) when it is either fulfilled or rejected. Once a promise is settled, it becomes immutable, and its state cannot change. The then and catch methods of a promise can be used to attach callbacks that execute when it is settled. These callbacks are invoked with the fulfillment value and rejection reason, respectively. 1513 | 1514 | The `then` and `catch` methods can be used to attach fulfillment and rejection callbacks: 1515 | ```js 1516 | promise.then(function(value) { 1517 | // Work has completed successfully, 1518 | // promise has been fulfilled with "value" 1519 | }).catch(function (reason) { 1520 | // Something went wrong, 1521 | // promise has been rejected with "reason" 1522 | }); 1523 | ``` 1524 | 1525 | ```js 1526 | let randVal = 18; 1527 | 1528 | var p3 = new Promise(function(resolve, reject){ 1529 | if (randVal == 6){ 1530 | resolve("Good Value"); 1531 | } else { 1532 | reject("Bad Value"); 1533 | } 1534 | }); 1535 | 1536 | p3.then((val) => console.log(`${val}`), 1537 | (err) => console.log(`${err}`)); 1538 | 1539 | // => Bad Value 1540 | ``` 1541 | 1542 | ```js 1543 | function sum (a, b) { 1544 | return Promise(function (resolve, reject) { 1545 | // Let's wait a second and only then send the response 1546 | setTimeout(function () { 1547 | if (typeof a !== "number" || typeof b !== "number") { 1548 | return reject(new TypeError("Please provide two numbers to sum.")); 1549 | } 1550 | resolve(a + b); 1551 | }, 1000); 1552 | }); 1553 | } 1554 | 1555 | var myPromise = sum(40, 2); 1556 | 1557 | myPromsise.then(function (result) { 1558 | // After one second we have the response here 1559 | console.log("> Summed 40 + 2: ", result); 1560 | 1561 | // Let's pass some invalid data and return another promise 1562 | return sum(null, "foo"); 1563 | }).then(function () { 1564 | // This won't be called because we have an error 1565 | }).catch(function (err) { 1566 | // Instead, this `catch` handler is called: (after another second) 1567 | console.error(err); 1568 | // => Please provide two numbers to sum. 1569 | }); 1570 | ``` 1571 | 1572 | ## Modules 1573 | In ES5 for example in Nodejs which makes use of CommonJS, let’s say we have `port` variable and `getAccounts` method in `module.js`: 1574 | ```js 1575 | module.exports = { 1576 | port: 3000, 1577 | getAccounts: function() { 1578 | ... 1579 | } 1580 | } 1581 | ``` 1582 | In ES5 `main.js`, we would require that dependency: 1583 | 1584 | ```js 1585 | var service = require('module.js') 1586 | console.log(service.port) // 3000 1587 | ``` 1588 | 1589 | ### Modules in ES6 1590 | --- 1591 | In ES6, we would use export and import. For example, this is our library in the ES6 `module.js` file: 1592 | ```js 1593 | export var port = 3000 1594 | export function getAccounts(url) { 1595 | ... 1596 | } 1597 | ``` 1598 | In the importer ES6 file `main.js`, we use `import {name} from 'my-module'` syntax. For example, 1599 | ```js 1600 | import {port, getAccounts} from 'module' 1601 | console.log(port) // 3000 1602 | ``` 1603 | Or we can import everything as a variable service in `main.js`: 1604 | ```js 1605 | import * as service from 'module' 1606 | console.log(service.port) // 3000 1607 | ``` 1608 | 1609 | ## Create and throw errors 1610 | --- 1611 | To create an error, you have to use the `Error` constructor: 1612 | ```js 1613 | let myError = new Error("Something went really wrong."); 1614 | 1615 | // You can even append custom data here 1616 | myError.code = "MY_FANCY_ERROR_CODE"; 1617 | ``` 1618 | 1619 | To throw an error, you have to use the `throw` statement: 1620 | ```js 1621 | throw new Error("Something bad happened."); 1622 | ``` 1623 | 1624 | There are few types of errors. For example, if you validate the arguments passed to a function, use `TypeError`: 1625 | ```js 1626 | function sayHello(message) { 1627 | if (typeof message !== "string") { 1628 | throw new TypeError("The message should be a string."); 1629 | } 1630 | console.log(message); 1631 | } 1632 | ``` 1633 | 1634 | ## Error handling 1635 | --- 1636 | In general, it is a good practice to validate the data you're passing to function (especially when they are coming from the user input). This way you can avoid `TypeError`s to be thrown. 1637 | 1638 | If there's a function which throws an error by design, you can catch it using `try - catch`: 1639 | ```js 1640 | function assert (truly) { 1641 | if (!truly) { 1642 | throw new Error("Not true."); 1643 | } 1644 | } 1645 | 1646 | try { 1647 | // This will *not* throw an error 1648 | assert(42 === 42); 1649 | 1650 | // This will throw an error, so that will go in the catch 1651 | assert(42 === -1); 1652 | 1653 | // Everything put after the place where the error was thrown 1654 | // is not executed 1655 | } catch (e) { 1656 | console.error(e); 1657 | // => Not true. 1658 | } 1659 | ``` 1660 | 1661 | Note if you have an async function (either callback-based or which returns a promise), you'll do something like this: 1662 | ```js 1663 | // Callback 1664 | fetchDataFromServer(function (err, data) { 1665 | if (err) { 1666 | /* do something if you have an error */ 1667 | } else { 1668 | /* Do something with `data` */ 1669 | } 1670 | }); 1671 | ``` 1672 | 1673 | ```js 1674 | // Promise 1675 | fetchDataFromServer().then(function (data) { 1676 | /* Do something with `data` */ 1677 | }).catch(function (err) { 1678 | /* do something if you have an error */ 1679 | }); 1680 | ``` 1681 | 1682 | ## Strict Mode 1683 | --- 1684 | The strict mode, when turned on, shows potential errors made by the developer: 1685 | ```js 1686 | a = 42; 1687 | // 42 1688 | 1689 | "use strict"; 1690 | b = 42; 1691 | // Error: `b` is not defined 1692 | ``` 1693 | It can also be enabled for a single function only: 1694 | ```js 1695 | function myfun(){ 1696 | "use strict"; 1697 | var myvar = 6; 1698 | } 1699 | ``` 1700 | Strict mode ensures the following: 1701 | 1702 | * New variables need to be declared with "var"; "var" is no longer optional. 1703 | * Attempts to write to non-writable variables throw an error rather than silently doing nothing. 1704 | * Attempts to delete undeletable properties throw an error rather than silently doing nothing. 1705 | * Octal numerals are disallowed. 1706 | 1707 | ## Regular expressions 1708 | --- 1709 | Regular expressions can be used to match things in strings, such as numbers: 1710 | ```js 1711 | // Get all the numbers from this input (note you'll get an array of strings) 1712 | > "Alice was born in 1974, so she's 42 years old in 2016.".match(/[0-9]+/g) 1713 | [ '1974', '42', '2016' ] 1714 | 1715 | // Want to get numbers? Map them using the `Number` function 1716 | > "Alice was born in 1974, so she's 42 years old in 2016.".match(/[0-9]+/g).map(Number) 1717 | [ 1974, 42, 2016 ] 1718 | 1719 | // BE CAREFUL that if there's no match `match` will return `null` 1720 | > "Bob is seven years old.".match(/[0-9]+/g) 1721 | null 1722 | ``` 1723 | 1724 | Also, they can be used to replace parts of the strings: 1725 | ```js 1726 | // Mask all the digits of a credit card number, but the last 4 1727 | > "1234234534564567".replace(/\d(?=\d{4})/g, "*"); 1728 | '************4567' 1729 | ``` 1730 | 1731 | ## Math functions and constants 1732 | --- 1733 | ```js 1734 | // Get the PI number 1735 | > Math.PI 1736 | 3.141592653589793 1737 | 1738 | // Get the E number 1739 | > Math.E 1740 | 2.718281828459045 1741 | 1742 | // Maximum between two numbers 1743 | > Math.max(7, 42) 1744 | 42 1745 | 1746 | // Minimum between numbers (arguments) 1747 | > Math.min(7, 42, 255, 264) 1748 | 7 1749 | 1750 | // Power 1751 | > Math.pow(2, 4) 1752 | 16 1753 | 1754 | // Random number between 0 (inclusive) and 1 (exclusive) 1755 | > Math.random() 1756 | 0.2114640628617317 1757 | 1758 | // Round 1759 | > Math.round(41.8) 1760 | 42 1761 | ``` 1762 | 1763 | ## Dates 1764 | --- 1765 | A Date is an object that contains a given time to millisecond precision. Unlike strings and numbers, the date must be explicitly created with the new operator. 1766 | ```js 1767 | var now = new Date(); 1768 | now.getFullYear(); 1769 | // => 2016 1770 | ``` 1771 | By default, the Date object contains the current date and time found on the computer, but can be set to any date or time desired. 1772 | 1773 | ```js 1774 | var time_before_2000 = new Date(1999, 12, 31, 23, 59, 59, 999); 1775 | ``` 1776 | 1777 | ## Handling JSON 1778 | --- 1779 | Handling JSON may require adding a supporting library, which creates the global JSON object. This object is present natively only in new browsers (e.g. FF 3.5, IE8). 1780 | 1781 | ```js 1782 | //Parsing JSON: 1783 | var myObject = JSON.parse(myJSONtext) 1784 | 1785 | //Creating JSON: 1786 | var myJSONText = JSON.stringify(myObject); 1787 | ``` 1788 | 1789 | ## Imperative VS Object Oriented VS Functional Approach 1790 | --- 1791 | A simple use case where users are prompted to input some words after clicking on a button and they get back all words capitalized their first letter; could be solved by all different paradigms. 1792 | ### Imperative 1793 | ```js 1794 | var result; 1795 | function getText() { 1796 | var someText = prompt("Give me something to capitalize"); 1797 | capWords(someText); 1798 | alert(result.join(" ")); 1799 | }; 1800 | function capWords(input) { 1801 | var counter; 1802 | var inputArray = input.split(" "); 1803 | var transformed = ""; 1804 | result = []; 1805 | for (counter = 0; counter < inputArray.length; counter++) { 1806 | transformed = [ 1807 | inputArray[counter].charAt(0).toUpperCase(), 1808 | inputArray[counter].substring(1) 1809 | ].join(""); 1810 | result.push(transformed); 1811 | } 1812 | }; 1813 | document.getElementById("main_button").onclick = getText; 1814 | ``` 1815 | In the above approach: Variables are being defined on the global scope. Values are being passed around and modified by functions. DOM methods are being mixed with native JavaScript. The function names are not very descriptive, and that’s due in part to the fact that the whole thing relies on a context that may or may not exist. 1816 | 1817 | ### Object Oriented 1818 | ```js 1819 | (function() { 1820 | "use strict"; 1821 | var SomeText = function(text) { 1822 | this.text = text; 1823 | }; 1824 | SomeText.prototype.capify = function(str) { 1825 | var firstLetter = str.charAt(0); 1826 | var remainder = str.substring(1); 1827 | return [firstLetter.toUpperCase(), remainder].join(""); 1828 | }; 1829 | SomeText.prototype.capifyWords = function() { 1830 | var result = []; 1831 | var textArray = this.text.split(" "); 1832 | for (var counter = 0; counter < textArray.length; counter++) { 1833 | result.push(this.capify(textArray[counter])); 1834 | } 1835 | return result.join(" "); 1836 | }; 1837 | 1838 | document.getElementById("main_button").addEventListener("click", function(e) { 1839 | var something = prompt("Give me something to capitalize"); 1840 | var newText = new SomeText(something); 1841 | alert(newText.capifyWords()); 1842 | }); 1843 | }()); 1844 | ``` 1845 | In the above approach: Methods live on the new object’s prototype to keep memory use low. And all of the code is isolated in an anonymous immediately-invoked function expression so it doesn’t litter the global scope. There’s even a "use strict" directive to take advantage of the latest JavaScript engine, and the old-fashioned onclick method has been replaced with a shiny new `addEventListener`. 1846 | There are still many artifacts of the same imperative style that led us here. The methods in the constructor function rely on variables that are scoped to the parent object. There’s a looping construct for iterating across all the members of the array of strings. There’s a `counter` variable that serves no purpose other than to increment the progress through the `for` loop. 1847 | 1848 | ### Functional 1849 | ```js 1850 | (function() { 1851 | "use strict"; 1852 | var capify = function(str) { 1853 | return [str.charAt(0).toUpperCase(), str.substring(1)].join(""); 1854 | }; 1855 | var processWords = function(fn, str) { 1856 | return str.split(" ").map(fn).join(" "); 1857 | }; 1858 | document.getElementById("main_button").addEventListener("click", function(e) { 1859 | var something = prompt("Give me something to capitalize"); 1860 | alert(processWords(capify, something)); 1861 | }); 1862 | }()); 1863 | ``` 1864 | In the above approach: There are two functions, `capify` and `processWords`. Each of these functions is pure, meaning that they don’t rely on the state of the code they’re called from. The functions don’t create side effects that alter variables outside of themselves. 1865 | 1866 | ## Design Patterns 1867 | --- 1868 | ### Singleton 1869 | Singletons are used when you only ever want 1 object to be created. Let's say you want to create a game character with fixed stats 1870 | ```js 1871 | function Hero(name){ 1872 | 1873 | // Check if the object exists 1874 | if(typeof Hero.instance === 'object'){ 1875 | 1876 | // If it does return it 1877 | return Hero.instance; 1878 | } 1879 | 1880 | // if it doesn't then create the hero 1881 | this.name = name; 1882 | Hero.instance = this; 1883 | 1884 | return this; 1885 | } 1886 | 1887 | var derekHero = new Hero("Superman"); 1888 | console.log("Are hero is " + derekHero.name); 1889 | 1890 | // This won't change the name to Paul 1891 | var paulHero = new Hero("Batman"); 1892 | console.log("Are hero is " + paulHero.name); 1893 | ``` 1894 | 1895 | ### Factory 1896 | The factory pattern can be used to generate different objects on request 1897 | ```js 1898 | function Sword(desc){ 1899 | this.weaponType = "Sword"; 1900 | this.metal = desc.metal || "Steel"; 1901 | this.style = desc.style || "Longsword"; 1902 | this.hasMagic = desc.hasMagic || false; 1903 | } 1904 | 1905 | function Bow(desc){ 1906 | this.weaponType = "Bow"; 1907 | this.material = desc.material || "Wood"; 1908 | this.style = desc.style || "Longbow"; 1909 | this.hasMagic = desc.hasMagic || false; 1910 | } 1911 | 1912 | function WeaponFactory(){}; 1913 | 1914 | WeaponFactory.prototype.makeWeapon = function(desc){ 1915 | var weaponClass = null; 1916 | 1917 | if(desc.weaponType === "Sword"){ 1918 | weaponClass = Sword; 1919 | } else if (desc.weaponType === "Bow"){ 1920 | weaponClass = Bow; 1921 | } else { 1922 | return false; 1923 | } 1924 | 1925 | return new weaponClass(desc); 1926 | 1927 | } 1928 | 1929 | var myWeaponFact = new WeaponFactory(); 1930 | 1931 | var bladeFist = myWeaponFact.makeWeapon({ 1932 | weaponType: "Sword", 1933 | metal: "Dark Iron", 1934 | style: "Scythe", 1935 | hasMagic: true 1936 | }); 1937 | 1938 | console.log(bladeFist.weaponType + " of type " + bladeFist.style + " crafted from " + bladeFist.metal); 1939 | ``` 1940 | ### Decorator 1941 | The decorator pattern allows you alter an object at run time 1942 | ```js 1943 | function Pizza(price){ 1944 | this.price = price || 10; 1945 | } 1946 | 1947 | Pizza.prototype.getPrice = function(){ 1948 | return this.price; 1949 | } 1950 | 1951 | function ExtraCheese(pizza){ 1952 | var prevPrice = pizza.price; 1953 | 1954 | pizza.price = prevPrice + 1; 1955 | } 1956 | 1957 | var myPizza = new Pizza(10); 1958 | 1959 | ExtraCheese(myPizza); 1960 | 1961 | console.log("Cost of Pizza : $" + myPizza.price); 1962 | ``` 1963 | 1964 | ### Observer 1965 | A single object notifies many objects (observers) when a state change occurs. 1966 | ```js 1967 | var Observable = function() { 1968 | this.subscribers = []; 1969 | } 1970 | 1971 | Observable.prototype = { 1972 | subscribe: function(subscriber) { 1973 | // Add the subscriber object to the list 1974 | this.subscribers.push(subscriber); 1975 | }, 1976 | unsubscribe: function(unsubscriber) { 1977 | 1978 | // Cycle through the subscriber array and delete 1979 | // the unsubscriber 1980 | for (i = 0; i < this.subscribers.length; i++) { 1981 | if (this.subscribers[i] === unsubscriber) { 1982 | this.subscribers.splice(i, 1); 1983 | 1984 | // We assume it only subscribed once so we 1985 | // leave after it is found 1986 | return unsubscriber.name; 1987 | } 1988 | } 1989 | }, 1990 | publish: function(data) { 1991 | 1992 | // Cycle through all subscribers and send them the update 1993 | for (i = 0; i < this.subscribers.length; i++) { 1994 | this.subscribers[i].receiveData(data); 1995 | } 1996 | } 1997 | }; 1998 | 1999 | var OrganFanny = { 2000 | name: "Organ Fanny", 2001 | receiveData: function(data){ 2002 | console.log(this.name + " received your info : " + data); 2003 | } 2004 | } 2005 | 2006 | var BoldmanYaks = { 2007 | name: "Boldman Yaks", 2008 | receiveData: function(data){ 2009 | console.log(this.name + " received your info : " + data); 2010 | } 2011 | } 2012 | 2013 | // Add subscribers and alert them 2014 | observable = new Observable(); 2015 | observable.subscribe(OrganFanny); 2016 | observable.subscribe(BoldmanYaks); 2017 | observable.publish('IBM at $145.30'); 2018 | 2019 | console.log(observable.unsubscribe(OrganFanny) + " Unsubscribed"); 2020 | 2021 | observable.publish('IBM at $145.33'); 2022 | ``` 2023 | 2024 | ## Some Optimization Workarounds 2025 | --- 2026 | * High Level Optimization 2027 | * Algorithmic Optimization (Mathematical Analysis) 2028 | * Simplification 2029 | * Low Level Optimization 2030 | * Loop Unrolling 2031 | * Strength Reduction 2032 | * Duff's Device 2033 | * Clean Loops 2034 | * External Tools & Libraries for speeding/optimizing/compressing JavaScript code 2035 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman 2 | title: Javascript Handbook 3 | description: A Hand Crafted Markdown Document that Contains All Major Javascript Topics Covered! 4 | show_downloads: true 5 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | {% seo %} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |