JavaScript Knowledge
What's the difference between .call() and .apply()?
Both can be called on functions, which they run in the context of the first argument. In 'call' the subsequent arguments are passed in to the function as they are, while 'apply' expects the second argument to be an array that it unpacks as arguments for the called function. Apply is useful when the arguments to be passed in are created by other code. Mnemonic device: A in Apply for Array.
What is an asynchronous call? When are they useful? How do these work in JavaScript?
An asynchronous call is one that does not execute entirely immediately. Between the time that it is called to the time that it finishes, other code executes. Asynchronousness prevents blocking. It allows other code to execute while the asynchronous call is completing. Async calls are useful on webpages where resources have to be retrieved from another source. Instead of waiting to load the rest of a webpage once an img tag is encountered, an async call is made to the img's source, more of the webpage is loaded, and then when the image resource returns it is loaded.
What is an item's "truth value"?
An item's "truth value" is either truthy or falsey. All values are truthy unless they are one of the 6 falsy values: 1. 0 2. null 3. undefined 4. false 5. NaN 6. Empty string
How does a while loop differ from a for loop?
In short, a for loop is used when the number of iterations is known. A while loop is used when the number of iterations is NOT known.
What does calling setTimeout with a delay of zero do?
It will end up on the callback queue. The event loop will move it onto the call stack only after the call stack is empty. setTimeout with a delay of zero will cause the setTimeout's callback to run after all non-asynchronous code. NOTE: the number given to setTimeout is a minimum time until execution, not an exact time.
What is node and how does it change how you use JavaScript?
node allows JS to run outside the browser. This enables you to use JavaScript to build web apps.
How do you install a package and save it as a dependency? What about saving it as a dev dependency? What's the difference between a dependency and a dev dependency?
npm <module> --save yarn add <module> Dev dependency: npm <module> --save-dev yarn add <module> --dev A regular dependency is needed in production. A dev dependency is only needed in development.
How do we generate a starter package.json file?
npm init
What is npm? What does module.exports do?
npm used to stand for "node package manager" but now it consists of packages that don't just run on node.
What does import do? What does the line import { name, id } from "./user" do?
The import statement is used to import bindings which are exported by another module. This imports the objects or values 'name' or 'id' into the current scope from the file 'user' which is on the same level as the file into which we are importing.
What's the difference between obj[key], obj.key, obj["key"]?
obj[key] will look for a variable 'key'. If it is found, it will use the value of 'key' to search in obj. If 'key' is not defined, an error will occur. obj.key and obj["key"] do the same thing. They look for the value associated with the key 'key' in obj. In short, obj.key and obj["key"] interpret key as a string. obj[key] interprets key as a variable.
What does "use strict"; do? Where does it go?
"use strict"; puts the code into strict mode. In short, strict mode makes it easier to write "secure" JavaScript and helps novices more easily catch their mistakes. Among other things, strict mode throws errors in many instances where non-strict mode will fail silently. Maybe most notably, in strict mode the value of 'this' does not default to the global object. It defaults to undefined. To invoke strict mode for an entire script, put the exact statement "use strict"; (or 'use strict';) before any other statements. Read more here: https://www.w3schools.com/js/js_strict.asp
What's the difference between a for loop and .forEach()?
.forEach() involves fewer lines of code so it is easier to read. However, it does not support 'break' while a for loop does.
What's the difference between node and JavaScript in the browser?
1. Node does not have the browser API's, like the DOM. 2. Node is more focused on input-output interactions. 3. Node can interact with the file system while JS in the browser can NOT. 4. Node can use npm modules.
What are different ways of iterating through arrays? What are their differences?
1. for loop: for (var i = 0; i < n; i++) { statement } 2. do...while: do { statement } while(condition); The statement executes once before the condition is checked--that is, it executes at least once. 3. while: while(condition) { statement } 4. for...in: for (var i in obj) { statement } This will iterate over the object's properties. Use this with true objects, not arrays. 5. for...of: for (var i of arr) { statement } This will iterate over the property VALUES (while for...in iterates over the property names). You CAN use this with arrays.
How do you iterate through the keys of an object?
1. for...in loop Basic syntax: for (const key in obj) {//logic}; NOTE: this will iterate over inherited properties. To skip inherited properties do this: for (const key in obj) { if (obj.hasOwnProperty(key)) { //logic } } 2. Use Object.keys(obj) or obj.getOwnPropertyNames() to create an array of keys. Then use a for loop or .forEach() to iterate through.
What are the standard types in JS?
6 Primitives 1. Boolean 2. Null 3. Undefined 4. Number 5. String 6. Symbol And 7. Object
What's the difference between === and ==? Truth table review! Is NaN == NaN?
=== is strict equality. This checks if two values are the same AND if they are the same type. == is loose equality. This checks if two values are the same after converting the values to the same type.
What's a closure? How do you use closures in JavaScript?
A closure is created by having one function inside the other. The inner function can access variables declared inside itself, inside any containing function, and the global scope. The outer function(s) CANNOT access variables in the inner function(s). In short: A subset can access variables declared in their supersets but the supersets cannot access variables declared in the subset. Imagine concentric circles!
What's an Immediately-Invoked Function Expression (IIFE)? Why do we use them?
Basic syntax: (function () { // logic here })(); or (function () { // logic here }()); IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs as soon as it is defined. The primary reason to use an IIFE is to obtain data privacy. Because JavaScript's var scopes variables to their containing function, any variables declared within the IIFE cannot be accessed by the outside world. A second reason is that an IIFE is anonymous so it does not pollute the global namespace and can't be called by accident.
What's the difference between throw and return?
Both 'throw' and 'return' stop the execution of the containing function. 'return' can spit out a value from the function which can be used to declare the value of a variable. 'throw' can't do this. Only 'throw' allows you to use the try...catch block.
What is a promise and what does it improve upon? How do you write one? What does Promise.all do? What's the difference between .then() and .catch()? How do you use it to replace a callback? Why do promises sometimes swallow errors silently? How do we prevent this? What are the possible return values inside a .then()?
Basic syntax: examplePromise() .then(result => examplePromise2(result)) .then(newResult => examplePromise3(newResult)) .then(finalResult => func(finalResult)) .catch(error) { doSomethingWithError(error); } A Promise is an object representing the eventual completion or failure of an asynchronous operation. Essentially, a promise is a returned object to which you attach callbacks, instead of passing callbacks into a function. Promises get us out of Callback Hell because we can chain promises together using .then(). The Promise.all() method returns a single Promise that resolves when all of the promises in the iterable argument have resolved or when the iterable argument contains no promises. It rejects with the reason of the first promise that rejects. If all promises in the Promise.all are resolved, the promise returns an array of the values returned from the individual promises. Example of Promise.all(): Promise.all([promise1, promise2, promise3]) .then(arr => { console.log(arr); // [p1, p2, p3] }); .then() can return a value, in which case the next .then() in the chain will pass it onto its corresponding function. Or .then() can return an async function in which case the next .then() will wait for the async function to resolve/reject and then pass this value onto its corresponding function. See here: https://developers.google.com/web/fundamentals/primers/promises#queuing_asynchronous_actions COULDN'T FIGURE OUT THE ISSUE WITH PROMISES SILENTLY SWALLOWING ERRORS
How can you catch exceptions in JavaScript?
Basic syntax: function f() { try { //stuff } catch(e) { //stuff } finally { //stuff } } The try...catch statement consists of a try block, which contains one or more statements, and a catch block, containing statements that specify what to do if an exception is thrown in the try block. That is, you want the try block to succeed, and if it does not succeed, you want control to pass to the catch block. If any statement within the try block (or in a function called from within the try block) throws an exception, control immediately shifts to the catch block. If no exception is thrown in the try block, the catch block is skipped. The finally block executes after the try and catch blocks execute but before the statements following the try...catch statement. The finally block will execute regardless of whether an exception was thrown or caught. When a 'throw' call is triggered in the try block, it can pass number/string/object onto to the catch block. It can be used in the catch block by adding an argument to catch, mostly usually 'e' (for error). The catch block will look like this: catch(e) {//do stuff with e}.
What is the spread operator? What is it used for? How do we use it to modify an array? How do we use it in place of .apply()?
Basic syntax: var args = [1, 2, 3] console.log(...args) // 1 2 3 Allows parts of an array literal to be initialized from an iterable expression (such as another array literal), or allows an expression to be expanded to multiple arguments (in function calls). You can use it to access items in array. Using it to modify an array: var arr1 = [1, 2, 3]; var arr2 = [a, b, ...arr1, c, d]; console.log(arr2); // a b 1 2 3 c d Comparing using concat and using the spread operator var a, b, c, d, e; a = [1,2,3]; b = "dog"; c = [42, "cat"]; // Using the concat method. d = a.concat(b, c); // Using the spread operator. e = [...a, b, ...c]; Using it in place of .apply(): function doStuff (x, y, z) { } var args = [0, 1, 2]; // Call the function, passing args doStuff.apply(null, args); // With the spread operator doStuff(...args);
What is an "arrow" function? How does it differ from the typical function declarations? What does it mean for an arrow function to be auto-bound? Why is this useful?
Basic syntax: var func = (param1, ..., paramn) => {statement}; OR var func = (param1, ..., paramn) => statement This returns statement automatically OR var func = (param1, ..., paramn) => ({obj}); This returns an object literal. OR var func = singleParam => {statement}; Parentheses are optional around param when there's only one. An arrow function expression has a shorter syntax than a function expression and does not have its own this, arguments, super, or new.target. These function expressions are best suited for non-method functions, and they cannot be used as constructors. An arrow function does not have its own this; the this value of the enclosing execution context is used. Given that this comes from the surrounding lexical context, strict mode rules with regard to this are ignored. Arrow functions cannot be used as constructors and will throw an error when used with new.
What is a template string? How do you write one?
Basic syntax: `${var}` Back ticks are the key! Template strings or template literals are string literals allowing embedded expressions. They enable: 1. Multiline strings 2. Expression interpolation 3. Tagged template literals (used for preprocessing)
What does .bind() do? How do you use it to "set the context" of a function? How do you use it to pass in variables to a function?
Basic syntax: var boundFun = fun.bind(this, arg1, arg2, ..., argn); The simplest use of bind() is to make a function that, no matter how it is called, is called with a particular 'this' value. The bind() method creates a new function that, when called, has its 'this' keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called. The next simplest use of bind() is to make a function with pre-specified initial arguments. These arguments (if any) follow the provided 'this' value and are then inserted at the start of the arguments passed to the target function, followed by the arguments passed to the bound function, whenever the bound function is called.
What does the var keyword do?
Basic syntax: var name Declares a variable. Variables declarations are processed before any code is executed. This means that a variable can appear to be called before it is declared via a process called 'hoisting'. However, the variable is only declared at the beginning of the code, not assigned a value.
How do we read environment variables in a node app? Why is this useful?
Environment variables keep information secret from others. A common use case are API keys. If someone else gets your API key, they can use your app/account. Here's how to use them: Via the command line: export MYAPIKEY = 'XXXX'; With the package dotenv: 1. Create .env file at the top of your project 2. Add the vars like so: MYAPIKEY='XXXX' 3. Add require('dotenv').config(); to the entry point of your project 4. The vars in the .env will be loaded into process.env and be used in your project by referencing process.env.VARNAME The "Horizons Method": 1. Create a file env.sh with lines that look like so: export FACEBOOK_APP_ID='XXXX' 2. In the CLI for your project, run 'source env.sh'
What is a generator? What does yield do? Why is this useful?
Example: function* idMaker() { var index = 0; while (index < 3) yield index++; } var gen = idMaker(); console.log(gen.next().value); // 0 console.log(gen.next().value); // 1 console.log(gen.next().value); // 2 console.log(gen.next().value); // undefined // ... Generators allows us to work with asynchronous code in an easier, more readable fashion. Generators are functions which can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances. Calling a generator function does not execute its body immediately; an iterator object for the function is returned instead. When the iterator's next() method is called, the generator function's body is executed until the first yield expression, which specifies the value to be returned from the iterator or, with yield*, delegates to another generator function. The next() method returns an object with a value property containing the yielded value and a done property which indicates whether the generator has yielded its last value as a boolean. Calling the next() method with an argument will resume the generator function execution, replacing the yield expression where execution was paused with the argument from next(). A return statement in a generator, when executed, will make the generator done. If a value is returned, it will be passed back as the value. A generator which has returned will not yield any more values.
What's the .prototype property in JavaScript? When do we use it?
Example: var Person = function(name, height, weight) { this.name = name; this.height = height; this.weight = weight; } Person.prototype.BMI = this.height/(this.weight * this.weight); An object constructor function or constructor method within a class will create an object prototype. the .prototype property allows you to add new properties and methods to an existing prototype. See this for a good example: https://www.khanacademy.org/computing/computer-programming/programming/object-oriented/p/object-inheritance
What's the purpose of the new keyword?
Example: var Bob = new Person('Bob', 73, 175); The new operator creates an instance of a user-defined object type or of one of the built-in object types that has a constructor function.
What are the different ways of defining a function in JS? What are their pros and cons? When might we use each? Discuss global, non-hoisted, local, and hoisted in your answer.
Function declaration: function func(args) {logic} Function expressions: var func = function(args) {logic} var func = (params) => {return expression}; Function expressions are NOT hoisted. Function declarations ARE hoisted. Using a function expression allows the function to be anonymous. Function expressions are convenient when passing a function as an argument to another function. A local function is one defined inside of a function. It is local to that function and cannot be accessed outside the scope of that function.
What's hoisting? What gets hoisted and what doesn't?
Hoisting effectively moves declarations to the top of the code and executes these before the rest of the code. The effect of hoisting is that variables and functions can be used before they are declared in the code. Note that initializations (i.e. var i = 5) are NOT hoisted. Only the declaration 'var i' will be hoisted. If you tried to use the value of i before the line 'var i = 5' appears in the code, you will encounter an error.
Explain variable scoping in JavaScript.
Imagine the scopes as concentric circles. If one scope is inside the other, the inner scope can access the variables of the outer scope, but the outer scope cannot access the variables in the inner scope. The largest circle is the global scope. The inner circles (each created by a function) are local scopes. In short, you can go out but you can't go in.
Can you access a variable defined inside a function, outside of that function?
No.
What does Object.assign() do? When might we use it?
Object.assign() copies the values (of all enumerable own properties) from one or more source objects to a target object. It has a signature of Object.assign(target, ...sources). The target object is the first parameter and is also used as the return value. Object.assign() is useful for merging objects or cloning them shallowly. See this page for a very good explanation: https://googlechrome.github.io/samples/object-assign-es6/
Where are variables declared with var in Node module visible?
Only within that module. (This is why you have to export-import between node modules). This is because modules in Node are executed in their own closure.
What is a "module"? What are "dependencies"? Why is knowing about them important?
Package = module = a directory with one or more files in it that solves a particular problem. Packages enable you to use JS to build things. npm makes it easy to use and share packages.
What's the REPL?
REPL stands for Read-Eval-Print-Loop. It is the Node.js shell. It gives you an environment to test out JS, much like you can do in Chrome console. To use the REPL, just run 'node' in the console of a text editor.
What's a RegEx and what can you use it for?
Regular expressions are used to perform pattern-matching and "search-and-replace" functions on text. Basic syntax: var RegEx = /pattern/; Works with the following methods: RegEx.exec(); RegEx.test(); String.match(); String.search(); String.replace(); String.split();
Is JavaScript single-threaded or multi-threaded? What does this mean exactly?
Single-threaded. This means that JS can only run one line of code at a time. one thread == one call stack == one thing at a time
What is the JavaScript event loop? Why is it important?
The event loop pops an item from the callback queue and pushes it onto the call stack. The event loop, in conjunction with the callback queue, enable JavaScript to run asynchronously and give the impression of running concurrently.
What's the difference between .concat() and .push() on an array? What do each return? What kind of effect does each have on the array?
The concat() method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array. The push() method adds one or more elements to the end of an array and returns the new length of the array.
What is de-structuring/unpacking?
The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables. It enables stuff like the following: var a, b, rest; [a, b] = [10, 20]; console.log(a); // 10 console.log(b); // 20 [a, b, ...rest] = [10, 20, 30, 40, 50]; console.log(a); // 10 console.log(b); // 20 console.log(rest); // [30, 40, 50] It works similarly for objects. There are lots of nuanced use-cases. See here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
What does .map() do?
The map() method creates a new array with the results of calling a provided function on every element in the calling array. Think of map as a transformation. Basic syntax: var arr2 = arr.map(function(x) { // logic });
What does the package.json file do?
The package.json file records your application's dependencies (the modules that it needs to work).
What does .reduce() do?
The reduce() method applies a function against an accumulator and each element in the array (from left to right) to reduce it to a single value. Basic syntax: arr.reduce(fun(accumulator, value)[, initialValue]); Example of using .reduce() to flatten an array: var flattened = [[0, 1], [2, 3], [4,5]].reduce(function(a, b) { return a.concat(b); }, []);
What is the rest operator? What is it used for? How is it different from the spread operator?
The rest parameter syntax allows us to represent an indefinite number of arguments as an array. The rest operator comes last and it represents an array containing the "rest" of the arguments in a function. When not all values should be included in the rest parameter, you could define those as comma separated parameters at the beginning. The difference between the rest and spread operators is where they are used. The spread operator fills the function invocation arguments with values from an array while the rest operator grabs arguments passed into the function.
How do you iterate through arguments in a function?
Use the 'arguments' Array-like object. The arguments object is a local variable available within all (non-arrow) functions. You can refer to a function's arguments within the function by using the arguments object. This object contains an entry for each argument passed to the function, the first entry's index starting at 0. You can set a particular value of arguments like this: arguments[n] = whatever. Note that the arguments object is not an Array. It is similar to an Array, but does not have any Array properties except length. However, it can be converted into a real array by: 1. var args = Array.from(arguments); 2. var args = [...arguments];
How does this work in JavaScript?
When a function executes, it gets the 'this' property—a variable with the value of the object that invokes the function where this is used. Note that when we use strict mode, 'this' holds the value of undefined in global functions and in anonymous functions that are not bound to any object. In non-strict mode, 'this' defaults to 'window'. 'this' is not assigned a value until an object invokes the function where 'this' is defined. bind(), apply(), and call() can be used to set the value of this within a function.
How can JavaScript be single-threaded and asynchronous?
You have the call stack, the Web Apis queue, and the callback queue. When you call a piece of code, it will pushed onto the call stack. If it involves some code that is async, this part is put on the Web Apis queue where it is run and then its result is put onto the callback queue. Once the call stack is empty, the event loop will pop from the callback queue, push this onto the call stack, and execute this code. This is why setTimeout(func, 0) will execute func AFTER all the other code. See this amazing video for a full explanation: https://www.youtube.com/watch?v=8aGhZQkoFbQ
How do you remove/replace an item somewhere in the middle of an array?
array.splice(start, deleteCount, itemToInsert1, ..., itemToInsertn) To find the index of an item: array.indexOf(item); Mnemonic: sPlice has more Power than slice because sPlice changes the original array. ES6: let newArray = [ ...array.slice(0, index), ...array.slice(index + 1) ]
How do you break out of a loop? Bonus: How do you break out of a loop inside of a loop?
break; Bonus: label each loop and then include the label with the break statement in the inner loop. Example: outer-loop: for (var i = 0; i < 3; i++) { inner-loop: for (var j = 0: j < 4: i++) { break outer-loop; } }
What's the return value of a function that doesn't call return?
undefined
What's the difference between var, let, and const? When do you use each one?
var is function-scoped. let and const are block-scoped. var is hoisted. let and const are NOT hoisted. let is useful to bind the value of the iterand in each loop. Use const when you will not reassign the variable. const however does NOT make the variable immutable.
In a for loop, what are the semi-colon separated values? (i.e. for (x; y; z) { ... })
x = initial expression (e.g. var i = 0); y = condition (e.g. i < array.length); z = increment expression (e.g. i++);