mirror of
https://github.com/chubin/cheat.sh.git
synced 2024-11-29 23:36:40 +03:00
565 lines
52 KiB
Plaintext
565 lines
52 KiB
Plaintext
[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
|
||
[38;5;246m// true[39m
|
||
|
||
[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
|