2019-02-17 16:03:46 +03:00
[38;5;246m// Single-line comments start with two slashes. [39m
[38;5;246m/* Multiline comments start with slash-star, [39m
[38;5;246m and end with star-slash */ [39m
[38;5;246m// Statements can be terminated by ; [39m
[38;5;252mdoStuff [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;246m// ... but they don't have to be, as semicolons are automatically inserted [39m
[38;5;246m// wherever there's a newline, except in certain cases. [39m
[38;5;252mdoStuff [39m [38;5;252m( [39m [38;5;252m) [39m
[38;5;246m// Because those cases can cause unexpected results, we'll keep on using [39m
[38;5;246m// semicolons in this guide. [39m
[38;5;246m/////////////////////////////////// [39m
[38;5;246m// 1. Numbers, Strings and Operators [39m
[38;5;246m// JavaScript has one number type (which is a 64-bit IEEE 754 double). [39m
[38;5;246m// Doubles have a 52-bit mantissa, which is enough to store integers [39m
[38;5;246m// up to about 9✕10¹⁵ precisely. [39m
[38;5;67m3 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 3 [39m
[38;5;67m1.5 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 1.5 [39m
[38;5;246m// Some basic arithmetic works as you'd expect. [39m
[38;5;67m1 [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;67m1 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 2 [39m
[38;5;67m0.1 [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;67m0.2 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 0.30000000000000004 [39m
[38;5;67m8 [39m [38;5;252m [39m [38;5;252m- [39m [38;5;252m [39m [38;5;67m1 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 7 [39m
[38;5;67m10 [39m [38;5;252m [39m [38;5;252m* [39m [38;5;252m [39m [38;5;67m2 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 20 [39m
[38;5;67m35 [39m [38;5;252m [39m [38;5;252m/ [39m [38;5;252m [39m [38;5;67m5 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 7 [39m
[38;5;246m// Including uneven division. [39m
[38;5;67m5 [39m [38;5;252m [39m [38;5;252m/ [39m [38;5;252m [39m [38;5;67m2 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 2.5 [39m
[38;5;246m// And modulo division. [39m
[38;5;67m10 [39m [38;5;252m [39m [38;5;252m% [39m [38;5;252m [39m [38;5;67m2 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 0 [39m
[38;5;67m30 [39m [38;5;252m [39m [38;5;252m% [39m [38;5;252m [39m [38;5;67m4 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 2 [39m
[38;5;67m18.5 [39m [38;5;252m [39m [38;5;252m% [39m [38;5;252m [39m [38;5;67m7 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 4.5 [39m
[38;5;246m// Bitwise operations also work; when you perform a bitwise operation your float [39m
[38;5;246m// is converted to a signed int *up to* 32 bits. [39m
[38;5;67m1 [39m [38;5;252m [39m [38;5;252m<< [39m [38;5;252m [39m [38;5;67m2 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 4 [39m
[38;5;246m// Precedence is enforced with parentheses. [39m
[38;5;252m( [39m [38;5;67m1 [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;67m3 [39m [38;5;252m) [39m [38;5;252m [39m [38;5;252m* [39m [38;5;252m [39m [38;5;67m2 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 8 [39m
[38;5;246m// There are three special not-a-real-number values: [39m
[38;5;70;01mInfinity [39;00m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// result of e.g. 1/0 [39m
[38;5;252m- [39m [38;5;70;01mInfinity [39;00m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// result of e.g. -1/0 [39m
[38;5;70;01mNaN [39;00m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// result of e.g. 0/0, stands for 'Not a Number' [39m
[38;5;246m// There's also a boolean type. [39m
[38;5;70;01mtrue [39;00m [38;5;252m; [39m
[38;5;70;01mfalse [39;00m [38;5;252m; [39m
[38;5;246m// Strings are created with ' or ". [39m
[38;5;214m'abc' [39m [38;5;252m; [39m
[38;5;214m"Hello, world" [39m [38;5;252m; [39m
[38;5;246m// Negation uses the ! symbol [39m
[38;5;252m! [39m [38;5;70;01mtrue [39;00m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = false [39m
[38;5;252m! [39m [38;5;70;01mfalse [39;00m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = true [39m
[38;5;246m// Equality is === [39m
[38;5;67m1 [39m [38;5;252m [39m [38;5;252m=== [39m [38;5;252m [39m [38;5;67m1 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = true [39m
[38;5;67m2 [39m [38;5;252m [39m [38;5;252m=== [39m [38;5;252m [39m [38;5;67m1 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = false [39m
[38;5;246m// Inequality is !== [39m
[38;5;67m1 [39m [38;5;252m [39m [38;5;252m!== [39m [38;5;252m [39m [38;5;67m1 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = false [39m
[38;5;67m2 [39m [38;5;252m [39m [38;5;252m!== [39m [38;5;252m [39m [38;5;67m1 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = true [39m
[38;5;246m// More comparisons [39m
[38;5;67m1 [39m [38;5;252m [39m [38;5;252m< [39m [38;5;252m [39m [38;5;67m10 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = true [39m
[38;5;67m1 [39m [38;5;252m [39m [38;5;252m> [39m [38;5;252m [39m [38;5;67m10 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = false [39m
[38;5;67m2 [39m [38;5;252m [39m [38;5;252m<= [39m [38;5;252m [39m [38;5;67m2 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = true [39m
[38;5;67m2 [39m [38;5;252m [39m [38;5;252m>= [39m [38;5;252m [39m [38;5;67m2 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = true [39m
[38;5;246m// Strings are concatenated with + [39m
[38;5;214m"Hello " [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;214m"world!" [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "Hello world!" [39m
[38;5;246m// ... which works with more than just strings [39m
[38;5;214m"1, 2, " [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;67m3 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "1, 2, 3" [39m
[38;5;214m"Hello " [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;252m[ [39m [38;5;214m"world" [39m [38;5;252m, [39m [38;5;252m [39m [38;5;214m"!" [39m [38;5;252m] [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "Hello world,!" [39m
[38;5;246m// and are compared with < and > [39m
[38;5;214m"a" [39m [38;5;252m [39m [38;5;252m< [39m [38;5;252m [39m [38;5;214m"b" [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = true [39m
[38;5;246m// Type coercion is performed for comparisons with double equals... [39m
[38;5;214m"5" [39m [38;5;252m [39m [38;5;252m== [39m [38;5;252m [39m [38;5;67m5 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = true [39m
[38;5;70;01mnull [39;00m [38;5;252m [39m [38;5;252m== [39m [38;5;252m [39m [38;5;70;01mundefined [39;00m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = true [39m
[38;5;246m// ...unless you use === [39m
[38;5;214m"5" [39m [38;5;252m [39m [38;5;252m=== [39m [38;5;252m [39m [38;5;67m5 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = false [39m
[38;5;70;01mnull [39;00m [38;5;252m [39m [38;5;252m=== [39m [38;5;252m [39m [38;5;70;01mundefined [39;00m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = false [39m
[38;5;246m// ...which can result in some weird behaviour... [39m
[38;5;67m13 [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;252m! [39m [38;5;67m0 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// 14 [39m
[38;5;214m"13" [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;252m! [39m [38;5;67m0 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// '13true' [39m
[38;5;246m// You can access characters in a string with `charAt` [39m
[38;5;214m"This is a string" [39m [38;5;252m. [39m [38;5;252mcharAt [39m [38;5;252m( [39m [38;5;67m0 [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 'T' [39m
[38;5;246m// ...or use `substring` to get larger pieces. [39m
[38;5;214m"Hello world" [39m [38;5;252m. [39m [38;5;252msubstring [39m [38;5;252m( [39m [38;5;67m0 [39m [38;5;252m, [39m [38;5;252m [39m [38;5;67m5 [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "Hello" [39m
[38;5;246m// `length` is a property, so don't use (). [39m
[38;5;214m"Hello" [39m [38;5;252m. [39m [38;5;252mlength [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 5 [39m
[38;5;246m// There's also `null` and `undefined`. [39m
[38;5;70;01mnull [39;00m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// used to indicate a deliberate non-value [39m
[38;5;70;01mundefined [39;00m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// used to indicate a value is not currently present (although [39m
[38;5;252m [39m [38;5;246m// `undefined` is actually a value itself) [39m
[38;5;246m// false, null, undefined, NaN, 0 and "" are falsy; everything else is truthy. [39m
[38;5;246m// Note that 0 is falsy and "0" is truthy, even though 0 == "0". [39m
[38;5;246m/////////////////////////////////// [39m
[38;5;246m// 2. Variables, Arrays and Objects [39m
[38;5;246m// Variables are declared with the `var` keyword. JavaScript is dynamically [39m
[38;5;246m// typed, so you don't need to specify type. Assignment uses a single `=` [39m
[38;5;246m// character. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252msomeVar [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m5 [39m [38;5;252m; [39m
[38;5;246m// If you leave the var keyword off, you won't get an error... [39m
[38;5;252msomeOtherVar [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m10 [39m [38;5;252m; [39m
[38;5;246m// ...but your variable will be created in the global scope, not in the scope [39m
[38;5;246m// you defined it in. [39m
[38;5;246m// Variables declared without being assigned to are set to undefined. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252msomeThirdVar [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = undefined [39m
[38;5;246m// If you want to declare a couple of variables, then you could use a comma [39m
[38;5;246m// separator [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252msomeFourthVar [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m2 [39m [38;5;252m, [39m [38;5;252m [39m [38;5;252msomeFifthVar [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m4 [39m [38;5;252m; [39m
[38;5;246m// There's shorthand for performing math operations on variables: [39m
[38;5;252msomeVar [39m [38;5;252m [39m [38;5;252m+= [39m [38;5;252m [39m [38;5;67m5 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// equivalent to someVar = someVar + 5; someVar is 10 now [39m
[38;5;252msomeVar [39m [38;5;252m [39m [38;5;252m*= [39m [38;5;252m [39m [38;5;67m10 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// now someVar is 100 [39m
[38;5;246m// and an even-shorter-hand for adding or subtracting 1 [39m
[38;5;252msomeVar [39m [38;5;252m++ [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// now someVar is 101 [39m
[38;5;252msomeVar [39m [38;5;252m-- [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// back to 100 [39m
[38;5;246m// Arrays are ordered lists of values, of any type. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyArray [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252m[ [39m [38;5;214m"Hello" [39m [38;5;252m, [39m [38;5;252m [39m [38;5;67m45 [39m [38;5;252m, [39m [38;5;252m [39m [38;5;70;01mtrue [39;00m [38;5;252m] [39m [38;5;252m; [39m
[38;5;246m// Their members can be accessed using the square-brackets subscript syntax. [39m
[38;5;246m// Array indices start at zero. [39m
[38;5;252mmyArray [39m [38;5;252m[ [39m [38;5;67m1 [39m [38;5;252m] [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 45 [39m
[38;5;246m// Arrays are mutable and of variable length. [39m
[38;5;252mmyArray [39m [38;5;252m. [39m [38;5;252mpush [39m [38;5;252m( [39m [38;5;214m"World" [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252mmyArray [39m [38;5;252m. [39m [38;5;252mlength [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 4 [39m
[38;5;246m// Add/Modify at specific index [39m
[38;5;252mmyArray [39m [38;5;252m[ [39m [38;5;67m3 [39m [38;5;252m] [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;214m"Hello" [39m [38;5;252m; [39m
[38;5;246m// Add and remove element from front or back end of an array [39m
[38;5;252mmyArray [39m [38;5;252m. [39m [38;5;252munshift [39m [38;5;252m( [39m [38;5;67m3 [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// Add as the first element [39m
[38;5;252msomeVar [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252mmyArray [39m [38;5;252m. [39m [38;5;252mshift [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// Remove first element and return it [39m
[38;5;252mmyArray [39m [38;5;252m. [39m [38;5;252mpush [39m [38;5;252m( [39m [38;5;67m3 [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// Add as the last element [39m
[38;5;252msomeVar [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252mmyArray [39m [38;5;252m. [39m [38;5;252mpop [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// Remove last element and return it [39m
[38;5;246m// Join all elements of an array with semicolon [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyArray0 [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252m[ [39m [38;5;67m32 [39m [38;5;252m, [39m [38;5;70;01mfalse [39;00m [38;5;252m, [39m [38;5;214m"js" [39m [38;5;252m, [39m [38;5;67m12 [39m [38;5;252m, [39m [38;5;67m56 [39m [38;5;252m, [39m [38;5;67m90 [39m [38;5;252m] [39m [38;5;252m; [39m
[38;5;252mmyArray0 [39m [38;5;252m. [39m [38;5;252mjoin [39m [38;5;252m( [39m [38;5;214m";" [39m [38;5;252m) [39m [38;5;252m [39m [38;5;246m// = "32;false;js;12;56;90" [39m
[38;5;246m// Get subarray of elements from index 1 (include) to 4 (exclude) [39m
[38;5;252mmyArray0 [39m [38;5;252m. [39m [38;5;252mslice [39m [38;5;252m( [39m [38;5;67m1 [39m [38;5;252m, [39m [38;5;67m4 [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = [false,"js",12] [39m
[38;5;246m// Remove 4 elements starting from index 2, and insert there strings [39m
[38;5;246m// "hi","wr" and "ld"; return removed subarray [39m
[38;5;252mmyArray0 [39m [38;5;252m. [39m [38;5;252msplice [39m [38;5;252m( [39m [38;5;67m2 [39m [38;5;252m, [39m [38;5;67m4 [39m [38;5;252m, [39m [38;5;214m"hi" [39m [38;5;252m, [39m [38;5;214m"wr" [39m [38;5;252m, [39m [38;5;214m"ld" [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = ["js",12,56,90] [39m
[38;5;246m// myArray0 === [32,false,"hi","wr","ld"] [39m
[38;5;246m// JavaScript's objects are equivalent to "dictionaries" or "maps" in other [39m
[38;5;246m// languages: an unordered collection of key-value pairs. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyObj [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252m{ [39m [38;5;252mkey1 [39m [38;5;252m: [39m [38;5;252m [39m [38;5;214m"Hello" [39m [38;5;252m, [39m [38;5;252m [39m [38;5;252mkey2 [39m [38;5;252m: [39m [38;5;252m [39m [38;5;214m"World" [39m [38;5;252m} [39m [38;5;252m; [39m
[38;5;246m// Keys are strings, but quotes aren't required if they're a valid [39m
[38;5;246m// JavaScript identifier. Values can be any type. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyObj [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252m{ [39m [38;5;252mmyKey [39m [38;5;252m: [39m [38;5;252m [39m [38;5;214m"myValue" [39m [38;5;252m, [39m [38;5;252m [39m [38;5;214m"my other key" [39m [38;5;252m: [39m [38;5;252m [39m [38;5;67m4 [39m [38;5;252m} [39m [38;5;252m; [39m
[38;5;246m// Object attributes can also be accessed using the subscript syntax, [39m
[38;5;252mmyObj [39m [38;5;252m[ [39m [38;5;214m"my other key" [39m [38;5;252m] [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 4 [39m
[38;5;246m// ... or using the dot syntax, provided the key is a valid identifier. [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmyKey [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "myValue" [39m
[38;5;246m// Objects are mutable; values can be changed and new keys added. [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmyThirdKey [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;70;01mtrue [39;00m [38;5;252m; [39m
[38;5;246m// If you try to access a value that's not yet set, you'll get undefined. [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmyFourthKey [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = undefined [39m
[38;5;246m/////////////////////////////////// [39m
[38;5;246m// 3. Logic and Control Structures [39m
[38;5;246m// The `if` structure works as you'd expect. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mcount [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m1 [39m [38;5;252m; [39m
[38;5;70;01mif [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;252mcount [39m [38;5;252m [39m [38;5;252m== [39m [38;5;252m [39m [38;5;67m3 [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;246m// evaluated if count is 3 [39m
[38;5;252m} [39m [38;5;252m [39m [38;5;70;01melse [39;00m [38;5;252m [39m [38;5;70;01mif [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;252mcount [39m [38;5;252m [39m [38;5;252m== [39m [38;5;252m [39m [38;5;67m4 [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;246m// evaluated if count is 4 [39m
[38;5;252m} [39m [38;5;252m [39m [38;5;70;01melse [39;00m [38;5;252m [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;246m// evaluated if it's not either 3 or 4 [39m
[38;5;252m} [39m
[38;5;246m// As does `while`. [39m
[38;5;70;01mwhile [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;70;01mtrue [39;00m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;246m// An infinite loop! [39m
[38;5;252m} [39m
[38;5;246m// Do-while loops are like while loops, except they always run at least once. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252minput [39m [38;5;252m; [39m
[38;5;70;01mdo [39;00m [38;5;252m [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252minput [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252mgetInput [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m} [39m [38;5;252m [39m [38;5;70;01mwhile [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;252m! [39m [38;5;252misValid [39m [38;5;252m( [39m [38;5;252minput [39m [38;5;252m) [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;246m// The `for` loop is the same as C and Java: [39m
[38;5;246m// initialization; continue condition; iteration. [39m
[38;5;70;01mfor [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mi [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m0 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;252mi [39m [38;5;252m [39m [38;5;252m< [39m [38;5;252m [39m [38;5;67m5 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;252mi [39m [38;5;252m++ [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;246m// will run 5 times [39m
[38;5;252m} [39m
[38;5;246m// Breaking out of labeled loops is similar to Java [39m
[38;5;252mouter [39m [38;5;252m: [39m
[38;5;70;01mfor [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mi [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m0 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;252mi [39m [38;5;252m [39m [38;5;252m< [39m [38;5;252m [39m [38;5;67m10 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;252mi [39m [38;5;252m++ [39m [38;5;252m) [39m [38;5;252m [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mfor [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mj [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m0 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;252mj [39m [38;5;252m [39m [38;5;252m< [39m [38;5;252m [39m [38;5;67m10 [39m [38;5;252m; [39m [38;5;252m [39m [38;5;252mj [39m [38;5;252m++ [39m [38;5;252m) [39m [38;5;252m [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mif [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;252mi [39m [38;5;252m [39m [38;5;252m== [39m [38;5;252m [39m [38;5;67m5 [39m [38;5;252m [39m [38;5;252m&& [39m [38;5;252m [39m [38;5;252mj [39m [38;5;252m [39m [38;5;252m== [39m [38;5;67m5 [39m [38;5;252m) [39m [38;5;252m [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mbreak [39;00m [38;5;252m [39m [38;5;252mouter [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;246m// breaks out of outer loop instead of only the inner one [39m
[38;5;252m [39m [38;5;252m} [39m
[38;5;252m [39m [38;5;252m} [39m
[38;5;252m} [39m
[38;5;246m// The for/in statement allows iteration over properties of an object. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mdescription [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;214m"" [39m [38;5;252m; [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mperson [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252m{ [39m [38;5;252mfname [39m [38;5;252m: [39m [38;5;214m"Paul" [39m [38;5;252m, [39m [38;5;252m [39m [38;5;252mlname [39m [38;5;252m: [39m [38;5;214m"Ken" [39m [38;5;252m, [39m [38;5;252m [39m [38;5;252mage [39m [38;5;252m: [39m [38;5;67m18 [39m [38;5;252m} [39m [38;5;252m; [39m
[38;5;70;01mfor [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mx [39m [38;5;252m [39m [38;5;70;01min [39;00m [38;5;252m [39m [38;5;252mperson [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252mdescription [39m [38;5;252m [39m [38;5;252m+= [39m [38;5;252m [39m [38;5;252mperson [39m [38;5;252m[ [39m [38;5;252mx [39m [38;5;252m] [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;214m" " [39m [38;5;252m; [39m
[38;5;252m} [39m [38;5;252m [39m [38;5;246m// description = 'Paul Ken 18 ' [39m
[38;5;246m// The for/of statement allows iteration over iterable objects (including the built-in String, [39m
[38;5;246m// Array, e.g. the Array-like arguments or NodeList objects, TypedArray, Map and Set, [39m
[38;5;246m// and user-defined iterables). [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyPets [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;214m"" [39m [38;5;252m; [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mpets [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252m[ [39m [38;5;214m"cat" [39m [38;5;252m, [39m [38;5;252m [39m [38;5;214m"dog" [39m [38;5;252m, [39m [38;5;252m [39m [38;5;214m"hamster" [39m [38;5;252m, [39m [38;5;252m [39m [38;5;214m"hedgehog" [39m [38;5;252m] [39m [38;5;252m; [39m
[38;5;70;01mfor [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mpet [39m [38;5;252m [39m [38;5;70;01mof [39;00m [38;5;252m [39m [38;5;252mpets [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252mmyPets [39m [38;5;252m [39m [38;5;252m+= [39m [38;5;252m [39m [38;5;252mpet [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;214m" " [39m [38;5;252m; [39m
[38;5;252m} [39m [38;5;252m [39m [38;5;246m// myPets = 'cat dog hamster hedgehog ' [39m
[38;5;246m// && is logical and, || is logical or [39m
[38;5;70;01mif [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;252mhouse [39m [38;5;252m. [39m [38;5;252msize [39m [38;5;252m [39m [38;5;252m== [39m [38;5;252m [39m [38;5;214m"big" [39m [38;5;252m [39m [38;5;252m&& [39m [38;5;252m [39m [38;5;252mhouse [39m [38;5;252m. [39m [38;5;252mcolour [39m [38;5;252m [39m [38;5;252m== [39m [38;5;252m [39m [38;5;214m"blue" [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252mhouse [39m [38;5;252m. [39m [38;5;252mcontains [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;214m"bear" [39m [38;5;252m; [39m
[38;5;252m} [39m
[38;5;70;01mif [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;252mcolour [39m [38;5;252m [39m [38;5;252m== [39m [38;5;252m [39m [38;5;214m"red" [39m [38;5;252m [39m [38;5;252m|| [39m [38;5;252m [39m [38;5;252mcolour [39m [38;5;252m [39m [38;5;252m== [39m [38;5;252m [39m [38;5;214m"blue" [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;246m// colour is either red or blue [39m
[38;5;252m} [39m
[38;5;246m// && and || "short circuit", which is useful for setting default values. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mname [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252motherName [39m [38;5;252m [39m [38;5;252m|| [39m [38;5;252m [39m [38;5;214m"default" [39m [38;5;252m; [39m
[38;5;246m// The `switch` statement checks for equality with `===`. [39m
[38;5;246m// Use 'break' after each case [39m
[38;5;246m// or the cases after the correct one will be executed too. [39m
[38;5;252mgrade [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;214m'B' [39m [38;5;252m; [39m
[38;5;70;01mswitch [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;252mgrade [39m [38;5;252m) [39m [38;5;252m [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mcase [39;00m [38;5;252m [39m [38;5;214m'A' [39m [38;5;252m: [39m
[38;5;252m [39m [38;5;252mconsole [39m [38;5;252m. [39m [38;5;252mlog [39m [38;5;252m( [39m [38;5;214m"Great job" [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;70;01mbreak [39;00m [38;5;252m; [39m
[38;5;252m [39m [38;5;70;01mcase [39;00m [38;5;252m [39m [38;5;214m'B' [39m [38;5;252m: [39m
[38;5;252m [39m [38;5;252mconsole [39m [38;5;252m. [39m [38;5;252mlog [39m [38;5;252m( [39m [38;5;214m"OK job" [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;70;01mbreak [39;00m [38;5;252m; [39m
[38;5;252m [39m [38;5;70;01mcase [39;00m [38;5;252m [39m [38;5;214m'C' [39m [38;5;252m: [39m
[38;5;252m [39m [38;5;252mconsole [39m [38;5;252m. [39m [38;5;252mlog [39m [38;5;252m( [39m [38;5;214m"You can do better" [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;70;01mbreak [39;00m [38;5;252m; [39m
[38;5;252m [39m [38;5;70;01mdefault [39;00m [38;5;252m: [39m
[38;5;252m [39m [38;5;252mconsole [39m [38;5;252m. [39m [38;5;252mlog [39m [38;5;252m( [39m [38;5;214m"Oy vey" [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;70;01mbreak [39;00m [38;5;252m; [39m
[38;5;252m} [39m
[38;5;246m/////////////////////////////////// [39m
[38;5;246m// 4. Functions, Scope and Closures [39m
[38;5;246m// JavaScript functions are declared with the `function` keyword. [39m
[38;5;70;01mfunction [39;00m [38;5;252m [39m [38;5;252mmyFunction [39m [38;5;252m( [39m [38;5;252mthing [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mreturn [39;00m [38;5;252m [39m [38;5;252mthing [39m [38;5;252m. [39m [38;5;252mtoUpperCase [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m} [39m
[38;5;252mmyFunction [39m [38;5;252m( [39m [38;5;214m"foo" [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "FOO" [39m
[38;5;246m// Note that the value to be returned must start on the same line as the [39m
[38;5;246m// `return` keyword, otherwise you'll always return `undefined` due to [39m
[38;5;246m// automatic semicolon insertion. Watch out for this when using Allman style. [39m
[38;5;70;01mfunction [39;00m [38;5;252m [39m [38;5;252mmyFunction [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mreturn [39;00m [38;5;252m [39m [38;5;246m// <- semicolon automatically inserted here [39m
[38;5;252m [39m [38;5;252m{ [39m [38;5;252mthisIsAn [39m [38;5;252m: [39m [38;5;252m [39m [38;5;214m'object literal' [39m [38;5;252m} [39m [38;5;252m; [39m
[38;5;252m} [39m
[38;5;252mmyFunction [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = undefined [39m
[38;5;246m// JavaScript functions are first class objects, so they can be reassigned to [39m
[38;5;246m// different variable names and passed to other functions as arguments - for [39m
[38;5;246m// example, when supplying an event handler: [39m
[38;5;70;01mfunction [39;00m [38;5;252m [39m [38;5;252mmyFunction [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;246m// this code will be called in 5 seconds' time [39m
[38;5;252m} [39m
[38;5;252msetTimeout [39m [38;5;252m( [39m [38;5;252mmyFunction [39m [38;5;252m, [39m [38;5;252m [39m [38;5;67m5000 [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;246m// Note: setTimeout isn't part of the JS language, but is provided by browsers [39m
[38;5;246m// and Node.js. [39m
[38;5;246m// Another function provided by browsers is setInterval [39m
[38;5;70;01mfunction [39;00m [38;5;252m [39m [38;5;252mmyFunction [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;246m// this code will be called every 5 seconds [39m
[38;5;252m} [39m
[38;5;252msetInterval [39m [38;5;252m( [39m [38;5;252mmyFunction [39m [38;5;252m, [39m [38;5;252m [39m [38;5;67m5000 [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;246m// Function objects don't even have to be declared with a name - you can write [39m
[38;5;246m// an anonymous function definition directly into the arguments of another. [39m
[38;5;252msetTimeout [39m [38;5;252m( [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;246m// this code will be called in 5 seconds' time [39m
[38;5;252m} [39m [38;5;252m, [39m [38;5;252m [39m [38;5;67m5000 [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;246m// JavaScript has function scope; functions get their own scope but other blocks [39m
[38;5;246m// do not. [39m
[38;5;70;01mif [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;70;01mtrue [39;00m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mi [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m5 [39m [38;5;252m; [39m
[38;5;252m} [39m
[38;5;252mi [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 5 - not undefined as you'd expect in a block-scoped language [39m
[38;5;246m// This has led to a common pattern of "immediately-executing anonymous [39m
[38;5;246m// functions", which prevent temporary variables from leaking into the global [39m
[38;5;246m// scope. [39m
[38;5;252m( [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mtemporary [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m5 [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;246m// We can access the global scope by assigning to the "global object", which [39m
[38;5;252m [39m [38;5;246m// in a web browser is always `window`. The global object may have a [39m
[38;5;252m [39m [38;5;246m// different name in non-browser environments such as Node.js. [39m
[38;5;252m [39m [38;5;31mwindow [39m [38;5;252m. [39m [38;5;252mpermanent [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m10 [39m [38;5;252m; [39m
[38;5;252m} [39m [38;5;252m) [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252mtemporary [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// raises ReferenceError [39m
[38;5;252mpermanent [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 10 [39m
[38;5;246m// One of JavaScript's most powerful features is closures. If a function is [39m
[38;5;246m// defined inside another function, the inner function has access to all the [39m
[38;5;246m// outer function's variables, even after the outer function exits. [39m
[38;5;70;01mfunction [39;00m [38;5;252m [39m [38;5;252msayHelloInFiveSeconds [39m [38;5;252m( [39m [38;5;252mname [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mprompt [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;214m"Hello, " [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;252mname [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;214m"!" [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;246m// Inner functions are put in the local scope by default, as if they were [39m
[38;5;252m [39m [38;5;246m// declared with `var`. [39m
[38;5;252m [39m [38;5;70;01mfunction [39;00m [38;5;252m [39m [38;5;252minner [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252malert [39m [38;5;252m( [39m [38;5;252mprompt [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;252m} [39m
[38;5;252m [39m [38;5;252msetTimeout [39m [38;5;252m( [39m [38;5;252minner [39m [38;5;252m, [39m [38;5;252m [39m [38;5;67m5000 [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;246m// setTimeout is asynchronous, so the sayHelloInFiveSeconds function will [39m
[38;5;252m [39m [38;5;246m// exit immediately, and setTimeout will call inner afterwards. However, [39m
[38;5;252m [39m [38;5;246m// because inner is "closed over" sayHelloInFiveSeconds, inner still has [39m
[38;5;252m [39m [38;5;246m// access to the `prompt` variable when it is finally called. [39m
[38;5;252m} [39m
[38;5;252msayHelloInFiveSeconds [39m [38;5;252m( [39m [38;5;214m"Adam" [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// will open a popup with "Hello, Adam!" in 5s [39m
[38;5;246m/////////////////////////////////// [39m
[38;5;246m// 5. More about Objects; Constructors and Prototypes [39m
[38;5;246m// Objects can contain functions. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyObj [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252mmyFunc [39m [38;5;252m: [39m [38;5;252m [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mreturn [39;00m [38;5;252m [39m [38;5;214m"Hello world!" [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;252m} [39m
[38;5;252m} [39m [38;5;252m; [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmyFunc [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "Hello world!" [39m
[38;5;246m// When functions attached to an object are called, they can access the object [39m
[38;5;246m// they're attached to using the `this` keyword. [39m
[38;5;252mmyObj [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252mmyString [39m [38;5;252m: [39m [38;5;252m [39m [38;5;214m"Hello world!" [39m [38;5;252m, [39m
[38;5;252m [39m [38;5;252mmyFunc [39m [38;5;252m: [39m [38;5;252m [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mreturn [39;00m [38;5;252m [39m [38;5;70;01mthis [39;00m [38;5;252m. [39m [38;5;252mmyString [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;252m} [39m
[38;5;252m} [39m [38;5;252m; [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmyFunc [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "Hello world!" [39m
[38;5;246m// What this is set to has to do with how the function is called, not where [39m
[38;5;246m// it's defined. So, our function doesn't work if it isn't called in the [39m
[38;5;246m// context of the object. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyFunc [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmyFunc [39m [38;5;252m; [39m
[38;5;252mmyFunc [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = undefined [39m
[38;5;246m// Inversely, a function can be assigned to the object and gain access to it [39m
[38;5;246m// through `this`, even if it wasn't attached when it was defined. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyOtherFunc [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mreturn [39;00m [38;5;252m [39m [38;5;70;01mthis [39;00m [38;5;252m. [39m [38;5;252mmyString [39m [38;5;252m. [39m [38;5;252mtoUpperCase [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m} [39m [38;5;252m; [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmyOtherFunc [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252mmyOtherFunc [39m [38;5;252m; [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmyOtherFunc [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "HELLO WORLD!" [39m
[38;5;246m// We can also specify a context for a function to execute in when we invoke it [39m
[38;5;246m// using `call` or `apply`. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252manotherFunc [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252ms [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mreturn [39;00m [38;5;252m [39m [38;5;70;01mthis [39;00m [38;5;252m. [39m [38;5;252mmyString [39m [38;5;252m [39m [38;5;252m+ [39m [38;5;252m [39m [38;5;252ms [39m [38;5;252m; [39m
[38;5;252m} [39m [38;5;252m; [39m
[38;5;252manotherFunc [39m [38;5;252m. [39m [38;5;252mcall [39m [38;5;252m( [39m [38;5;252mmyObj [39m [38;5;252m, [39m [38;5;252m [39m [38;5;214m" And Hello Moon!" [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "Hello World! And Hello Moon!" [39m
[38;5;246m// The `apply` function is nearly identical, but takes an array for an argument [39m
[38;5;246m// list. [39m
[38;5;252manotherFunc [39m [38;5;252m. [39m [38;5;252mapply [39m [38;5;252m( [39m [38;5;252mmyObj [39m [38;5;252m, [39m [38;5;252m [39m [38;5;252m[ [39m [38;5;214m" And Hello Sun!" [39m [38;5;252m] [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "Hello World! And Hello Sun!" [39m
[38;5;246m// This is useful when working with a function that accepts a sequence of [39m
[38;5;246m// arguments and you want to pass an array. [39m
[38;5;31mMath [39m [38;5;252m. [39m [38;5;252mmin [39m [38;5;252m( [39m [38;5;67m42 [39m [38;5;252m, [39m [38;5;252m [39m [38;5;67m6 [39m [38;5;252m, [39m [38;5;252m [39m [38;5;67m27 [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 6 [39m
[38;5;31mMath [39m [38;5;252m. [39m [38;5;252mmin [39m [38;5;252m( [39m [38;5;252m[ [39m [38;5;67m42 [39m [38;5;252m, [39m [38;5;252m [39m [38;5;67m6 [39m [38;5;252m, [39m [38;5;252m [39m [38;5;67m27 [39m [38;5;252m] [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = NaN (uh-oh!) [39m
[38;5;31mMath [39m [38;5;252m. [39m [38;5;252mmin [39m [38;5;252m. [39m [38;5;252mapply [39m [38;5;252m( [39m [38;5;31mMath [39m [38;5;252m, [39m [38;5;252m [39m [38;5;252m[ [39m [38;5;67m42 [39m [38;5;252m, [39m [38;5;252m [39m [38;5;67m6 [39m [38;5;252m, [39m [38;5;252m [39m [38;5;67m27 [39m [38;5;252m] [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 6 [39m
[38;5;246m// But, `call` and `apply` are only temporary. When we want it to stick, we can [39m
[38;5;246m// use `bind`. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mboundFunc [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252manotherFunc [39m [38;5;252m. [39m [38;5;252mbind [39m [38;5;252m( [39m [38;5;252mmyObj [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252mboundFunc [39m [38;5;252m( [39m [38;5;214m" And Hello Saturn!" [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "Hello World! And Hello Saturn!" [39m
[38;5;246m// `bind` can also be used to partially apply (curry) a function. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mproduct [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252ma [39m [38;5;252m, [39m [38;5;252m [39m [38;5;252mb [39m [38;5;252m) [39m [38;5;252m{ [39m [38;5;252m [39m [38;5;70;01mreturn [39;00m [38;5;252m [39m [38;5;252ma [39m [38;5;252m [39m [38;5;252m* [39m [38;5;252m [39m [38;5;252mb [39m [38;5;252m; [39m [38;5;252m [39m [38;5;252m} [39m [38;5;252m; [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mdoubler [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252mproduct [39m [38;5;252m. [39m [38;5;252mbind [39m [38;5;252m( [39m [38;5;70;01mthis [39;00m [38;5;252m, [39m [38;5;252m [39m [38;5;67m2 [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252mdoubler [39m [38;5;252m( [39m [38;5;67m8 [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 16 [39m
[38;5;246m// When you call a function with the `new` keyword, a new object is created, and [39m
[38;5;246m// made available to the function via the `this` keyword. Functions designed to be [39m
[38;5;246m// called like that are called constructors. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mMyConstructor [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mthis [39;00m [38;5;252m. [39m [38;5;252mmyNumber [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m5 [39m [38;5;252m; [39m
[38;5;252m} [39m [38;5;252m; [39m
[38;5;252mmyNewObj [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;70;01mnew [39;00m [38;5;252m [39m [38;5;252mMyConstructor [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = {myNumber: 5} [39m
[38;5;252mmyNewObj [39m [38;5;252m. [39m [38;5;252mmyNumber [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 5 [39m
[38;5;246m// Unlike most other popular object-oriented languages, JavaScript has no [39m
[38;5;246m// concept of 'instances' created from 'class' blueprints; instead, JavaScript [39m
[38;5;246m// combines instantiation and inheritance into a single concept: a 'prototype'. [39m
[38;5;246m// Every JavaScript object has a 'prototype'. When you go to access a property [39m
[38;5;246m// on an object that doesn't exist on the actual object, the interpreter will [39m
[38;5;246m// look at its prototype. [39m
[38;5;246m// Some JS implementations let you access an object's prototype on the magic [39m
[38;5;246m// property `__proto__`. While this is useful for explaining prototypes it's not [39m
[38;5;246m// part of the standard; we'll get to standard ways of using prototypes later. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyObj [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252mmyString [39m [38;5;252m: [39m [38;5;252m [39m [38;5;214m"Hello world!" [39m
[38;5;252m} [39m [38;5;252m; [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyPrototype [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252mmeaningOfLife [39m [38;5;252m: [39m [38;5;252m [39m [38;5;67m42 [39m [38;5;252m, [39m
[38;5;252m [39m [38;5;252mmyFunc [39m [38;5;252m: [39m [38;5;252m [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mreturn [39;00m [38;5;252m [39m [38;5;70;01mthis [39;00m [38;5;252m. [39m [38;5;252mmyString [39m [38;5;252m. [39m [38;5;252mtoLowerCase [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;252m} [39m
[38;5;252m} [39m [38;5;252m; [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252m__proto__ [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252mmyPrototype [39m [38;5;252m; [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmeaningOfLife [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 42 [39m
[38;5;246m// This works for functions, too. [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmyFunc [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "hello world!" [39m
[38;5;246m// Of course, if your property isn't on your prototype, the prototype's [39m
[38;5;246m// prototype is searched, and so on. [39m
[38;5;252mmyPrototype [39m [38;5;252m. [39m [38;5;252m__proto__ [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252mmyBoolean [39m [38;5;252m: [39m [38;5;252m [39m [38;5;70;01mtrue [39;00m
[38;5;252m} [39m [38;5;252m; [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmyBoolean [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = true [39m
[38;5;246m// There's no copying involved here; each object stores a reference to its [39m
[38;5;246m// prototype. This means we can alter the prototype and our changes will be [39m
[38;5;246m// reflected everywhere. [39m
[38;5;252mmyPrototype [39m [38;5;252m. [39m [38;5;252mmeaningOfLife [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m43 [39m [38;5;252m; [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmeaningOfLife [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 43 [39m
[38;5;246m// The for/in statement allows iteration over properties of an object, [39m
[38;5;246m// walking up the prototype chain until it sees a null prototype. [39m
[38;5;70;01mfor [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mx [39m [38;5;252m [39m [38;5;70;01min [39;00m [38;5;252m [39m [38;5;252mmyObj [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252mconsole [39m [38;5;252m. [39m [38;5;252mlog [39m [38;5;252m( [39m [38;5;252mmyObj [39m [38;5;252m[ [39m [38;5;252mx [39m [38;5;252m] [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m} [39m
[38;5;246m///prints: [39m
[38;5;246m// Hello world! [39m
[38;5;246m// 43 [39m
[38;5;246m// [Function: myFunc] [39m
2019-05-09 22:53:34 +03:00
[38;5;246m// true [39m
2019-02-17 16:03:46 +03:00
[38;5;246m// To only consider properties attached to the object itself [39m
[38;5;246m// and not its prototypes, use the `hasOwnProperty()` check. [39m
[38;5;70;01mfor [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mx [39m [38;5;252m [39m [38;5;70;01min [39;00m [38;5;252m [39m [38;5;252mmyObj [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mif [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mhasOwnProperty [39m [38;5;252m( [39m [38;5;252mx [39m [38;5;252m) [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252mconsole [39m [38;5;252m. [39m [38;5;252mlog [39m [38;5;252m( [39m [38;5;252mmyObj [39m [38;5;252m[ [39m [38;5;252mx [39m [38;5;252m] [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;252m} [39m
[38;5;252m} [39m
[38;5;246m///prints: [39m
[38;5;246m// Hello world! [39m
[38;5;246m// We mentioned that `__proto__` was non-standard, and there's no standard way to [39m
[38;5;246m// change the prototype of an existing object. However, there are two ways to [39m
[38;5;246m// create a new object with a given prototype. [39m
[38;5;246m// The first is Object.create, which is a recent addition to JS, and therefore [39m
[38;5;246m// not available in all implementations yet. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyObj [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;31mObject [39m [38;5;252m. [39m [38;5;252mcreate [39m [38;5;252m( [39m [38;5;252mmyPrototype [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252mmyObj [39m [38;5;252m. [39m [38;5;252mmeaningOfLife [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 43 [39m
[38;5;246m// The second way, which works anywhere, has to do with constructors. [39m
[38;5;246m// Constructors have a property called prototype. This is *not* the prototype of [39m
[38;5;246m// the constructor function itself; instead, it's the prototype that new objects [39m
[38;5;246m// are given when they're created with that constructor and the new keyword. [39m
[38;5;252mMyConstructor [39m [38;5;252m. [39m [38;5;252mprototype [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;252mmyNumber [39m [38;5;252m: [39m [38;5;252m [39m [38;5;67m5 [39m [38;5;252m, [39m
[38;5;252m [39m [38;5;252mgetMyNumber [39m [38;5;252m: [39m [38;5;252m [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mreturn [39;00m [38;5;252m [39m [38;5;70;01mthis [39;00m [38;5;252m. [39m [38;5;252mmyNumber [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;252m} [39m
[38;5;252m} [39m [38;5;252m; [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyNewObj2 [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;70;01mnew [39;00m [38;5;252m [39m [38;5;252mMyConstructor [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252mmyNewObj2 [39m [38;5;252m. [39m [38;5;252mgetMyNumber [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 5 [39m
[38;5;252mmyNewObj2 [39m [38;5;252m. [39m [38;5;252mmyNumber [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m6 [39m [38;5;252m; [39m
[38;5;252mmyNewObj2 [39m [38;5;252m. [39m [38;5;252mgetMyNumber [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 6 [39m
[38;5;246m// Built-in types like strings and numbers also have constructors that create [39m
[38;5;246m// equivalent wrapper objects. [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyNumber [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;67m12 [39m [38;5;252m; [39m
[38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mmyNumberObj [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;70;01mnew [39;00m [38;5;252m [39m [38;5;31mNumber [39m [38;5;252m( [39m [38;5;67m12 [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252mmyNumber [39m [38;5;252m [39m [38;5;252m== [39m [38;5;252m [39m [38;5;252mmyNumberObj [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = true [39m
[38;5;246m// Except, they aren't exactly equivalent. [39m
[38;5;70;01mtypeof [39;00m [38;5;252m [39m [38;5;252mmyNumber [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 'number' [39m
[38;5;70;01mtypeof [39;00m [38;5;252m [39m [38;5;252mmyNumberObj [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = 'object' [39m
[38;5;252mmyNumber [39m [38;5;252m [39m [38;5;252m=== [39m [38;5;252m [39m [38;5;252mmyNumberObj [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = false [39m
[38;5;70;01mif [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;67m0 [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;246m// This code won't execute, because 0 is falsy. [39m
[38;5;252m} [39m
[38;5;70;01mif [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;70;01mnew [39;00m [38;5;252m [39m [38;5;31mNumber [39m [38;5;252m( [39m [38;5;67m0 [39m [38;5;252m) [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;246m// This code will execute, because wrapped numbers are objects, and objects [39m
[38;5;252m [39m [38;5;246m// are always truthy. [39m
[38;5;252m} [39m
[38;5;246m// However, the wrapper objects and the regular builtins share a prototype, so [39m
[38;5;246m// you can actually add functionality to a string, for instance. [39m
[38;5;31mString [39m [38;5;252m. [39m [38;5;252mprototype [39m [38;5;252m. [39m [38;5;252mfirstCharacter [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;70;01mreturn [39;00m [38;5;252m [39m [38;5;70;01mthis [39;00m [38;5;252m. [39m [38;5;252mcharAt [39m [38;5;252m( [39m [38;5;67m0 [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m} [39m [38;5;252m; [39m
[38;5;214m"abc" [39m [38;5;252m. [39m [38;5;252mfirstCharacter [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m [38;5;252m [39m [38;5;246m// = "a" [39m
[38;5;246m// This fact is often used in "polyfilling", which is implementing newer [39m
[38;5;246m// features of JavaScript in an older subset of JavaScript, so that they can be [39m
[38;5;246m// used in older environments such as outdated browsers. [39m
[38;5;246m// For instance, we mentioned that Object.create isn't yet available in all [39m
[38;5;246m// implementations, but we can still use it with this polyfill: [39m
[38;5;70;01mif [39;00m [38;5;252m [39m [38;5;252m( [39m [38;5;31mObject [39m [38;5;252m. [39m [38;5;252mcreate [39m [38;5;252m [39m [38;5;252m=== [39m [38;5;252m [39m [38;5;70;01mundefined [39;00m [38;5;252m) [39m [38;5;252m{ [39m [38;5;252m [39m [38;5;246m// don't overwrite it if it exists [39m
[38;5;252m [39m [38;5;31mObject [39m [38;5;252m. [39m [38;5;252mcreate [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252mproto [39m [38;5;252m) [39m [38;5;252m{ [39m
[38;5;252m [39m [38;5;246m// make a temporary constructor with the right prototype [39m
[38;5;252m [39m [38;5;70;01mvar [39;00m [38;5;252m [39m [38;5;252mConstructor [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;70;01mfunction [39;00m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m{ [39m [38;5;252m} [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;252mConstructor [39m [38;5;252m. [39m [38;5;252mprototype [39m [38;5;252m [39m [38;5;252m= [39m [38;5;252m [39m [38;5;252mproto [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;246m// then use it to create a new, appropriately-prototyped object [39m
[38;5;252m [39m [38;5;70;01mreturn [39;00m [38;5;252m [39m [38;5;70;01mnew [39;00m [38;5;252m [39m [38;5;252mConstructor [39m [38;5;252m( [39m [38;5;252m) [39m [38;5;252m; [39m
[38;5;252m [39m [38;5;252m} [39m [38;5;252m; [39m
[38;5;252m} [39m