├── README.html └── README.md /README.html: -------------------------------------------------------------------------------- 1 | README

JavaScript Cheat Sheet

1018 |

Based off of Learn X in Y Minutes.

1019 |

JavaScript (JS) is a dynamic interpreted language that powers the web. It is widely used in browsers (where JS scripts are interpreted by JavaScript engines like Chrome’s V8) and increasingly on servers (on a Node.js runtime environment).

1020 |

JS is a prototype-based scripting language with first-class functions and dynamic typing. Because of its super flexibility, JS supports multiple styles of programming including imperative, object-oriented and functional.

1021 |

Here’s what all those big words above mean:
1022 | - Interpreted Language: a language (eg. JS, Python) in which most of its implementations execute instructions directly, without previously compiling a program into machine-language instructions like compiled languages do (eg. C++)
1023 | - JavaScript Engine: a virtual machine that interprets and executes JS
1024 | - Prototype-Based: unlike classical OOP with classes and objects, in JS, objects are cloned from other objects, and all objects have prototypes (kinda like the template they inherit from)
1025 | - First-Class Functions: JS supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures
1026 | - Dynamically Typed: The “type” of all variables is only interpreted at run-time unlike statically typed languages where all variables have a type at compile-time
1027 | - Imperative Programming: Statement based programming
1028 | - Object-Oriented Programming: Object based programming
1029 | - Functional Programming: Function based programming

1030 | 1031 |
    1032 |
  1. Basics
      1033 |
    1. Primitives
    2. 1034 |
    3. Operators
    4. 1035 |
    1036 |
  2. 1037 |
  3. More Basic Syntax
      1038 |
    1. Variables
    2. 1039 |
    3. Arrays
    4. 1040 |
    5. Logic and Control Structures
    6. 1041 |
    1042 |
  4. 1043 |
  5. Objects and Functions
      1044 |
    1. Objects
    2. 1045 |
    3. Functions
    4. 1046 |
    5. Bind, Call and Apply
    6. 1047 |
    1048 |
  6. 1049 |
  7. Function Execution, Variable Scope, Closures & Callbacks
      1050 |
    1. Hoisting
    2. 1051 |
    3. Scope Chain
    4. 1052 |
    5. Closures
    6. 1053 |
    7. Callbacks
    8. 1054 |
    1055 |
  8. 1056 |
  9. Object-Oriented JS and Prototypal Inheritance
      1057 |
    1. Constructors
    2. 1058 |
    3. Prototypes
    4. 1059 |
    5. Prototypal Inheritance
    6. 1060 |
    7. Built-In Constructors
    8. 1061 |
    1062 |
  10. 1063 |
  11. Bugs and Error Handling
  12. 1064 |
  13. New ES6 stuff
  14. 1065 |
1066 |

TODO: Add 8. Useful Libraries (LoDash, jQuery), 9. Javascript in the browser, 10. NodeJS

1067 |

1068 |

1. Basics

1069 |

Everything in JS is either an object or a primitive.
1070 |


1071 | // This is a single line comment,
1072 | /* and this is a 
1073 | multiline comment */
1074 | 
1075 | // Semicolons (;) to terminate lines are optional
1076 | // However, the JS engine will (usually) automatically insert semicolons upon seeing '\n'
1077 | // This can cause some weird behaviour so ALWAYS use semicolons
1078 | doStuff();
1079 | 

1080 |

1081 |

i. Primitives: Number, String, Boolean (and some special ones)

1082 |

// JavaScript has one number type (which is a 64-bit IEEE 754 double).
1083 | // Doubles have a 52-bit mantissa, which is enough to store integers
1084 | //    up to about 9✕10¹⁵ precisely.
1085 | 3; // = 3
1086 | 1.5; // = 1.5
1087 | 
1088 | // Some basic arithmetic works as you'd expect.
1089 | 1 + 1; // = 2
1090 | 0.1 + 0.2; // = 0.30000000000000004 (funky floating point arithmetic--be careful!)
1091 | 8 - 1; // = 7
1092 | 10 * 2; // = 20
1093 | 35 / 5; // = 7
1094 | 
1095 | // Including uneven division.
1096 | 5 / 2; // = 2.5
1097 | 
1098 | // Bitwise operations also work; when you perform a bitwise operation your float
1099 | // is converted to a signed int *up to* 32 bits.
1100 | 1 << 2; // = 4
1101 | 
1102 | // Precedence is enforced with parentheses.
1103 | (1 + 3) * 2; // = 8
1104 | 
1105 | // There are special primitive values:
1106 | Infinity; // result of e.g. 1/0
1107 | -Infinity; // result of e.g. -1/0
1108 | NaN; // result of e.g. 0/0
1109 | undefined; // never use this yourself. This is the default value for "not assigned"
1110 | null; // use this instead. This is the programmer setting a var to "not assigned"
1111 | 
1112 | // There's also a boolean type.
1113 | true;
1114 | false;
1115 | 
1116 | // Strings are created with single quotes (') or double quotes (").
1117 | 'abc';
1118 | "Hello, world";
1119 | 
1120 | // You can access characters in a string with `charAt`
1121 | "This is a string".charAt(0);  // = 'T'
1122 | 
1123 | // ...or use `substring` to get larger pieces.
1124 | "Hello world".substring(0, 5); // = "Hello"
1125 | "Hello world".slice(0, 5); // does the same thing
1126 | "Hello world".substr(0, 5); // yet again
1127 | 
1128 | // `length` is a property, so don't use ().
1129 | "Hello".length; // = 5
1130 | 
1131 | // Searching strings
1132 | "Mary had a little lamb".search("had"); // returns 5
1133 | "Mary had a little lamb".indexOf("zebra"); // returns -1
1134 | 
1135 | // String to a character array
1136 | "one two three four".split(" "); // ['one', 'two', 'three', 'four']
1137 | 
1138 | // String replace
1139 | "happy birthday henry!".replace("h", "H"); // "Happy birthday Henry!"
1140 | 
1141 | // ES6 also introduces Symbol as a new primitive type
1142 | // But I'll add that on here once I actually figure out what it is
1143 | 

1144 |

1145 |

ii. Operators aka weirdly written functions

1146 |
// Operators have both a precedence (order of importance, like * before +) 
1147 | // and an associativity (order of evaluation, like left-to-right)
1148 | // A table of operators can be found here 
1149 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence)
1150 | 
1151 | // Negation uses the ! symbol
1152 | !true; // = false
1153 | !false; // = true
1154 | 
1155 | // There's shorthand operators for performing math operations on variables:
1156 | someVar += 5; // equivalent to someVar = someVar + 5;
1157 | someVar *= 10; // someVar = someVar * 10;
1158 | 
1159 | // and an even-shorter-hand  operators for adding or subtracting 1
1160 | someVar++; 
1161 | someVar--; 
1162 | 
1163 | // Strings are concatenated with +
1164 | "Hello " + "world!"; // = "Hello world!"
1165 | 
1166 | // Comparison Operators
1167 | 1 < 10; // = true
1168 | 1 > 10; // = false
1169 | 2 <= 2; // = true
1170 | 2 >= 2; // = true
1171 | 
1172 | // and are compared with < and >
1173 | "a" < "b"; // = true
1174 | 
1175 | // Strict Equality is ===
1176 | // Strict meaning both type AND value are the same
1177 | 1 === 1; // = true
1178 | 2 === 1; // = false
1179 | 
1180 | // Strict Inequality is !==
1181 | 1 !== 1; // = false
1182 | 2 !== 1; // = true
1183 | 
1184 | // == allows for type coercion (conversion) and only checks if the values are equal after coercion
1185 | "5" == 5; // = true
1186 | null == undefined; // = true
1187 | 
1188 | // ...which can result in some weird behaviour...so use === whenever possible
1189 | 13 + !0; // 14
1190 | "13" + !0; // '13true'
1191 | 
1192 | // false, null, undefined, NaN, 0 and "" are falsy; everything else is truthy.
1193 | // Note that 0 is falsy and "0" is truthy, even though 0 == "0".
1194 | 
1195 | // We can use this to our advantage when checking for existence
1196 | if (x) { //doSomething };
1197 | 
1198 | // Or to set default values
1199 | x = x || "default" 
1200 | // if x exists, do nothing and short-circuit, else set x to a default
1201 | 
1202 | // but a problem arises if x = 0. It exists, but will coerce to false
1203 | // be wary of this
1204 | 
1205 | // figuring out types of literals and vars
1206 | typeof "Hello"; // = "string"
1207 | typeof 42; // = "number"
1208 | typeof undefined // = "undefined"
1209 | typeof null // = 'object' THIS IS A JS BUG!
1210 | 
1211 | // figuring out if an object is an instance of another object
1212 | // checks all the way down the prototype chain
1213 | var x = {}
1214 | x instanceof Object // = true
1215 | x instanceof Function // = false
1216 | 
1217 | 
1218 | 1219 |

1220 |

2. More Basic Syntax

1221 |

1222 |

i. Variables

1223 |
// Variables are declared with the `var` keyword. JavaScript is dynamically
1224 | // typed, so you don't need to specify type. Assignment uses a single `=`
1225 | // character.
1226 | var someVar = 5;
1227 | 
1228 | // if you leave the var keyword off, you won't get an error...
1229 | someOtherVar = 10;
1230 | 
1231 | // ...but your variable will be created in the global scope, not in the scope
1232 | // you defined it in.
1233 | 
1234 | // Variables declared without being assigned to are set to undefined.
1235 | var someThirdVar; // = undefined
1236 | 
1237 | 1238 |

1239 |

ii. Arrays

1240 |
// Arrays are ordered lists of values, of any type.
1241 | var myArray = ["Hello", 45, true];
1242 | 
1243 | // Their members can be accessed using the square-brackets subscript syntax.
1244 | // Array indices start at zero.
1245 | myArray[1]; // = 45
1246 | 
1247 | // Arrays are mutable and of variable length (dynamically sized arrays)
1248 | myArray.push("World"); // adds to the end
1249 | myArray.length; // = 4
1250 | 
1251 | // Add/Modify at specific index
1252 | myArray[3] = "Hello";
1253 | 
1254 | 1255 |

1256 |

iii. Logic and Control Structures

1257 |
// The `if` structure works as you'd expect.
1258 | var count = 1;
1259 | if (count === 3){
1260 |     // evaluated if count is 3
1261 | } else if (count === 4){
1262 |     // evaluated if count is 4
1263 | } else {
1264 |     // evaluated if it's not either 3 or 4
1265 | }
1266 | 
1267 | // As does `while`.
1268 | while (true){
1269 |     // An infinite loop!
1270 | }
1271 | 
1272 | // Do-while loops are like while loops, except they always run at least once.
1273 | var input;
1274 | do {
1275 |     input = getInput();
1276 | } while (!isValid(input))
1277 | 
1278 | // The `for` loop is the same as C++ and Java:
1279 | // initialisation; continue condition; iteration.
1280 | for (var i = 0; i < 5; i++){
1281 |     // will run 5 times
1282 | }
1283 | 
1284 | // && is logical AND, || is logical OR
1285 | if (house.size === "big" && house.colour === "blue"){
1286 |     house.contains = "bear";
1287 | }
1288 | if (colour === "red" || colour === "blue"){
1289 |     // colour is either red or blue
1290 | }
1291 | 
1292 | // The `switch` statement checks for equality with `===`.
1293 | // use 'break' after each case 
1294 | // or the cases after the correct one will be executed too. 
1295 | grade = 'B';
1296 | switch (grade) {
1297 |   case 'A':
1298 |     console.log("Great job");
1299 |     break;
1300 |   case 'B':
1301 |     console.log("OK job");
1302 |     break;
1303 |   case 'C':
1304 |     console.log("You can do better");
1305 |     break;
1306 |   default:
1307 |     console.log("Oy vey");
1308 |     break;
1309 | }
1310 | 
1311 | 
1312 | 1313 |

1314 |

3. Objects and Functions

1315 |

1316 |

i. Objects

1317 |

An object is simply an unordered collection of key-value pairs.
1318 |

// They can be made literally:
1319 | var myObj = {key1: "Hello", key2: "World"};
1320 | // or using the Object constructor:
1321 | var myObj = new Object();
1322 | 
1323 | // Keys are strings, but quotes aren't required if they're a valid
1324 | // JavaScript identifier. Values can be any type including other objects.
1325 | var myObj = {myKey: "myValue", "my other key": 4};
1326 | 
1327 | // Objects can even contain functions (called methods)
1328 | // When functions attached to an object are called, they can access the object
1329 | // they're attached to using the `this` keyword.
1330 | var myObj = { 
1331 |   name: "Destiny's Child",
1332 |   sayMyName: function() {
1333 |     console.log(this.name);
1334 |   }
1335 | }
1336 | myObj.sayMyName(); // outputs "Destiny's Child"
1337 | 
1338 | // Object attributes can also be accessed using the subscript syntax,
1339 | myObj["my other key"]; // = 4
1340 | 
1341 | // ... or using the dot syntax, provided the key is a valid identifier.
1342 | myObj.myKey; // = "myValue"
1343 | 
1344 | // Objects are mutable; values can be changed and new keys added.
1345 | myObj.myThirdKey = true;
1346 | 
1347 | // If you try to access a value that's not yet set, you'll get undefined.
1348 | myObj.myFourthKey; // = undefined
1349 | 
1350 | // iterating through objects
1351 | for(var property in myObj) { // do something }
1352 | 
1353 | // JSON (JavaScript Object Notation) is just a special case of Object literal notation
1354 | // where the keys are strings wrapped in quotes
1355 | var json_stuff = {
1356 |   "firstName": "John",
1357 |   "lastName": "Doe",
1358 |   "Age": 25
1359 | }
1360 | 
1361 | // JS Object => JSON
1362 | JSON.stringify(myObj);
1363 | 
1364 | // JSON => JS Object
1365 | JSON.parse(json_stuff);
1366 | 

1367 |

1368 |

ii. Functions

1369 |

Functions are special kinds of objects! Functions can have their own methods and properties just like other objects, but they’re rarely used in that way.

1370 |

Remember, functions in JS are first-class. Meaning they can be assigned and passed just like any other variable can.

1371 |

Functions are special in that they have an optional name property and a code property (which is the body of the function that actually does stuff). The function’s code is executed by the invocation operator ().

1372 |

// JavaScript functions are declared with the `function` keyword.
1373 | // This is a function statement
1374 | function myFunction(thing){
1375 |     return thing.toUpperCase();
1376 | }
1377 | 
1378 | // This is a function expression
1379 | var makeUpperCase = function() {
1380 |     return think.toUpperCase();
1381 | }
1382 | 
1383 | // Note that the value to be returned must start on the same line as the
1384 | // `return` keyword, otherwise you'll always return `undefined` due to
1385 | // automatic semicolon insertion. Watch out for this when using Allman style.
1386 | function myFunction()
1387 | {
1388 |     return // <- semicolon automatically inserted here
1389 |     {
1390 |         thisIsAn: 'object literal'
1391 |     }
1392 | }
1393 | myFunction(); // = undefined
1394 | 
1395 | // JavaScript functions are first class objects, so they can be reassigned to
1396 | // different variable names and passed to other functions as arguments - for
1397 | // example, when supplying an event handler:
1398 | function myFunction(){
1399 |     // this code will be called in 5 seconds' time
1400 | }
1401 | setTimeout(myFunction, 5000);
1402 | // Note: setTimeout isn't part of the JS language, but is provided by browsers
1403 | // and Node.js.
1404 | 

1405 | Function objects don’t even have to be declared with a name - you can write an anonymous function definition directly into the arguments of another.

1406 |
setTimeout(function(){
1407 |     console.log("It's been 5 seconds!");
1408 |     // this code will be called in 5 seconds time
1409 | }, 5000);
1410 | 
1411 | 1412 |

This has led to a common pattern of “immediately-executing anonymous functions”, which prevent temporary variables from leaking into the global scope. The function expression is wrapped in parenthesis and then is invoked using ()

1413 |
(function(){
1414 |     var temporary = 5;
1415 | })();
1416 | temporary; // raises ReferenceError
1417 | permanent; // = 10
1418 | 
1419 | 1420 |

An important distinction: primitives Pass by Value while objects Pass by Reference
1421 |

// Primitives are passed by value
1422 | var i = 2;
1423 | function double(i){  i*2;  } // another i is created with the same value in a different execution context
1424 | double(i);
1425 | console.log(i); // still 2 
1426 | 
1427 | // Objects (including functions) are passed by reference
1428 | var obj = { hero: "Superman" };
1429 | function bestSuperhero(obj){
1430 |   obj.hero = "Batman";
1431 | }
1432 | bestSuperhero(obj);
1433 | console.log(obj.hero); // = "Batman"
1434 | 

1435 | The this keyword within methods, always refers to the object that the method is tied to. However, if the method has an inner function, its this refers to the global object. Some regard this as a bug in JS, so the good practice is to create and use a variable called self.

1436 |
var c = {
1437 |     name: 'The c object',
1438 |     log: function() {
1439 |         var self = this;
1440 | 
1441 |         self.name = 'Updated c object';
1442 |         console.log(self);
1443 | 
1444 |         var setname = function(newname) {
1445 |             self.name = newname;   
1446 |         }
1447 |         setname('Updated again! The c object');
1448 |         console.log(self);
1449 |     }
1450 | }
1451 | c.log(); // outputs "Updated again! The c object"
1452 | 
1453 | 1454 |

1455 |

iii. Bind, Call and Apply

1456 |

Functions that aren’t tied to objects can use this and still be useful. Consider this example.
1457 |

var cow = { says: "moo" };
1458 | var dog = { says: "woof" };
1459 | var pig = { says: "oink" };
1460 | 
1461 | function speak(times) { 
1462 |   for(i = 0; i < times; i++) {
1463 |     console.log(this.says);
1464 |   }
1465 | }
1466 | speak(4); // error because this is the global object which doesn't have a 'says' property
1467 | 

1468 | To use speak, we need to use the .bind, .call or .apply methods, which are available to all functions. The first parameter of these functions is the object which becomes this within the function.

1469 |

// bind creates a copy of the function it's being called on
1470 | var cowSpeak = speak.bind(cow);
1471 | cowSpeak(4); // outputs "moo moo"
1472 | 
1473 | // call directly executes the function with the first parameter being 'this'
1474 | // and all the other parameters being the function's parameters
1475 | speak.call(dog, 3); // outputs "woof woof woof"
1476 | 
1477 | // apply directly executes the function with the first parameter being 'this'
1478 | // and all the other function parameters being passed in as an array
1479 | speak.apply(pig, [1]); // outputs "oink"
1480 | 

1481 | The call and apply methods allow us to do something called Function Borrowing.
1482 |
var darthVader = { 
1483 |   son: "Luke",
1484 |   saying: function(){
1485 |     console.log(this.son + ", I am your father");
1486 |   }
1487 | };
1488 | var luke = { son: "Ben" };
1489 | 
1490 | darthVader.saying.call(luke);
1491 | // borrowing Darth Vader's saying
1492 | // outputs "Ben, I am your father"
1493 | 

1494 | The bind method allows us to do Function Currying.
1495 |
// Creating a copy of a function with preset parameters
1496 | function multiply(a,b){ return a*b }
1497 | 
1498 | // first parameter can be 'this' or null or anything--doesn't matter since 'this' is not used
1499 | // the second parameter (a) is permanently set to 2
1500 | var double = multiply.bind(this, 2);
1501 | double(16); // outputs 32
1502 | 
1503 | 

1504 |

1505 |

4. Function Execution, Variable Scope, Closures & Callbacks

1506 |

A few important concepts:
1507 | - Global means not inside a function. The global object is ‘window’ in browsers.
1508 | - The Lexical Environment is where something sits physically in the code
1509 | - ‘this’ is a reference to the object that the currently running method is tied to (by default it’s tied to the global object)
1510 | - The Execution Context consists of the environment (state of variables) of the function currently being evaluated. It also includes ‘this’ and a reference to the outer environment (aka what object is sitting outside this function lexically)
1511 | - The Execution Stack or Call Stack is the “stack” of execution contexts with the global execution context being the bottommost. When the program flow enters a function, a new execution context is popped onto the call stack, and when the function returns, it is popped off.

1512 |

1513 |

i. Hoisting

1514 |

Before actually executing any of the code, the JS engine first looks at all the variable declarations and function statements and sets aside some memory space for them effectively moving them to the top of the code. This is known as hoisting.
1515 |

// Variable example
1516 | 
1517 | function a(){
1518 |   console.log(x);
1519 |   var x = 2;
1520 |   console.log(x);
1521 | }
1522 | a(); // outputs 'undefined' then 2
1523 | 
1524 | // Function a is essentially equivalent to:
1525 | function a(){
1526 |   var x; // the var declaration is hoisted up to the top and is set to undefined
1527 |   console.log(x); // outputs undefined
1528 |   x = 2; // the variable assignment stays. It is NOT hoisted.
1529 |   console.log(x); // outputs 2
1530 | }
1531 | 
1532 | // Function example
1533 | 
1534 | a(); // will run properly
1535 | b(); // will fail with TypeError because b isn't assigned until line 4
1536 | function a() { }
1537 | var b = function() { }
1538 | 
1539 | The above is equivalent to:
1540 | function a() {} // the function statement is hoisted
1541 | var b;
1542 | a();
1543 | b(); // = undefined(); invoking undefined raises an error
1544 | b = function() {}
1545 | 

1546 |

JS is always synchronous (executing code 1 line at a time and in-order) and single-threaded (only 1 command at a time). However, jQuery, event handlers and AJAX calls make use of callbacks which appear to run asynchronously. AJAX calls are delegated off to a different part of the browser (outside the JS engine) which is why they are run asynchronously. When the call returns, or if there’s a user click, then these events fill up the Event Queue. The JS Engine only handles the Event Queue when the Execution Stack is empty.

1547 |

1548 |

ii. Scope Chain

1549 |

To find a variable when functions are running, JS looks further than just the variable environment of the currently executing context, it also looks at the outer environment (the environment to which this function is lexically attached). This process continues looking all the way down to the global environment in a process known as the __scope chain_.

1550 |
function b() {
1551 |     console.log(myVar);
1552 | }
1553 | 
1554 | function a() {
1555 |     var myVar = 2;
1556 |     b();
1557 | }
1558 | 
1559 | var myVar = 1;
1560 | a();
1561 | 
1562 | // function b does not have a myVar variable so it looks to its outer environment
1563 | // here, b is lexically attached to the global object, and myVar exists in the global environment
1564 | // therefore, it logs '1'
1565 | 
1566 | 
1567 | // JavaScript has function scope; functions get their own scope but other blocks
1568 | // do not.
1569 | if (true){
1570 |     var i = 5;
1571 | }
1572 | i; // = 5 - not undefined as you'd expect in a block-scoped language
1573 | 
1574 | 1575 |

1576 |

iii. Closures

1577 |

One of JS’s most powerful features is closures. Whenever a function is nested within another function, the inner function has access to all the outer function’s variables even after the outer function exits.
1578 | After the outer function exits, it is popped off the Execution Stack, however if any of its variables are referenced in the inner function, then those variables are “closed into” the inner function’s Execution Context and are accessible by the inner function.

1579 |
// Example 1
1580 | 
1581 | function sayHelloInFiveSeconds(name){
1582 |     var prompt = "Hello, " + name + "!";
1583 |     // Inner functions are put in the local scope by default, as if they were
1584 |     // declared with `var`.
1585 |     function inner(){
1586 |         alert(prompt);
1587 |     }
1588 |     setTimeout(inner, 5000);
1589 |     // setTimeout is asynchronous, so the sayHelloInFiveSeconds function will
1590 |     // exit immediately, and setTimeout will call inner afterwards. However,
1591 |     // because inner is "closed over" sayHelloInFiveSeconds, inner still has
1592 |     // access to the `prompt` variable when it is finally called.
1593 | }
1594 | sayHelloInFiveSeconds("Adam"); // will open a popup with "Hello, Adam!" in 5s
1595 | 
1596 | 
1597 | // Example 2
1598 | 
1599 | function buildFunctions() {
1600 |     var arr = [];    
1601 |     for (var i = 0; i < 3; i++) {
1602 |         arr.push(
1603 |             function() {
1604 |                 console.log(i);   
1605 |             }
1606 |         )
1607 |     }
1608 |     return arr;
1609 | }
1610 | 
1611 | var fs = buildFunctions();
1612 | fs[0]();
1613 | fs[1]();
1614 | fs[2]();
1615 | // all 3 of these will log '3' because after buildFunctions finishes, i = 3
1616 | // when fs[0..2] are invoked, they look for the value of i and they all see 3
1617 | 
1618 | // Avoid creating functions in loops. It will lead to bad behaviour.
1619 | 
1620 | 1621 |

1622 |

iv. Callbacks

1623 |

Callbacks are simply functions passed as arguments to other functions to be run when the other functions are finished.

1624 |
function alertWhenDone(callback){
1625 |   // do some work
1626 |   callback(); // invoke the callback right before exiting
1627 | }
1628 | 
1629 | alertWhenDone(function(){
1630 |   alert("I am done!"); 
1631 | });
1632 | 
1633 | // Callback making use of the JavaScript Timer
1634 | setTimeout(function(){
1635 |   alert("3 seconds have passed.");
1636 | }, 3000);
1637 | 
1638 | 1639 |

1640 |

5. Object-Oriented JS and Prototypal Inheritance

1641 |

1642 |

i. Function Constructors

1643 |

When you call a function with the new keyword, a new object is created in memory, and is made available to the function via the this keyword. Functions designed to be called like that are called constructors.
1644 |

var MyConstructor = function(){
1645 |     // public variables are declared using this
1646 |     this.myNumber = 5;
1647 |     // private variables are declared using var
1648 |     var secretNum = 4;
1649 |     // public getter for the private variable
1650 |     this.getSecret = function(){ return secretNum };
1651 | }
1652 | myNewObj = new MyConstructor(); // = {myNumber: 5, secretNum: 4}
1653 | myNewObj.myNumber; // = 5
1654 | myNewObj.secretNum; // undefined
1655 | myNewObj.getSecret(); // = 4
1656 | 
1657 | 

1658 |

1659 |

ii. Prototypes

1660 |

Every JavaScript object has a ‘prototype’ property, which is simply a reference to another object. When you go to access a property that doesn’t exist on the actual object, the interpreter will look at its prototype. If it doesn’t exist on the prototype, it’ll look at the prototype’s prototype. It will keep looking down this prototype chain until it hits the base object Object, which doesn’t have a prototype.
1661 |

// Some JS implementations let you access an object's prototype on the magic
1662 | // property `__proto__`. While this is useful for explaining prototypes it's not
1663 | // part of the standard; we'll get to standard ways of using prototypes later.
1664 | var myObj = {
1665 |     myString: "Hello world!"
1666 | };
1667 | var myPrototype = {
1668 |     meaningOfLife: 42,
1669 |     myFunc: function(){
1670 |         return this.myString.toLowerCase()
1671 |     }
1672 | };
1673 | 
1674 | myObj.__proto__ = myPrototype;
1675 | myObj.meaningOfLife; // = 42
1676 | 
1677 | // This works for functions, too.
1678 | myObj.myFunc(); // = "hello world!"
1679 | 
1680 | // Of course, if your property isn't on your prototype, the prototype's
1681 | // prototype is searched, and so on.
1682 | myPrototype.__proto__ = {
1683 |     myBoolean: true
1684 | };
1685 | myObj.myBoolean; // = true
1686 | 
1687 | // There's no copying involved here; each object stores a reference to its
1688 | // prototype. This means we can alter the prototype and our changes will be
1689 | // reflected everywhere.
1690 | myPrototype.meaningOfLife = 43;
1691 | myObj.meaningOfLife; // = 43
1692 | 

1693 |

1694 |

iii. Prototypal Inheritance aka setting prototypes of new objects

1695 |

Accessing __proto__ is non-standard, and there are no standard ways to change the prototype of an existing object. However, there are two ways to create a new object with a given prototype.
1696 |

// The first is Object.create, which is a recent addition to JS, and therefore
1697 | // not available in all implementations yet.
1698 | var myObj = Object.create(myPrototype);
1699 | myObj.meaningOfLife; // = 43
1700 | 

1701 | Every JS function also has a property called ‘prototype’. When used as a normal function, the ‘prototype’ property is not used. Only when functions are used as constructors with the new keyword, the ‘prototype’ sets the prototype of the object being created.

1702 |
// Constructors have a property called prototype. This is *not* the prototype of
1703 | // the constructor function itself; instead, it's the prototype that new objects
1704 | // are given when they're created with that constructor and the new keyword.
1705 | MyConstructor.prototype = {
1706 |     myNumber: 5,
1707 |     getMyNumber: function(){
1708 |         return this.myNumber;
1709 |     }
1710 | };
1711 | var myNewObj2 = new MyConstructor();
1712 | myNewObj2.getMyNumber(); // = 5
1713 | myNewObj2.myNumber = 6
1714 | myNewObj2.getMyNumber(); // = 6
1715 | 
1716 | 1717 |

1718 |

iv. Built-In Constructors

1719 |

// Built-in types like strings and numbers also have constructors that create
1720 | // equivalent wrapper objects.
1721 | var myNumber = 12;
1722 | var myNumberObj = new Number(12);
1723 | myNumber == myNumberObj; // = true
1724 | 
1725 | // Except, they aren't exactly equivalent.
1726 | typeof myNumber; // = 'number'
1727 | typeof myNumberObj; // = 'object'
1728 | myNumber === myNumberObj; // = false
1729 | if (0){
1730 |     // This code won't execute, because 0 is falsy.
1731 | }
1732 | if (Number(0)){
1733 |     // This code *will* execute, because Number(0) is truthy.
1734 | }
1735 | 
1736 | // However, the wrapper objects and the regular builtins share a prototype, so
1737 | // you can actually add functionality to a string, for instance.
1738 | String.prototype.firstCharacter = function(){
1739 |     return this.charAt(0);
1740 | }
1741 | "abc".firstCharacter(); // = "a"
1742 | 

1743 | Polyfilling takes advantage of the fact that we can modify the built-in prototypes to implement newer features of JavaScript in an older subset of JavaScript, so that they can be used in older environments such as outdated browsers.
1744 |
// For instance, Object.create isn't yet available in all
1745 | // implementations, but we can still use it with this polyfill:
1746 | if (Object.create === undefined){ // don't overwrite it if it exists
1747 |     Object.create = function(proto){
1748 |         // make a temporary constructor with the right prototype
1749 |         var Constructor = function(){};
1750 |         Constructor.prototype = proto;
1751 |         // then use it to create a new, appropriately-prototyped object
1752 |         return new Constructor();
1753 |     }
1754 | }
1755 | 
1756 | 

1757 |

1758 |

6. Bugs and Error Handling

1759 |
// You can opt in to tell the JS engine to be very strict in its interpretation
1760 | // It must go at the top of the file to interpret the whole file in strict mode
1761 | // Or at the top of a function, to make just that function strict
1762 | "use strict"
1763 | 
1764 | 1765 |

1766 |

7. New ES6 stuff

1767 |

Arrows

1768 |

Arrows are a function shorthands for anonymous functions used with the => syntax. They pass the outside lexical scope (ie. this) to the function.
1769 |

// Expression bodies
1770 | var odds = evens.map(v => v + 1);
1771 | var nums = evens.map((v, i) => v + i);
1772 | 
1773 | // Statement bodies
1774 | nums.forEach(v => {
1775 |   if (v % 5 === 0)
1776 |     fives.push(v);
1777 | });
1778 | 
1779 | // Lexical this
1780 | var bob = {
1781 |   _name: "Bob",
1782 |   _friends: [],
1783 |   printFriends() {
1784 |     this._friends.forEach(f =>
1785 |       console.log(this._name + " knows " + f));
1786 |   }
1787 | }
1788 | 

1789 |

Classes

1790 |

Object-oriented syntactic sugar for the prototypal inheritance pattern.

1791 |
class SkinnedMesh extends THREE.Mesh {
1792 |   constructor(geometry, materials) {
1793 |     super(geometry, materials);
1794 | 
1795 |     this.idMatrix = SkinnedMesh.defaultMatrix();
1796 |     this.bones = [];
1797 |     this.boneMatrices = [];
1798 |     //...
1799 |   }
1800 |   update(camera) {
1801 |     //...
1802 |     super.update();
1803 |   }
1804 |   get boneCount() {
1805 |     return this.bones.length;
1806 |   }
1807 |   set matrixType(matrixType) {
1808 |     this.idMatrix = SkinnedMesh[matrixType]();
1809 |   }
1810 |   static defaultMatrix() {
1811 |     return new THREE.Matrix4();
1812 |   }
1813 | }
1814 | 
1815 | 1816 |

String Interpolation

1817 |
var name = "Bob", time = "today";
1818 | `Hello ${name}, how are you ${time}?`
1819 | 
1820 | 1821 |

let and const

1822 |

let is like var except it is block-scoped. Variables declared with const can only be assigned once.
1823 |

if (1 < 2) {
1824 |   let i = 4;
1825 |   const name = 'Jon Snow'
1826 | }
1827 | var i = 5; // error, i is already defined
1828 | name = 'Samwell Tarly' // error, const can only be defined once
1829 | 

1830 |

Generator

1831 |

Functions that can be paused using the yield keyword and restarted from the outside. yield _____ is called a “yield expression” which gets evaluated with whatever value we send in when we restart the generator. yield is making a request for a value.

1832 |

function* fibonacci() {
1833 |   let a = 0, b = 1;
1834 | 
1835 |   while(true) {
1836 |     yield a;
1837 |     [a, b] = [b, a + b];
1838 |   }
1839 | }
1840 | 
1841 | // Enumerates the Fibonacci numbers
1842 | for(let value of fibonacci()) {
1843 |   console.log(value);
1844 | }
1845 | 

1846 | Generators are useful because they return (i.e. create) iterators. In turn, an iterator, an object with a next method, actually executes the body of generators. The next method, when repeatedly called, partially executes the corresponding generator, gradually advancing through the body until a yield keyword is hit.

1847 |

function* argumentsGenerator() {
1848 |   for (let i = 0; i < arguments.length; i += 1) {
1849 |     yield arguments[i];
1850 |   }
1851 | }
1852 | 
1853 | var argumentsIterator = argumentsGenerator('a', 'b', 'c');
1854 | 
1855 | // Prints "a b c"
1856 | console.log(
1857 |     argumentsIterator.next().value,
1858 |     argumentsIterator.next().value,
1859 |     argumentsIterator.next().value
1860 | );
1861 | 
1862 | // ES6 has syntactic sugar for iteration.
1863 | // Prints "a", "b", "c"
1864 | for(let value of argumentsIterator) {
1865 |   console.log(value);
1866 | }
1867 | 

1868 | The next method of an iterator returns an object with a value property and a done property, as long as the body of the corresponding generator has not returned. The value property refers the value yielded or returned. The done property is false up until the generator body returns, at which point it is true. If the next method is called after done is true, an error is thrown.

1869 |

Maps, Sets, WeakMap, WeakSet

1870 |

A Map is an object for which the keys can be any arbitrary object. A Set is a data structure which contains a finite set of elements, each occurring only once. WeakMaps and WeakSets provide leak-free object-key’d side tables. The JavaScript virtual machine periodically frees memory allocated to objects no longer in scope. An object is no longer in scope if there is no chain of references from the current scope leading to it.
1871 |

// Sets
1872 | var s = new Set();
1873 | s.add("hello").add("goodbye").add("hello");
1874 | s.size === 2;
1875 | s.has("hello") === true;
1876 | 
1877 | // Maps
1878 | var m = new Map();
1879 | m.set("hello", 42);
1880 | m.set(s, 34);
1881 | m.get(s) == 34;
1882 | 
1883 | // Weak Maps
1884 | var wm = new WeakMap();
1885 | wm.set(s, { extra: 42 });
1886 | wm.size === undefined
1887 | 
1888 | // Weak Sets
1889 | var ws = new WeakSet();
1890 | ws.add({ data: 42 });
1891 | // Because the added object has no other references, it will not be held in the set
1892 | 

1893 |

Promises

1894 |

Promises are a library for asynchronous programming. Promises are a first class representation of a value that may be made available in the future. A Promise is in one of these states:
1895 | - pending: initial state, not fulfilled or rejected.
1896 | - fulfilled: successful operation
1897 | - rejected: failed operation.
1898 | - settled: the Promise is either fulfilled or rejected, but not pending.

1899 |
var someAsyncThing = function() {
1900 |   return new Promise(function(resolve, reject) {
1901 |     // this will throw, x does not exist
1902 |     resolve(x + 2);
1903 |   });
1904 | };
1905 | 
1906 | someAsyncThing().then(function() {
1907 |   console.log('everything is great');
1908 | }).catch(function(error) {
1909 |   console.log('oh no', error);
1910 | });
1911 | 
1912 | 1913 |

Modules

1914 |

// lib/math.js
1915 | export function sum(x, y) {
1916 |   return x + y;
1917 | }
1918 | export var pi = 3.141593;
1919 | 

1920 |
// app.js
1921 | import * as math from "lib/math";
1922 | alert("2π = " + math.sum(math.pi, math.pi));
1923 | 

1924 |
// otherApp.js
1925 | import {sum, pi} from "lib/math";
1926 | alert("2π = " + sum(pi, pi));
1927 | 

1928 |

TODO: Proxies, Symbol

-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # JavaScript Cheat Sheet 2 | 3 | Based off of [Learn X in Y Minutes](http://learnxinyminutes.com/docs/javascript/). 4 | 5 | JavaScript (JS) is a dynamic [interpreted language](#interpreted-lang) that powers the web. It is widely used in browsers (where JS scripts are interpreted by [JavaScript engines](#javascript-engine) like Chrome's [V8](https://developers.google.com/v8/)) and increasingly on servers (on a [Node.js](https://nodejs.org) runtime environment). 6 | 7 | JS is a [prototype-based](#prototype-based) scripting language with [first-class functions](#first-class-functions) and [dynamic typing](#dynamic-type). Because of its super flexibility, JS supports multiple styles of programming including [imperative](#imperative), [object-oriented](#object-oriented) and [functional](#functional). 8 | 9 | Here's what all those big words above mean: 10 | - __Interpreted Language__: a language (eg. JS, Python) in which most of its implementations execute instructions directly, without previously compiling a program into machine-language instructions like compiled languages do (eg. C++) 11 | - __JavaScript Engine__: a virtual machine that interprets and executes JS 12 | - __Prototype-Based__: unlike classical OOP with classes and objects, in JS, objects are cloned from other objects, and all objects have _prototypes_ (kinda like the template they inherit from) 13 | - __First-Class Functions__: JS supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures 14 | - __Dynamically Typed__: The "type" of all variables is only interpreted at run-time unlike statically typed languages where all variables have a type at compile-time 15 | - __Imperative Programming__: Statement based programming 16 | - __Object-Oriented Programming__: Object based programming 17 | - __Functional Programming__: Function based programming 18 | 19 | ## Quick Access Links 20 | 1. [Basics](#basics) 21 | 1. [Primitives](#primitives) 22 | 2. [Operators](#operators) 23 | 2. [More Basic Syntax](#syntax) 24 | 1. [Variables](#variables) 25 | 2. [Arrays](#arrays) 26 | 3. [Logic and Control Structures](#logic) 27 | 3. [Objects and Functions](#objects-and-functions) 28 | 1. [Objects](#objects) 29 | 2. [Functions](#functions) 30 | 3. [Bind, Call and Apply](#bind) 31 | 4. [Function Execution, Variable Scope, Closures & Callbacks](#execution) 32 | 1. [Hoisting](#hoisting) 33 | 2. [Scope Chain](#scope-chain) 34 | 3. [Closures](#closures) 35 | 4. [Callbacks](#callbacks) 36 | 5. [Object-Oriented JS and Prototypal Inheritance](#object-oriented) 37 | 1. [Constructors](#constructors) 38 | 2. [Prototypes](#prototypes) 39 | 3. [Prototypal Inheritance](#prototypal-inheritance) 40 | 4. [Built-In Constructors](#built-in) 41 | 6. [Bugs and Error Handling](#bugs) 42 | 7. [New ES6 stuff](#es6) 43 | 44 | TODO: Add 8. Useful Libraries (LoDash, jQuery), 9. Javascript in the browser, 10. NodeJS 45 | 46 | 47 | ## 1. Basics 48 | __Everything__ in JS is either an object or a primitive. 49 | ```javascript 50 | 51 | // This is a single line comment, 52 | /* and this is a 53 | multiline comment */ 54 | 55 | // Semicolons (;) to terminate lines are optional 56 | // However, the JS engine will (usually) automatically insert semicolons upon seeing '\n' 57 | // This can cause some weird behaviour so ALWAYS use semicolons 58 | doStuff(); 59 | ``` 60 | 61 | ### i. Primitives: Number, String, Boolean (and some special ones) 62 | 63 | ```javascript 64 | // JavaScript has one number type (which is a 64-bit IEEE 754 double). 65 | // Doubles have a 52-bit mantissa, which is enough to store integers 66 | // up to about 9✕10¹⁵ precisely. 67 | 3; // = 3 68 | 1.5; // = 1.5 69 | 70 | // Some basic arithmetic works as you'd expect. 71 | 1 + 1; // = 2 72 | 0.1 + 0.2; // = 0.30000000000000004 (funky floating point arithmetic--be careful!) 73 | 8 - 1; // = 7 74 | 10 * 2; // = 20 75 | 10 ** 2; // =100 (10 raised to the power 2) same as Math.pow(10, 2) 76 | 35 / 5; // = 7 77 | 78 | // Including uneven division. 79 | 5 / 2; // = 2.5 80 | 81 | // Bitwise operations also work; when you perform a bitwise operation your float 82 | // is converted to a signed int *up to* 32 bits. 83 | 1 << 2; // = 4 84 | 85 | // Precedence is enforced with parentheses. 86 | (1 + 3) * 2; // = 8 87 | 88 | // There are special primitive values: 89 | Infinity; // result of e.g. 1/0 90 | -Infinity; // result of e.g. -1/0 91 | NaN; // result of e.g. 0/0 92 | undefined; // never use this yourself. This is the default value for "not assigned" 93 | null; // use this instead. This is the programmer setting a var to "not assigned" 94 | 95 | // There's also a boolean type. 96 | true; 97 | false; 98 | 99 | // Strings are created with single quotes (') or double quotes ("). 100 | 'abc'; 101 | "Hello, world"; 102 | 103 | // You can access characters in a string with `charAt` 104 | "This is a string".charAt(0); // = 'T' 105 | 106 | // ...or use `substring` to get larger pieces. 107 | "Hello world".substring(0, 5); // = "Hello" 108 | "Hello world".slice(0, 5); // does the same thing 109 | "Hello world".substr(0, 5); // yet again 110 | 111 | // `length` is a property, so don't use (). 112 | "Hello".length; // = 5 113 | 114 | // Searching strings 115 | "Mary had a little lamb".search("had"); // returns 5 116 | "Mary had a little lamb".indexOf("zebra"); // returns -1 117 | "Mary had a little lamb".includes("had"); //returns true (ES7). includes() will return true if the parameter provided is in the string, and false otherwise. 118 | 119 | // String to a character array 120 | "one two three four".split(" "); // ['one', 'two', 'three', 'four'] 121 | 122 | // String replace 123 | "happy birthday henry!".replace("h", "H"); // "Happy birthday Henry!" 124 | 125 | // ES6 also introduces Symbol as a new primitive type 126 | // But I'll add that on here once I actually figure out what it is 127 | ``` 128 | 129 | ### ii. Operators aka weirdly written functions 130 | ```javascript 131 | // Operators have both a precedence (order of importance, like * before +) 132 | // and an associativity (order of evaluation, like left-to-right) 133 | // A table of operators can be found here 134 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence) 135 | 136 | // Negation uses the ! symbol 137 | !true; // = false 138 | !false; // = true 139 | 140 | // There's shorthand operators for performing math operations on variables: 141 | someVar += 5; // equivalent to someVar = someVar + 5; 142 | someVar *= 10; // someVar = someVar * 10; 143 | 144 | // and an even-shorter-hand operators for adding or subtracting 1 145 | someVar++; 146 | someVar--; 147 | 148 | // Strings are concatenated with + 149 | "Hello " + "world!"; // = "Hello world!" 150 | 151 | // Comparison Operators 152 | 1 < 10; // = true 153 | 1 > 10; // = false 154 | 2 <= 2; // = true 155 | 2 >= 2; // = true 156 | 157 | // and are compared with < and > 158 | "a" < "b"; // = true 159 | 160 | // Strict Equality is === 161 | // Strict meaning both type AND value are the same 162 | 1 === 1; // = true 163 | 2 === 1; // = false 164 | 165 | // Strict Inequality is !== 166 | 1 !== 1; // = false 167 | 2 !== 1; // = true 168 | 169 | // == allows for type coercion (conversion) and only checks if the values are equal after coercion 170 | "5" == 5; // = true 171 | null == undefined; // = true 172 | 173 | // ...which can result in some weird behaviour...so use === whenever possible 174 | 13 + !0; // 14 175 | "13" + !0; // '13true' 176 | 177 | // false, null, undefined, NaN, 0 and "" are falsy; everything else is truthy. 178 | // Note that 0 is falsy and "0" is truthy, even though 0 == "0". 179 | 180 | // We can use this to our advantage when checking for existence 181 | if (x) { //doSomething }; 182 | 183 | // Or to set default values 184 | x = x || "default" 185 | // if x exists, do nothing and short-circuit, else set x to a default 186 | 187 | // but a problem arises if x = 0. It exists, but will coerce to false 188 | // be wary of this 189 | 190 | // figuring out types of literals and vars 191 | typeof "Hello"; // = "string" 192 | typeof 42; // = "number" 193 | typeof undefined // = "undefined" 194 | typeof null // = 'object' THIS IS A JS BUG! 195 | 196 | // figuring out if an object is an instance of another object 197 | // checks all the way down the prototype chain 198 | var x = {} 199 | x instanceof Object // = true 200 | x instanceof Function // = false 201 | 202 | ``` 203 | 204 | 205 | ## 2. More Basic Syntax 206 | 207 | ### i. Variables 208 | ```javascript 209 | // Variables are declared with the `var` keyword. JavaScript is dynamically 210 | // typed, so you don't need to specify type. Assignment uses a single `=` 211 | // character. 212 | var someVar = 5; 213 | 214 | // if you leave the var keyword off, you won't get an error... 215 | someOtherVar = 10; 216 | 217 | // ...but your variable will be created in the global scope, not in the scope 218 | // you defined it in. 219 | 220 | // Variables declared without being assigned to are set to undefined. 221 | var someThirdVar; // = undefined 222 | ``` 223 | 224 | 225 | ### ii. Arrays 226 | ```javascript 227 | // Arrays are ordered lists of values, of any type. 228 | var myArray = ["Hello", 45, true]; 229 | 230 | // Their members can be accessed using the square-brackets subscript syntax. 231 | // Array indices start at zero. 232 | myArray[1]; // = 45 233 | 234 | // Arrays are mutable and of variable length (dynamically sized arrays) 235 | myArray.push("World"); // adds to the end 236 | myArray.length; // = 4 237 | 238 | // Add/Modify at specific index 239 | myArray[3] = "Hello"; 240 | 241 | //ES7 includes() can be used with arrays to check for the presence of a value. it is case sensitive 242 | let names = ["Samuel", "Hamilton", "Eric"]; 243 | names.includes("Samuel"); //true 244 | names.includes("samuel"); //false 245 | names.includes("John"); //false 246 | ``` 247 | 248 | 249 | ### iii. Logic and Control Structures 250 | ```javascript 251 | // The `if` structure works as you'd expect. 252 | var count = 1; 253 | if (count === 3){ 254 | // evaluated if count is 3 255 | } else if (count === 4){ 256 | // evaluated if count is 4 257 | } else { 258 | // evaluated if it's not either 3 or 4 259 | } 260 | 261 | // As does `while`. 262 | while (true){ 263 | // An infinite loop! 264 | } 265 | 266 | // Do-while loops are like while loops, except they always run at least once. 267 | var input; 268 | do { 269 | input = getInput(); 270 | } while (!isValid(input)) 271 | 272 | // The `for` loop is the same as C++ and Java: 273 | // initialisation; continue condition; iteration. 274 | for (var i = 0; i < 5; i++){ 275 | // will run 5 times 276 | } 277 | 278 | // && is logical AND, || is logical OR 279 | if (house.size === "big" && house.colour === "blue"){ 280 | house.contains = "bear"; 281 | } 282 | if (colour === "red" || colour === "blue"){ 283 | // colour is either red or blue 284 | } 285 | 286 | // The `switch` statement checks for equality with `===`. 287 | // use 'break' after each case 288 | // or the cases after the correct one will be executed too. 289 | grade = 'B'; 290 | switch (grade) { 291 | case 'A': 292 | console.log("Great job"); 293 | break; 294 | case 'B': 295 | console.log("OK job"); 296 | break; 297 | case 'C': 298 | console.log("You can do better"); 299 | break; 300 | default: 301 | console.log("Oy vey"); 302 | break; 303 | } 304 | 305 | ``` 306 | 307 | 308 | 309 | ## 3. Objects and Functions 310 | 311 | ### i. Objects 312 | An object is simply an unordered collection of key-value pairs. 313 | ```javascript 314 | // They can be made literally: 315 | var myObj = {key1: "Hello", key2: "World"}; 316 | // or using the Object constructor: 317 | var myObj = new Object(); 318 | 319 | // Keys are strings, but quotes aren't required if they're a valid 320 | // JavaScript identifier. Values can be any type including other objects. 321 | var myObj = {myKey: "myValue", "my other key": 4}; 322 | 323 | // Objects can even contain functions (called methods) 324 | // When functions attached to an object are called, they can access the object 325 | // they're attached to using the `this` keyword. 326 | var myObj = { 327 | name: "Destiny's Child", 328 | sayMyName: function() { 329 | console.log(this.name); 330 | } 331 | } 332 | myObj.sayMyName(); // outputs "Destiny's Child" 333 | 334 | // Object attributes can also be accessed using the subscript syntax, 335 | myObj["my other key"]; // = 4 336 | 337 | // ... or using the dot syntax, provided the key is a valid identifier. 338 | myObj.myKey; // = "myValue" 339 | 340 | // Objects are mutable; values can be changed and new keys added. 341 | myObj.myThirdKey = true; 342 | 343 | // If you try to access a value that's not yet set, you'll get undefined. 344 | myObj.myFourthKey; // = undefined 345 | 346 | // iterating through objects 347 | for(var property in myObj) { // do something } 348 | 349 | // JSON (JavaScript Object Notation) is just a special case of Object literal notation 350 | // where the keys are strings wrapped in quotes 351 | var json_stuff = { 352 | "firstName": "John", 353 | "lastName": "Doe", 354 | "Age": 25 355 | } 356 | 357 | // JS Object => JSON 358 | JSON.stringify(myObj); 359 | 360 | // JSON => JS Object 361 | JSON.parse(json_stuff); 362 | ``` 363 | 364 | 365 | ### ii. Functions 366 | Functions are special kinds of objects! Functions can have their own methods and properties just like other objects, but they're rarely used in that way. 367 | 368 | Remember, functions in JS are first-class. Meaning they can be assigned and passed just like any other variable can. 369 | 370 | Functions are special in that they have an optional name property and a code property (which is the body of the function that actually does stuff). The function's code is executed by the invocation operator `()`. 371 | 372 | ```javascript 373 | // JavaScript functions are declared with the `function` keyword. 374 | // This is a function statement 375 | function myFunction(thing){ 376 | return thing.toUpperCase(); 377 | } 378 | 379 | // This is a function expression 380 | var makeUpperCase = function() { 381 | return think.toUpperCase(); 382 | } 383 | 384 | // Note that the value to be returned must start on the same line as the 385 | // `return` keyword, otherwise you'll always return `undefined` due to 386 | // automatic semicolon insertion. Watch out for this when using Allman style. 387 | function myFunction() 388 | { 389 | return // <- semicolon automatically inserted here 390 | { 391 | thisIsAn: 'object literal' 392 | } 393 | } 394 | myFunction(); // = undefined 395 | 396 | // JavaScript functions are first class objects, so they can be reassigned to 397 | // different variable names and passed to other functions as arguments - for 398 | // example, when supplying an event handler: 399 | function myFunction(){ 400 | // this code will be called in 5 seconds' time 401 | } 402 | setTimeout(myFunction, 5000); 403 | // Note: setTimeout isn't part of the JS language, but is provided by browsers 404 | // and Node.js. 405 | ``` 406 | Function objects don't even have to be declared with a name - you can write an __anonymous function__ definition directly into the arguments of another. 407 | 408 | ``` javascript 409 | setTimeout(function(){ 410 | console.log("It's been 5 seconds!"); 411 | // this code will be called in 5 seconds time 412 | }, 5000); 413 | ``` 414 | 415 | This has led to a common pattern of __"immediately-executing anonymous functions"__, which prevent temporary variables from leaking into the global scope. The function expression is wrapped in parenthesis and then is invoked using `()` 416 | 417 | ``` javascript 418 | (function(){ 419 | var temporary = 5; 420 | })(); 421 | temporary; // raises ReferenceError 422 | permanent; // = 10 423 | ``` 424 | 425 | An important distinction: primitives __Pass by Value__ while objects __Pass by Reference__ 426 | ```javascript 427 | // Primitives are passed by value 428 | var i = 2; 429 | function double(i){ i*2; } // another i is created with the same value in a different execution context 430 | double(i); 431 | console.log(i); // still 2 432 | 433 | // Objects (including functions) are passed by reference 434 | var obj = { hero: "Superman" }; 435 | function bestSuperhero(obj){ 436 | obj.hero = "Batman"; 437 | } 438 | bestSuperhero(obj); 439 | console.log(obj.hero); // = "Batman" 440 | ``` 441 | The `this` keyword within methods, always refers to the object that the method is tied to. However, if the method has an inner function, its `this` refers to the global object. Some regard this as a bug in JS, so the good practice is to create and use a variable called `self`. 442 | 443 | ```javascript 444 | var c = { 445 | name: 'The c object', 446 | log: function() { 447 | var self = this; 448 | 449 | self.name = 'Updated c object'; 450 | console.log(self); 451 | 452 | var setname = function(newname) { 453 | self.name = newname; 454 | } 455 | setname('Updated again! The c object'); 456 | console.log(self); 457 | } 458 | } 459 | c.log(); // outputs "Updated again! The c object" 460 | ``` 461 | 462 | 463 | ### iii. Bind, Call and Apply 464 | Functions that aren't tied to objects can use `this` and still be useful. Consider this example. 465 | ```javascript 466 | var cow = { says: "moo" }; 467 | var dog = { says: "woof" }; 468 | var pig = { says: "oink" }; 469 | 470 | function speak(times) { 471 | for(i = 0; i < times; i++) { 472 | console.log(this.says); 473 | } 474 | } 475 | speak(4); // error because this is the global object which doesn't have a 'says' property 476 | ``` 477 | To use speak, we need to use the .bind, .call or .apply methods, which are available to __all__ functions. The first parameter of these functions is the object which becomes `this` within the function. 478 | 479 | ```javascript 480 | // bind creates a copy of the function it's being called on 481 | var cowSpeak = speak.bind(cow); 482 | cowSpeak(4); // outputs "moo moo" 483 | 484 | // call directly executes the function with the first parameter being 'this' 485 | // and all the other parameters being the function's parameters 486 | speak.call(dog, 3); // outputs "woof woof woof" 487 | 488 | // apply directly executes the function with the first parameter being 'this' 489 | // and all the other function parameters being passed in as an array 490 | speak.apply(pig, [1]); // outputs "oink" 491 | ``` 492 | The call and apply methods allow us to do something called __Function Borrowing__. 493 | ```javascript 494 | var darthVader = { 495 | son: "Luke", 496 | saying: function(){ 497 | console.log(this.son + ", I am your father"); 498 | } 499 | }; 500 | var luke = { son: "Ben" }; 501 | 502 | darthVader.saying.call(luke); 503 | // borrowing Darth Vader's saying 504 | // outputs "Ben, I am your father" 505 | ``` 506 | The bind method allows us to do __Function Currying__. 507 | ```javascript 508 | // Creating a copy of a function with preset parameters 509 | function multiply(a,b){ return a*b } 510 | 511 | // first parameter can be 'this' or null or anything--doesn't matter since 'this' is not used 512 | // the second parameter (a) is permanently set to 2 513 | var double = multiply.bind(this, 2); 514 | double(16); // outputs 32 515 | 516 | ``` 517 | 518 | 519 | ## 4. Function Execution, Variable Scope, Closures & Callbacks 520 | 521 | A few important concepts: 522 | - __Global__ means not inside a function. The global object is 'window' in browsers. 523 | - The __Lexical Environment__ is where something sits physically in the code 524 | - __'this'__ is a reference to the object that the currently running method is tied to (by default it's tied to the global object) 525 | - The __Execution Context__ consists of the environment (state of variables) of the function currently being evaluated. It also includes 'this' and a reference to the outer environment (aka what object is sitting outside this function _lexically_) 526 | - The __Execution Stack__ or __Call Stack__ is the "stack" of execution contexts with the global execution context being the bottommost. When the program flow enters a function, a new execution context is popped onto the call stack, and when the function returns, it is popped off. 527 | 528 | 529 | ### i. Hoisting 530 | Before actually executing any of the code, the JS engine first looks at all the variable declarations and function statements and sets aside some memory space for them effectively moving them to the top of the code. This is known as __hoisting__. 531 | ```javascript 532 | // Variable example 533 | 534 | function a(){ 535 | console.log(x); 536 | var x = 2; 537 | console.log(x); 538 | } 539 | a(); // outputs 'undefined' then 2 540 | 541 | // Function a is essentially equivalent to: 542 | function a(){ 543 | var x; // the var declaration is hoisted up to the top and is set to undefined 544 | console.log(x); // outputs undefined 545 | x = 2; // the variable assignment stays. It is NOT hoisted. 546 | console.log(x); // outputs 2 547 | } 548 | 549 | // Function example 550 | 551 | a(); // will run properly 552 | b(); // will fail with TypeError because b isn't assigned until line 4 553 | function a() { } 554 | var b = function() { } 555 | 556 | The above is equivalent to: 557 | function a() {} // the function statement is hoisted 558 | var b; 559 | a(); 560 | b(); // = undefined(); invoking undefined raises an error 561 | b = function() {} 562 | ``` 563 | 564 | JS is always synchronous (executing code 1 line at a time and in-order) and single-threaded (only 1 command at a time). However, jQuery, event handlers and AJAX calls make use of callbacks which appear to run asynchronously. AJAX calls are delegated off to a different part of the browser (outside the JS engine) which is why they are run asynchronously. When the call returns, or if there's a user click, then these events fill up the Event Queue. The JS Engine only handles the Event Queue when the Execution Stack is empty. 565 | 566 | 567 | ### ii. Scope Chain 568 | To find a variable when functions are running, JS looks further than just the variable environment of the currently executing context, it also looks at the outer environment (the environment to which this function is _lexically_ attached). This process continues looking all the way down to the global environment in a process known as the __scope chain_. 569 | 570 | ```javascript 571 | function b() { 572 | console.log(myVar); 573 | } 574 | 575 | function a() { 576 | var myVar = 2; 577 | b(); 578 | } 579 | 580 | var myVar = 1; 581 | a(); 582 | 583 | // function b does not have a myVar variable so it looks to its outer environment 584 | // here, b is lexically attached to the global object, and myVar exists in the global environment 585 | // therefore, it logs '1' 586 | 587 | 588 | // JavaScript has function scope; functions get their own scope but other blocks 589 | // do not. 590 | if (true){ 591 | var i = 5; 592 | } 593 | i; // = 5 - not undefined as you'd expect in a block-scoped language 594 | ``` 595 | 596 | 597 | ### iii. Closures 598 | One of JS's most powerful features is __closures__. Whenever a function is nested within another function, the inner function has access to all the outer function's variables even after the outer function exits. 599 | After the outer function exits, it is popped off the Execution Stack, however if any of its variables are referenced in the inner function, then those variables are "closed into" the inner function's Execution Context and are accessible by the inner function. 600 | 601 | ```javascript 602 | // Example 1 603 | 604 | function sayHelloInFiveSeconds(name){ 605 | var prompt = "Hello, " + name + "!"; 606 | // Inner functions are put in the local scope by default, as if they were 607 | // declared with `var`. 608 | function inner(){ 609 | alert(prompt); 610 | } 611 | setTimeout(inner, 5000); 612 | // setTimeout is asynchronous, so the sayHelloInFiveSeconds function will 613 | // exit immediately, and setTimeout will call inner afterwards. However, 614 | // because inner is "closed over" sayHelloInFiveSeconds, inner still has 615 | // access to the `prompt` variable when it is finally called. 616 | } 617 | sayHelloInFiveSeconds("Adam"); // will open a popup with "Hello, Adam!" in 5s 618 | 619 | 620 | // Example 2 621 | 622 | function buildFunctions() { 623 | var arr = []; 624 | for (var i = 0; i < 3; i++) { 625 | arr.push( 626 | function() { 627 | console.log(i); 628 | } 629 | ) 630 | } 631 | return arr; 632 | } 633 | 634 | var fs = buildFunctions(); 635 | fs[0](); 636 | fs[1](); 637 | fs[2](); 638 | // all 3 of these will log '3' because after buildFunctions finishes, i = 3 639 | // when fs[0..2] are invoked, they look for the value of i and they all see 3 640 | 641 | // Avoid creating functions in loops. It will lead to bad behaviour. 642 | ``` 643 | 644 | 645 | ### iv. Callbacks 646 | __Callbacks__ are simply functions passed as arguments to other functions to be run when the other functions are finished. 647 | 648 | ```javascript 649 | function alertWhenDone(callback){ 650 | // do some work 651 | callback(); // invoke the callback right before exiting 652 | } 653 | 654 | alertWhenDone(function(){ 655 | alert("I am done!"); 656 | }); 657 | 658 | // Callback making use of the JavaScript Timer 659 | setTimeout(function(){ 660 | alert("3 seconds have passed."); 661 | }, 3000); 662 | ``` 663 | 664 | 665 | ## 5. Object-Oriented JS and Prototypal Inheritance 666 | 667 | 668 | ### i. Function Constructors 669 | When you call a function with the `new` keyword, a new object is created in memory, and is made available to the function via the `this` keyword. Functions designed to be called like that are called constructors. 670 | ```javascript 671 | var MyConstructor = function(){ 672 | // public variables are declared using this 673 | this.myNumber = 5; 674 | // private variables are declared using var 675 | var secretNum = 4; 676 | // public getter for the private variable 677 | this.getSecret = function(){ return secretNum }; 678 | } 679 | myNewObj = new MyConstructor(); // = {myNumber: 5, secretNum: 4} 680 | myNewObj.myNumber; // = 5 681 | myNewObj.secretNum; // undefined 682 | myNewObj.getSecret(); // = 4 683 | 684 | ``` 685 | 686 | 687 | ### ii. Prototypes 688 | Every JavaScript object has a 'prototype' property, which is simply a reference to another object. When you go to access a property that doesn't exist on the actual object, the interpreter will look at its prototype. If it doesn't exist on the prototype, it'll look at the prototype's prototype. It will keep looking down this __prototype chain__ until it hits the base object Object, which doesn't have a prototype. 689 | ```javascript 690 | // Some JS implementations let you access an object's prototype on the magic 691 | // property `__proto__`. While this is useful for explaining prototypes it's not 692 | // part of the standard; we'll get to standard ways of using prototypes later. 693 | var myObj = { 694 | myString: "Hello world!" 695 | }; 696 | var myPrototype = { 697 | meaningOfLife: 42, 698 | myFunc: function(){ 699 | return this.myString.toLowerCase() 700 | } 701 | }; 702 | 703 | myObj.__proto__ = myPrototype; 704 | myObj.meaningOfLife; // = 42 705 | 706 | // This works for functions, too. 707 | myObj.myFunc(); // = "hello world!" 708 | 709 | // Of course, if your property isn't on your prototype, the prototype's 710 | // prototype is searched, and so on. 711 | myPrototype.__proto__ = { 712 | myBoolean: true 713 | }; 714 | myObj.myBoolean; // = true 715 | 716 | // There's no copying involved here; each object stores a reference to its 717 | // prototype. This means we can alter the prototype and our changes will be 718 | // reflected everywhere. 719 | myPrototype.meaningOfLife = 43; 720 | myObj.meaningOfLife; // = 43 721 | ``` 722 | 723 | 724 | ### iii. Prototypal Inheritance aka setting prototypes of new objects 725 | 726 | Accessing `__proto__` is non-standard, and there are no standard ways to change the prototype of an existing object. However, there are two ways to create a new object with a given prototype. 727 | ```javascript 728 | // The first is Object.create, which is a recent addition to JS, and therefore 729 | // not available in all implementations yet. 730 | var myObj = Object.create(myPrototype); 731 | myObj.meaningOfLife; // = 43 732 | ``` 733 | Every JS function also has a property called 'prototype'. When used as a normal function, the 'prototype' property is not used. Only when functions are used as constructors with the `new` keyword, the 'prototype' sets the prototype of the object being created. 734 | 735 | ```javascript 736 | // Constructors have a property called prototype. This is *not* the prototype of 737 | // the constructor function itself; instead, it's the prototype that new objects 738 | // are given when they're created with that constructor and the new keyword. 739 | MyConstructor.prototype = { 740 | myNumber: 5, 741 | getMyNumber: function(){ 742 | return this.myNumber; 743 | } 744 | }; 745 | var myNewObj2 = new MyConstructor(); 746 | myNewObj2.getMyNumber(); // = 5 747 | myNewObj2.myNumber = 6 748 | myNewObj2.getMyNumber(); // = 6 749 | ``` 750 | 751 | 752 | ### iv. Built-In Constructors 753 | ```javascript 754 | // Built-in types like strings and numbers also have constructors that create 755 | // equivalent wrapper objects. 756 | var myNumber = 12; 757 | var myNumberObj = new Number(12); 758 | myNumber == myNumberObj; // = true 759 | 760 | // Except, they aren't exactly equivalent. 761 | typeof myNumber; // = 'number' 762 | typeof myNumberObj; // = 'object' 763 | myNumber === myNumberObj; // = false 764 | if (0){ 765 | // This code won't execute, because 0 is falsy. 766 | } 767 | if (new Number(0)){ 768 | // This code will execute, because wrapped numbers are objects, and objects 769 | // are always truthy. 770 | } 771 | 772 | // However, the wrapper objects and the regular builtins share a prototype, so 773 | // you can actually add functionality to a string, for instance. 774 | String.prototype.firstCharacter = function(){ 775 | return this.charAt(0); 776 | } 777 | "abc".firstCharacter(); // = "a" 778 | ``` 779 | __Polyfilling__ takes advantage of the fact that we can modify the built-in prototypes to implement newer features of JavaScript in an older subset of JavaScript, so that they can be used in older environments such as outdated browsers. 780 | ```javascript 781 | // For instance, Object.create isn't yet available in all 782 | // implementations, but we can still use it with this polyfill: 783 | if (Object.create === undefined){ // don't overwrite it if it exists 784 | Object.create = function(proto){ 785 | // make a temporary constructor with the right prototype 786 | var Constructor = function(){}; 787 | Constructor.prototype = proto; 788 | // then use it to create a new, appropriately-prototyped object 789 | return new Constructor(); 790 | } 791 | } 792 | 793 | ``` 794 | 795 | 796 | ## 6. Bugs and Error Handling 797 | 798 | ```javascript 799 | // You can opt in to tell the JS engine to be very strict in its interpretation 800 | // It must go at the top of the file to interpret the whole file in strict mode 801 | // Or at the top of a function, to make just that function strict 802 | "use strict" 803 | ``` 804 | 805 | 806 | 807 | ## 7. New ES6 stuff 808 | 809 | ### Arrows 810 | Arrows are a function shorthands for anonymous functions used with the `=>` syntax. They pass the outside lexical scope (ie. `this`) to the function. 811 | ```javascript 812 | // Expression bodies 813 | var odds = evens.map(v => v + 1); 814 | var nums = evens.map((v, i) => v + i); 815 | 816 | // Statement bodies 817 | nums.forEach(v => { 818 | if (v % 5 === 0) 819 | fives.push(v); 820 | }); 821 | 822 | // Lexical this 823 | var bob = { 824 | _name: "Bob", 825 | _friends: [], 826 | printFriends() { 827 | this._friends.forEach(f => 828 | console.log(this._name + " knows " + f)); 829 | } 830 | } 831 | ``` 832 | 833 | ### Classes 834 | Object-oriented syntactic sugar for the prototypal inheritance pattern. 835 | 836 | ``` javascript 837 | class SkinnedMesh extends THREE.Mesh { 838 | constructor(geometry, materials) { 839 | super(geometry, materials); 840 | 841 | this.idMatrix = SkinnedMesh.defaultMatrix(); 842 | this.bones = []; 843 | this.boneMatrices = []; 844 | //... 845 | } 846 | update(camera) { 847 | //... 848 | super.update(); 849 | } 850 | get boneCount() { 851 | return this.bones.length; 852 | } 853 | set matrixType(matrixType) { 854 | this.idMatrix = SkinnedMesh[matrixType](); 855 | } 856 | static defaultMatrix() { 857 | return new THREE.Matrix4(); 858 | } 859 | } 860 | ``` 861 | 862 | ### String Interpolation 863 | ``` javascript 864 | var name = "Bob", time = "today"; 865 | `Hello ${name}, how are you ${time}?` 866 | ``` 867 | 868 | ### `let` and `const` 869 | `let` is like `var` except it is block-scoped. Variables declared with `const` can only be assigned once. 870 | ``` javascript 871 | if (1 < 2) { 872 | let i = 4; 873 | const name = 'Jon Snow' 874 | } 875 | var i = 5; // error, i is already defined 876 | name = 'Samwell Tarly' // error, const can only be defined once 877 | ``` 878 | 879 | ### Generator 880 | Functions that can be paused using the `yield` keyword and restarted from the outside. `yield _____` is called a "yield expression" which gets evaluated with whatever value we send in when we restart the generator. `yield` is making a request for a value. 881 | 882 | ``` javascript 883 | function* fibonacci() { 884 | let a = 0, b = 1; 885 | 886 | while(true) { 887 | yield a; 888 | [a, b] = [b, a + b]; 889 | } 890 | } 891 | 892 | // Enumerates the Fibonacci numbers 893 | for(let value of fibonacci()) { 894 | console.log(value); 895 | } 896 | ``` 897 | Generators are useful because they return (i.e. create) iterators. In turn, an iterator, an object with a `next` method, actually executes the body of generators. The `next` method, when repeatedly called, partially executes the corresponding generator, gradually advancing through the body until a `yield` keyword is hit. 898 | 899 | ``` javascript 900 | function* argumentsGenerator() { 901 | for (let i = 0; i < arguments.length; i += 1) { 902 | yield arguments[i]; 903 | } 904 | } 905 | 906 | var argumentsIterator = argumentsGenerator('a', 'b', 'c'); 907 | 908 | // Prints "a b c" 909 | console.log( 910 | argumentsIterator.next().value, 911 | argumentsIterator.next().value, 912 | argumentsIterator.next().value 913 | ); 914 | 915 | // ES6 has syntactic sugar for iteration. 916 | // Prints "a", "b", "c" 917 | for(let value of argumentsIterator) { 918 | console.log(value); 919 | } 920 | ``` 921 | The `next` method of an iterator returns an object with a `value` property and a `done` property, as long as the body of the corresponding generator has not `return`ed. The `value` property refers the value `yield`ed or `return`ed. The `done` property is `false` up until the generator body `return`s, at which point it is `true`. If the `next` method is called after `done` is `true`, an error is thrown. 922 | 923 | ### Maps, Sets, WeakMap, WeakSet 924 | 925 | A Map is an object for which the keys can be any arbitrary object. A Set is a data structure which contains a finite set of elements, each occurring only once. WeakMaps and WeakSets provide leak-free object-key’d side tables. The JavaScript virtual machine periodically frees memory allocated to objects no longer in scope. An object is no longer in scope if there is no chain of references from the current scope leading to it. 926 | ``` javascript 927 | // Sets 928 | var s = new Set(); 929 | s.add("hello").add("goodbye").add("hello"); 930 | s.size === 2; 931 | s.has("hello") === true; 932 | 933 | // Maps 934 | var m = new Map(); 935 | m.set("hello", 42); 936 | m.set(s, 34); 937 | m.get(s) == 34; 938 | 939 | // Weak Maps 940 | var wm = new WeakMap(); 941 | wm.set(s, { extra: 42 }); 942 | wm.size === undefined 943 | 944 | // Weak Sets 945 | var ws = new WeakSet(); 946 | ws.add({ data: 42 }); 947 | // Because the added object has no other references, it will not be held in the set 948 | ``` 949 | 950 | ### Promises 951 | 952 | Promises are a library for asynchronous programming. Promises are a first class representation of a value that may be made available in the future. A Promise is in one of these states: 953 | - pending: initial state, not fulfilled or rejected. 954 | - fulfilled: successful operation 955 | - rejected: failed operation. 956 | - settled: the Promise is either fulfilled or rejected, but not pending. 957 | 958 | ``` javascript 959 | var someAsyncThing = function() { 960 | return new Promise(function(resolve, reject) { 961 | // this will throw, x does not exist 962 | resolve(x + 2); 963 | }); 964 | }; 965 | 966 | someAsyncThing().then(function() { 967 | console.log('everything is great'); 968 | }).catch(function(error) { 969 | console.log('oh no', error); 970 | }); 971 | ``` 972 | 973 | ### Modules 974 | 975 | ``` javascript 976 | // lib/math.js 977 | export function sum(x, y) { 978 | return x + y; 979 | } 980 | export var pi = 3.141593; 981 | ``` 982 | ```javascript 983 | // app.js 984 | import * as math from "lib/math"; 985 | alert("2π = " + math.sum(math.pi, math.pi)); 986 | ``` 987 | ```javascript 988 | // otherApp.js 989 | import {sum, pi} from "lib/math"; 990 | alert("2π = " + sum(pi, pi)); 991 | ``` 992 | 993 | ### Proxy 994 | 995 | Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc). 996 | 997 | ```javascript 998 | // lib/proxy.js 999 | export function create(target) { 1000 | var target = {}; 1001 | return new Proxy(target, {}); 1002 | } 1003 | ``` 1004 | 1005 | ```javascript 1006 | // app.js 1007 | import * as proxy from 'lib/proxy'; 1008 | var target = {}; 1009 | var origin = proxy.create(target); 1010 | origin.a = 37; // operation forwarded to the target 1011 | alert('target.a = ' + target.a); // The operation has been properly forwarded 1012 | ``` 1013 | TODO: Symbol 1014 | --------------------------------------------------------------------------------