└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # JavaScript: The Weird Parts 2 | 3 | Below is a list of notes made for the course JavaScript: The Weird Parts. 4 | 5 | ## Table of Contents 6 | - [JavaScript: The Weird Parts](#javascript-the-weird-parts) 7 | * [01. Execution Contexts and Lexical Environments](#01-execution-contexts-and-lexical-environments) 8 | + [Syntax Parser](#syntax-parser) 9 | + [Lexical Environment](#lexical-environment) 10 | + [Execution Context](#execution-context) 11 | + [Name/Value Pair](#namevalue-pair) 12 | + [Object](#object) 13 | + [Hoisting](#hoisting) 14 | + [Phases of execution context inside JavaScript](#phases-of-execution-context-inside-javascript) 15 | + [JavaScript is single threaded, synchronous execution](#javascript-is-single-threaded-synchronous-execution) 16 | + [Invocation](#invocation) 17 | + [Execution Stack](#execution-stack) 18 | + [Variable environment](#variable-environment) 19 | + [Scope Chain](#scope-chain) 20 | + [Event Queue](#event-queue) 21 | * [02. Types and Operators](#02-types-and-operators) 22 | + [Dynamic Typing](#dynamic-typing) 23 | + [Primitive Type](#primitive-type) 24 | + [Operator](#operator) 25 | + [Operator Precedence](#operator-precedence) 26 | + [Associativity](#associativity) 27 | + [Coercion](#coercion) 28 | + [Short Circuiting](#short-circuiting) 29 | + [Frameworks](#frameworks) 30 | * [03. Objects and Functions](#03-objects-and-functions) 31 | + [Namespace](#namespace) 32 | + [First Class Functions](#first-class-functions) 33 | + [Expression vs Statement](#expression-vs-statement) 34 | + [Pass-by-value and pass-by-reference](#pass-by-value-and-pass-by-reference) 35 | + [Objects, Functions, and 'this'](#objects-functions-and-this) 36 | + ['arguments' and REST](#arguments-and-rest) 37 | + [Immediately Invoked Function Expressions (IIFE)s](#immediately-invoked-function-expressions-iifes) 38 | + [Closures](#closures) 39 | + [Function Factories](#function-factories) 40 | + [Callback Functions and Closures](#callback-functions-and-closures) 41 | + [Call, Apply, and Bind](#call-apply-and-bind) 42 | + [Functional Programming](#functional-programming) 43 | * [04. Object-Oriented JavaScript and Prototypal Inheritance](#04-object-oriented-javascript-and-prototypal-inheritance) 44 | + [Prototypal Inheritance](#prototypal-inheritance) 45 | + [Reflection and Extend](#reflection-and-extend) 46 | * [05. Building Objects](#05-building-objects) 47 | + [Function Constructors, 'new', and The History of JavaScript](#function-constructors-new-and-the-history-of-javascript) 48 | + [Function Constructors and '.prototypes'](#function-constructors-and-prototypes) 49 | + ['new' and Functions](#new-and-functions) 50 | + [Built-in Function Constructors](#built-in-function-constructors) 51 | + [Arrays and for ... in](#arrays-and-for--in) 52 | + [Object.create and Pure Prototypal Inheritance](#objectcreate-and-pure-prototypal-inheritance) 53 | + [ES6 and Classes](#es6-and-classes) 54 | 55 | ## 01. Execution Contexts and Lexical Environments 56 | ### Syntax Parser 57 | - A program that reads your code and determines what it does, and if the 58 | grammar is valid. 59 | 60 | ### Lexical Environment 61 | - Where something sits physically in the code you write, the positioning, where 62 | is it contained 63 | 64 | ### Execution Context 65 | - A wrapper to help manage the code that is currently running 66 | - The environment of the code being executed 67 | - Basically the scope of the code 68 | - An example: 69 | 70 | ```JavaScript 71 | // global context 72 | 73 | function a() { 74 | // a() itself is a execution context, and the global context is also an 75 | // execution context 76 | var myVar = 5; 77 | } 78 | ``` 79 | 80 | ### Name/Value Pair 81 | - A name which maps to a unique value, can be defined more than once, but can 82 | have only one value in any given context 83 | 84 | ### Object 85 | - A collection of Name/Value pairs, a function also counts as a value 86 | - If the value is a primitive, it's called a property. 87 | - If the value is a function, it's called a method. 88 | 89 | ### Hoisting 90 | - Setup memory space for variables and functions 91 | - Memory space is allocated for functions and variables, but variables are not 92 | yet defined. All values in JS are set initially to undefined. 93 | - Avoid using hoisting. Always declared methods and variables before using them. 94 | 95 | ### Phases of execution context inside JavaScript 96 | 1. Creation of variables and functions in memory 97 | 2. Execution phase 98 | 99 | ### JavaScript is single threaded, synchronous execution 100 | - Means that it can only execute one instruction at a time in the order that it 101 | appears. 102 | - Asynchronous events are actually handled synchronously. 103 | 104 | ### Invocation 105 | - Running a function, invoking a function 106 | 107 | ### Execution Stack 108 | - When the script is run, the global execution context is created, and is 109 | executed. 110 | - However, if there is another function invocation, it will stop at that line 111 | of code, and create and execute the execution context. 112 | 113 | ### Variable environment 114 | - Where the variables live, and how they relate to each other in memory 115 | 116 | ### Scope Chain 117 | - A scope is Where a variable is available in your code, and if it's truly the 118 | same copy, or a new one. 119 | - Basically what scope contains what scope/variables 120 | - If the variable is not found inside the execution context, it will search for 121 | the variable inside the outer lexical environment. If it is not found inside 122 | the inside the outer lexical environment, then it will go up the scope chain 123 | until it finds the variable, or when it reached the global execution context. 124 | - Note that just because your execution context is on top of another in the 125 | scope chain, it does not mean that it the one on the bottom is necessarily its 126 | parent. 127 | - An example: 128 | 129 | ```JavaScript 130 | // global context 131 | 132 | function a() { 133 | /* 134 | Function b is sitting lexically inside function a, so when it's referring to 135 | myVar, if it is not found inside function b, it will go to the parent 136 | execution context, which is positioned inside the scope chain. 137 | */ 138 | function b() { 139 | console.log(myVar); 140 | } 141 | 142 | b(); 143 | } 144 | 145 | var myVar = 1; 146 | a(); 147 | ``` 148 | 149 | ### Event Queue 150 | - Beside the scope chain list, there is also another list, called the event 151 | queue. 152 | - The event queue is populated with events, or populated events that we want to 153 | be notified of. 154 | - We can listen for events, and let a function handle that specific event. 155 | - The event queue is only periodically looked at when the execution stack is 156 | empty. 157 | - If an event is in the event queue, JS checks if there is a specific function 158 | to handle that specific event. 159 | - If there is function to handle an event, the function is added to the 160 | execution stack. 161 | 162 | ## 02. Types and Operators 163 | ### Dynamic Typing 164 | - The type of variable does not need to be defined, it is automatically 165 | determined in runtime. 166 | - The variables can hold different types of values, and the data stored can 167 | even be changed after the variable is declared. 168 | 169 | ### Primitive Type 170 | - A type of data that represents a single value. 171 | - There are not objects as they do not contain Name-Value pairs. 172 | - List of primitive data types: 173 | 1. Undefined 174 | - ***undefined*** represents a lack of existence, you should not assign a 175 | variable to this. 176 | 2. Null 177 | - ***null*** also represents a lack of existence, but you can set a 178 | variable to this. 179 | 3. Boolean 180 | - ***boolean*** is either *true* or *false* 181 | 4. Number 182 | - A ***number*** is a floating point number. There is only one type of 183 | floating type number inside JavaScript. 184 | 5. String 185 | - A ***String*** is a sequence of characters, and single quotes and 186 | double quotes can both be used to contain strings. 187 | 6. Symbol 188 | - A ***symbol*** is used in ES6 189 | 190 | ### Operator 191 | - Is a special function that is syntactically different. 192 | - JavaScript operators are infix notations. 193 | - Operators are actually just functions. 194 | 195 | ### Operator Precedence 196 | - Decides which operator function gets called first. 197 | 198 | ### Associativity 199 | - Decides what order operator functions get called, be it left-to-right , or 200 | right-to-left. 201 | - [Mozilla Developer Network on Associativity](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#Associativity) 202 | 203 | ### Coercion 204 | - **Coercion** is converting a value from one data type to another. 205 | - Also known as type casting. 206 | 207 | ### Short Circuiting 208 | - Because logical expressions are evaluated from left to right, they are tested 209 | for possible '**short-circuit**' evaluation using the following rules: 210 | - ***false*** && (anything) is short-circuit evaluated to ***false*** 211 | - ***true*** || (anything) is short-circuit evaluated to ***true*** 212 | - If the statement is evaluated to ***true***, the last operand will be 213 | executed. 214 | - An example: 215 | 216 | ```JavaScript 217 | 3 === 3 && 'cow' && console.log('chicken'); 218 | 219 | // Chicken will be logged to the console because if the condition is true, 220 | // the last operand will be executed. 221 | ``` 222 | - This is particularly useful when used in functions, because it allows for 223 | default parameters. 224 | 225 | ```JavaScript 226 | function greet(name) { 227 | name && console.log('Hi, ' + name + '!'); 228 | } 229 | 230 | greet('Sam'); 231 | ``` 232 | - However, you should take note that if you pass in a **falsey** value, such as 233 | ***undefined***, ***null***, or ***0***, the conditional statement will still 234 | evaluate to false, even if you have passed something in. 235 | 236 | ```JavaScript 237 | function plusOne(num) { 238 | num = num || 1; 239 | return num + 1; 240 | } 241 | 242 | // This statement will return 2, if you pass in a falsey value such as 0 243 | plusOne(0); 244 | ``` 245 | 246 | ### Frameworks 247 | - When you include several JavaScript files inside a HTML file, the browser 248 | does not actually create new execution contexts. Instead, the JavaScript files 249 | must be executed in order. 250 | 251 | ## 03. Objects and Functions 252 | ### Namespace 253 | - Is a container for variables and functions 254 | - Uses an object in JavaScript 255 | 256 | ```JavaScript 257 | 258 | var english = {}; 259 | var spanish = {}; 260 | 261 | english.greet = 'Hello!'; 262 | spanish.greet = 'Hola!'; 263 | 264 | ``` 265 | 266 | ### First Class Functions 267 | - You can do everything to them that you can do with other types. 268 | - E.g. 269 | - Being assigned to a variable 270 | - Passed around as an argument 271 | - Being created on the fly 272 | - In JavaScript, a function is actually a special type of object, hence, we can 273 | attach additional functions, variables, and even objects to it. 274 | - Functions also have some hidden special properties: 275 | - ***name***: The name is optional, the function can be anonymous. 276 | - ***code***: The code inside the function is actually stored inside a code 277 | variable, this code variable is actually invocable. 278 | - A function is actually just an object, whose code just happens to be one of 279 | the properties attached to the object. 280 | 281 | ### Expression vs Statement 282 | - An ***expression*** Is a unit of code that results in a value 283 | - A ***statement*** a unit of code that does not result in a value 284 | - E.g. 285 | 286 | ```JavaScript 287 | // The function greet here is just a statement, because it does not return a 288 | // value when evaluated. 289 | function greet() { 290 | console.log('hi'); 291 | } 292 | 293 | // This is an anonymous function, it is just a function without a name 294 | // In this case, the function here is an expression, because it returns a 295 | // value when evaluated, which is the function object 296 | var anonymousGreet = function() { 297 | console.log('hello'); 298 | } 299 | ``` 300 | 301 | ### Pass-by-value and pass-by-reference 302 | - Primitive data types are pass-by-value, whereas objects are pass-by-reference 303 | 304 | ### Objects, Functions, and 'this' 305 | - When a function is invoked, a new execution context is invoked. When the 306 | **code** 'property' is invoked, a new execution context is created, and put on 307 | the execution stack. That determines how the code is executed. 308 | - An execution context has: 309 | 1. Variable Environment 310 | 2. Outer Environment 311 | 3. '***this***' 312 | - The '***this***' keyword can point to different objects, and that depends on 313 | where the function is and where it's called. 314 | - When you're simply invoking a function, the ***this*** keyword inside will 315 | always point to the global object, the **Window** object. 316 | - If you're invoking a method inside a object, the ***this*** keyword will 317 | point to the object itself. 318 | - However, the '***this***' keyword when used inside a function inside a method 319 | inside an object, will point back to the global object. 320 | 321 | ```JavaScript 322 | // To be updated 323 | var c = { 324 | name: 'The c object', 325 | log: function() { 326 | this.name = 'Updated c object'; 327 | console.log(this); 328 | 329 | var setname = function(newname) { 330 | this.name = newname; 331 | } 332 | setname('Updated again! The c object'); 333 | } 334 | } 335 | c.log(); 336 | 337 | ``` 338 | 339 | ### 'arguments' and REST 340 | - **Arguments** are the parameters that you pass to a function 341 | - When an execution context is created, JavaScript creates the variable 342 | environment, outer environment, this, and ***arguments***. 343 | - The ***arguments*** variable is actually an array, and it contains all the 344 | arguments that you have passed to the function. 345 | - The rest operator takes the arguments that aren't defined specifically, and 346 | get wrapped into an array. 347 | 348 | ### Immediately Invoked Function Expressions (IIFE)s 349 | - IIFEs are function expressions that are immediately invoked once they are 350 | declared. 351 | - An example: 352 | 353 | ```JavaScript 354 | // function statement 355 | function greet(name) { 356 | console.log('Hello ' + name); 357 | } 358 | greet('John'); 359 | 360 | // using a function expression 361 | var greetFunc = function(name) { 362 | console.log('Hello ' + name); 363 | } 364 | greetFunc('John'); 365 | 366 | // using an IIFE 367 | var greeting = function(name) { 368 | return 'Hello ' + name; 369 | }('Adam'); 370 | console.log(greeting); 371 | 372 | /* 373 | Using an anonymous IIFE, by using the parentheses 374 | This is because JavaScript treats everything inside parentheses as 375 | expressions. This way you're telling JS that you're not creating a new 376 | statement, but creating a new expression instead. 377 | */ 378 | 379 | (function(name) { 380 | console.log('Hello ' + name); 381 | }('Adam')); 382 | ``` 383 | - By wrapping code in an IIFE, we can ensure that our code does not pollute 384 | the global namespace. (Like in any other normal function) 385 | 386 | ### Closures 387 | - A ***closure*** is the combination of a function and the lexical environment 388 | within which that function was declared. 389 | - It refers to a function having access to variables that it would normally 390 | would have access to, even though the execution context containing those 391 | variables is now gone. 392 | - In short, ***closures*** make sure that the scope of a method will always be 393 | intact, regardless of when or where you invoke a function. They make sure a 394 | function runs the way it's supposed to. 395 | - E.g. 396 | 397 | ```JavaScript 398 | function greet(whattosay) { 399 | return function(name) { 400 | console.log(whattosay + '' + name); 401 | } 402 | } 403 | 404 | var sayHi = greet('Hi'); 405 | 406 | /* 407 | The sayHi method still has access to the whattosay variable, even though 408 | the execution context of greet no longer exists. This is automatically 409 | done by JavaScript. 410 | 411 | */ 412 | sayHi('Tony'); 413 | ``` 414 | 415 | ```JavaScript 416 | function buildFunctions() { 417 | var arr = []; 418 | 419 | for(var i = 0; i < 3; i++) { 420 | arr.push(function() { 421 | console.log(i); 422 | }); 423 | } 424 | return arr; 425 | } 426 | 427 | var fs = buildFunctions(); 428 | 429 | /* 430 | All three methods above will log out the number 3. 431 | Because JavaScript actually prints out the current value of i, 432 | not the value of i at the point of time the function was pushed into the 433 | console. This is because the console logging is done after the method 434 | assignments, not during the creation of the functions. 435 | */ 436 | 437 | fs[0](); 438 | fs[1](); 439 | fs[2](); 440 | ``` 441 | - If you want to change the number that is logged, you could do this: 442 | 443 | ```JavaScript 444 | function buildFunctions2() { 445 | var arr = []; 446 | 447 | for(var i = 0; i < 3; i++) { 448 | let j = i; 449 | arr.push(function() { 450 | console.log(j); 451 | }); 452 | } 453 | return arr; 454 | } 455 | 456 | /* 457 | This works because a new variable is actually created every time the loop runs, 458 | hence, the variable j will be pointing to different memory locations even if 459 | they have the same variable name. 460 | */ 461 | 462 | // OR YOU COULD DO THIS (If you don't have ES5 support) 463 | 464 | function buildFunctions2() { 465 | var arr = []; 466 | 467 | for(var i = 0; i < 3; i++) { 468 | arr.push( 469 | (function(j) { 470 | return function() { 471 | console.log(j); 472 | } 473 | }(i)) 474 | ) 475 | } 476 | return arr; 477 | } 478 | 479 | /* 480 | The code above simply pushes a function that returns another function. Each 481 | of the functions has its very own execution context, and they contain different 482 | values of j. Hence, the console is able to log different values of j. 483 | */ 484 | 485 | var fs2 = buildFunctions2(); 486 | 487 | fs2[0](); 488 | fs2[1](); 489 | fs2[2](); 490 | ``` 491 | 492 | ### Function Factories 493 | - A function factory is simply a function that generates another function, but 494 | the function generated may vary. 495 | - Function factories take advantage of closures, which is the ability to make 496 | sure that the scope of a function will always be intact. 497 | 498 | ```JavaScript 499 | function makeGreeting(language) { 500 | return function(firstname, lastname) { 501 | if (language === 'en') { 502 | console.log('Hello '+ firstname + ' ' + lastname); 503 | } 504 | 505 | if (language === 'es') { 506 | console.log('Hola '+ firstname + ' ' + lastname); 507 | } 508 | }; 509 | } 510 | 511 | var greetEnglish = makeGreeting('en'); 512 | var greetSpanish = makeGreeting('es'); 513 | 514 | greetEnglish('John', 'Doe'); 515 | greetSpanish('John', 'Doa'); 516 | ``` 517 | 518 | ### Callback Functions and Closures 519 | - A callback function, is a function that you pass to another function, to be 520 | run when the other function is finished. 521 | - An example: 522 | 523 | ```JavaScript 524 | function sayHiLater() { 525 | var greeting = 'Hi'; 526 | 527 | setTimeout(function() { 528 | console.log(greeting); 529 | }, 3000); 530 | } 531 | 532 | sayHiLater(); 533 | ``` 534 | - But this does not work: 535 | 536 | ```JavaScript 537 | function sayHiLater(callback) { 538 | var greeting = 'Hi'; 539 | 540 | setTimeout(callback, 3000); 541 | } 542 | 543 | sayHiLater(function() { 544 | console.log(greeting); 545 | }); 546 | ``` 547 | - This is because the function is actually declared outside the function, and 548 | since it's parent execution context is not **sayHiLater**, it cannot access 549 | the variable greeting. 550 | 551 | ### Call, Apply, and Bind 552 | - The Function is just another special kind of object, it has the following 553 | attributes: 554 | 1. Name 555 | 2. Code (Invocable) 556 | 3. ***call()*** 557 | 4. ***apply()*** 558 | 5. ***bind()*** 559 | - Bind is used when you want to change the reference of this for a function 560 | - It creates a copy of your function, and whatever object you pass to the bind 561 | method, becomes the object that the '***this***' keyword points to. 562 | - The ***call*** function also lets you decide what the **this** variable will 563 | be. The first argument for ***call*** should be what the **this** variable 564 | should refer to. The rest of the arguments passed to it are the arguments 565 | that you will normally pass to a function. 566 | - The difference between the ***bind*** and the ***call*** method is that the 567 | ***call*** method actually executes the method. 568 | - The ***call*** method and the ***apply*** method perform the same actions, 569 | but the ***call*** method accepts the arguments directly in the parentheses, 570 | whereas the ***apply*** method accepts the arguments in an array format. 571 | - A use for **apply** and **call** would be function borrowing. 572 | - Function borrowing is used to reduce redundant code, by using functions from 573 | an object on another object. 574 | - Example of use of **bind**, **call**, and **apply**: 575 | 576 | ```JavaScript 577 | var person = { 578 | firstName: 'John', 579 | lastName: 'Doe', 580 | getFullName: function() { 581 | var fullName = this.firstName + ' ' + this.lastName; 582 | return fullName; 583 | } 584 | } 585 | 586 | var logName = function(lang1, lang2) { 587 | console.log('Logged: '+ this.getFullName()); 588 | console.log('Arguments: ' + lang1 + ' ' + lang2); 589 | console.log('-----------'); 590 | }; 591 | 592 | var logPersonName = logName.bind(person); 593 | 594 | logPersonName('en', 'cn'); 595 | 596 | logName.call(person, 'en', 'es'); 597 | 598 | logName.apply(person, ['en', 'my']); 599 | 600 | // You can also create a function on the fly and invoking it using apply and call 601 | 602 | (function(lang1, lang2) { 603 | console.log('Logged: '+ this.getFullName()); 604 | console.log('Arguments: ' + lang1 + ' ' + lang2); 605 | console.log('-----------'); 606 | }).call(person, 'en', 'ru'); 607 | 608 | // function borrowing 609 | var person2 = { 610 | firstName: 'Jane', 611 | lastName: 'Doe' 612 | }; 613 | 614 | person.getFullName.call(person2, 'en', 'ru'); 615 | 616 | ``` 617 | - Function currying is the act of creating a copy of a function but with some 618 | preset parameters. This is done by passing additional arguments to the bind 619 | method. 620 | 621 | ```JavaScript 622 | // function currying 623 | function multiply(a, b) { 624 | return a*b; 625 | } 626 | 627 | var multiplyByTwo = multiply.bind(this, 2); 628 | 629 | // is actually equals to 630 | function multiply(b) { 631 | var a = 2; 632 | return a*b; 633 | } 634 | 635 | ``` 636 | 637 | ```JavaScript 638 | function multiply(a, b, c) { 639 | return a * b * c; 640 | } 641 | 642 | function curriedMultiply(a) { 643 | return function (b) { 644 | return function (c) { 645 | return a * b * c; 646 | } 647 | } 648 | } 649 | 650 | console.log(multiply(5, 10, 3)); 651 | console.log(curriedMultiply(5)(10)(3)); 652 | ``` 653 | 654 | ### Functional Programming 655 | - Functional programming is a programming style where you think and code in 656 | terms of functions 657 | - Functional programming languages are languages that have first-class functions 658 | - Here are the examples of the use of first-class functions: 659 | 660 | ```JavaScript 661 | function mapForEach(arr, fn) { 662 | 663 | var newArr = []; 664 | for (var i=0; i < arr.length; i++) { 665 | newArr.push( 666 | fn(arr[i]) 667 | ); 668 | } 669 | return newArr; 670 | } 671 | 672 | var arr1 = [1,2,3]; 673 | console.log(arr1); 674 | 675 | var arr2 = mapForEach(arr1, function(item) { 676 | return item * 2; 677 | }); 678 | console.log(arr2); 679 | 680 | var arr3 = mapForEach(arr1, function(item) { 681 | return item > 2; 682 | }); 683 | console.log(arr3); 684 | 685 | var checkPastLimit = function(limiter, item) { 686 | return item > limiter; 687 | } 688 | 689 | // When additional arguments to the bind method, 690 | // a new copy of the method gets created with preset parameters. 691 | var arr4 = mapForEach(arr1, bindy(checkPastLimit, 1)); 692 | console.log(arr4); 693 | 694 | var checkPastLimitSimplified = function(limiter) { 695 | return function(limiter, item) { 696 | return item > limiter; 697 | }.bind(this, limiter); 698 | }; 699 | 700 | var arr5 = mapForEach(arr1, checkPastLimitSimplified(2)); 701 | console.log(arr5); 702 | 703 | ``` 704 | - Instead of just separating your code into functions, first class functions 705 | allow you to pass functions to your functions, and also return functions 706 | from your functions. 707 | - In functional programming, your functions should not mutate data, but instead 708 | output data from input data. 709 | 710 | ## 04. Object-Oriented JavaScript and Prototypal Inheritance 711 | ### Prototypal Inheritance 712 | - ***Inheritance*** is when one object gets access to the properties and 713 | methods of another object. 714 | - In prototypal inheritance, each object has its **\__proto__** property, 715 | which contains a **reference** to another object, which is its prototype. 716 | - The prototype of an object can also have a reference to its very own 717 | prototype. 718 | - When you're looking for a property on an object, if it doesn't find the 719 | property on the object you're specifying, JavaScript will go down the 720 | prototypal chain until it finds the property specified. 721 | - All objects in JavaScript have their own prototypes, except for the base 722 | *Object*. 723 | - An example would be that each function has the methods **bind**, **call**, 724 | and **apply** 725 | on its on prototype chain. 726 | - A code example: 727 | 728 | ```JavaScript 729 | var getCookies = function() { 730 | console.log('I has the cookies'); 731 | } 732 | 733 | // Instead of calling getCookies.__proto__.bind(this); 734 | // We can do this: 735 | 736 | getCookies.bind(this); 737 | 738 | ``` 739 | ### Reflection and Extend 740 | - ***Reflection*** means that an **object** can look at itself, and it can list 741 | and change its properties and methods. 742 | 743 | ```JavaScript 744 | var person = { 745 | firstname: 'Default', 746 | lastname: 'Default', 747 | getFullName: function() { 748 | return this.firstname + ' ' + this.lastname; 749 | } 750 | }; 751 | 752 | var john = { 753 | firstname: 'John', 754 | lastname: 'Doe' 755 | }; 756 | 757 | for (var prop in john) { 758 | // To check if the property is actually directly on the object 759 | if (john.hasOwnProperty(prop)) 760 | console.log(prop + ': ' + john[prop]); 761 | } 762 | 763 | var jim = { 764 | getFirstName: function() { 765 | return firstname; 766 | } 767 | }; 768 | 769 | // Using Lodash / Underscore JS 770 | _.extend(john, jim); 771 | ``` 772 | 773 | ## 05. Building Objects 774 | ### Function Constructors, 'new', and The History of JavaScript 775 | - A ***function constructor*** is actually just a normal function, that is used 776 | to construct objects. 777 | - When you create a new object using a function constructor, the following 778 | happens: 779 | 1. The '**new**' keyword creates a new empty object. 780 | 2. It then binds the '**this**' keyword to that of the new empty object. 781 | 3. It binds the ***\__proto__*** property of the new object to the prototype 782 | property of the function constructor. 783 | 4. It then executes the code inside the function constructor, which sets 784 | the properties of the object. 785 | 5. As long as the function constructor doesn't explicitly return a value, 786 | JavaScript will automatically return the object that was created. 787 | 788 | ### Function Constructors and '.prototypes' 789 | - When the function constructor is used, the prototype is already automatically 790 | set for the object. 791 | - Other than name and code, all functions in JavaScript have a property called 792 | ***prototype***. Unless the function is used as a function constructor, 793 | ***prototype*** will never be used. (It is only used by the **new** operator). 794 | - The ***prototype*** property on the function is not the prototype of the 795 | function (The prototypes of the function are actually accessed using the 796 | **\__proto__** keyword). 797 | - Instead, ***prototype*** is actually the prototype of any objects created 798 | using the function constructor. 799 | 800 | ```JavaScript 801 | function Person(firstname, lastname) { 802 | console.log(this); 803 | this.firstname = firstname; 804 | this.lastname = lastname; 805 | console.log('This function is invoked.'); 806 | } 807 | 808 | Person.prototype.getFullName = function() { 809 | return this.firstname + ' ' + this.lastname; 810 | }; 811 | 812 | // The 'new' keyword is actually an operator, which is used to actually 813 | // create a new object, and perform the binding of 'this' 814 | var john = new Person('John', 'Doe'); 815 | console.log(john); 816 | 817 | var jane = new Person('Jane', 'Doe'); 818 | ``` 819 | - When you create an object using the **new** keyword, a new empty object is 820 | created, it binds the '***this***' keyword to the new object, and it sets the 821 | ***\__proto__*** of the empty object to the ***prototype*** property of the 822 | function constructor that is called. 823 | - The ***prototype*** property of function constructors is where the 824 | ***\__proto__*** property of all objects created using the function 825 | constructors point to. 826 | - This means that you can add additional functionality to the objects later on, 827 | all at once since you're adding functionality to the prototype of the objects. 828 | - Properties are often setup inside the function constructors, because 829 | properties largely vary from object to object. 830 | - However, since objects created from the same class have mostly the same 831 | functionality, we could put functions on the prototype of the function 832 | constructor, and objects can refer to the function on its prototype. 833 | 834 | ### 'new' and Functions 835 | - Function constructors are actually just regular functions. 836 | - That means that if you forgot to use the ***new*** keyword when creating a 837 | new object, the function is still syntactically correct, and JavaScript won't 838 | catch the error. 839 | - When you try to create a new object without using the ***new*** keyword, the 840 | function constructor will return ***undefined***. Hence, an error will be 841 | thrown when you try to access the uncreated object. 842 | - As a rule of thumb, any function that is intended to be used as a function 843 | constructor, should start with a capital letter. 844 | 845 | ### Built-in Function Constructors 846 | - An example built-in function constructors are: 847 | 848 | ```JavaScript 849 | var a = new Number('3'); 850 | 851 | var b = new String('John'); 852 | 853 | 'John'.length; 854 | // is equal to 855 | var c = new String('John'); 856 | c.length; 857 | ``` 858 | - We could also add new functions to existing objects in JavaScript: 859 | 860 | ```JavaScript 861 | String.prototype.isLengthGreaterThan = function(limit) { 862 | // If this is called inside a string object, it would be pointing at your 863 | // String object. JavaScript takes care of this by going down the prototype 864 | // chain. 865 | return this.lengthh > limit; 866 | }; 867 | 868 | console.log('John'.isLengthGreaterThan(2)); 869 | 870 | Number.prototype.isPositive = function() { 871 | return this > 0; 872 | } 873 | ``` 874 | - Built-in functions constructors especially for primitive data types are 875 | dangerous. 876 | - When using built-in function constructors for creating primitives, actual 877 | primitives are not created. Hence, when strict comparison happens a primitive 878 | and a primitive created using a built-in function constructor, the two values 879 | will not be the same. 880 | - Moment.js is useful for manipulating dates in JavaScript 881 | 882 | ### Arrays and for ... in 883 | - An array in JavaScript is actually an object. 884 | - Whenever you're adding additional functionality to a built-in functionality 885 | constructor, when you use for ... in, the additional functionality 886 | gets triggered even if it was not explicitly called. 887 | - This is because the for ... in gets every property in the object, regardless 888 | if it is directly on the object itself, or on the prototype of the object. 889 | 890 | ```JavaScript 891 | Array.prototype.myCustomFeature = 'cool'; 892 | 893 | var arr = ['John', 'Jane', 'Jim']; 894 | 895 | // avoid this 896 | for (var prop in arr) { 897 | console.log(prop + ': ' + arr[prop]); 898 | } 899 | 900 | //use this instead 901 | for (var i=0; i < arr.length; i++) { 902 | console.log(arr[i]); 903 | } 904 | ``` 905 | 906 | ### Object.create and Pure Prototypal Inheritance 907 | - Object.create is a newer way to create objects, using pure prototypal 908 | inheritance concepts. 909 | - With Object.create, you create a new empty object, and the object that you 910 | have passed in becomes your prototype. 911 | - If you do not use '***this***' to refer to properties inside the object, 912 | JavaScript will not be able to locate the property that you want, since the 913 | creation of the object does not actually create a new execution context. 914 | - With this pattern, you simply override whatever you need to by simply adding 915 | the properties or methods to your created object. 916 | - A ***polyfill*** is code that adds a feature which the engine *may* lack. 917 | 918 | ```JavaScript 919 | // polyfill 920 | if(!Object.create) { 921 | Object.create = function (o) { 922 | if (arguments.length > 1) { 923 | throw new Error('Object.create implementation' 924 | + ' only accepts the first parameter.'); 925 | } 926 | function F() {}; 927 | F.prototype = o; 928 | return new F(); 929 | }; 930 | } 931 | 932 | var person = { 933 | firstname: 'Default', 934 | lastname: 'Default', 935 | greet: function() { 936 | return 'Hi ' + this.firstname; 937 | } 938 | }; 939 | 940 | // Object.create is just used to create others of person 941 | var john = Object.create(person); 942 | john.firstname = 'John'; 943 | john.lastname = 'Doe'; 944 | console.log(john); 945 | ``` 946 | 947 | ### ES6 and Classes 948 | - Classes in JavaScript are actually objects. When you create a new object from 949 | a class in JavaScript, you're actually creating an object from an object. 950 | - The ***extends*** keyword in JavaScript is actually just used to set the 951 | prototype of an object to another object. 952 | - ***Syntactic Sugar*** is just a different way to type something that doesn't 953 | change how it works under the hood. 954 | --------------------------------------------------------------------------------