HTML Cheat
HTML Cheat
25 contributors
JS Questions
Answers to Front-end Job Interview Questions - JS Questions. Pull
requests for suggestions and corrections are welcome!
• What are the differences between ES6 class and ES5 function
constructors?
• Can you offer a use case for the new arrow => function syntax?
How does this new syntax differ from other functions?
• What advantage is there for using the arrow syntax for a method
in a constructor?
• What is the definition of a higher-order function?
• Can you give an example for destructuring an object or an array?
• ES6 Template Literals offer a lot of flexibility in generating strings,
can you give an example?
• Can you give an example of a curry function and why this syntax
offers an advantage?
• What are the benefits of using spread syntax and how is it
different from rest syntax?
• How can you share code between files?
• Why you might want to create static class members?
Explain event delegation
Event delegation is a technique involving adding event listeners to a
parent element instead of adding them to the descendant elements.
The listener will fire whenever the event is triggered on the descendant
elements due to event bubbling up the DOM. The benefits of this
technique are:
References
• https://davidwalsh.name/event-delegate
• https://stackoverflow.com/questions/1687296/what-is-dom-
event-delegation
1. If the new keyword is used when calling the function, this inside
the function is a brand new object.
2. If apply , call , or bind are used to call/create a function, this
inside the function is the object that is passed in as the argument.
3. If a function is called as a method, such as obj.method() — this
is the object that the function is a property of.
4. If a function is invoked as a free function invocation, meaning it
was invoked without any of the conditions present above, this is
the global object. In a browser, it is the window object. If in strict
mode ( 'use strict' ), this will be undefined instead of the
global object.
5. If multiple of the above rules apply, the rule that is higher wins
and will set the this value.
6. If the function is an ES2015 arrow function, it ignores all the rules
above and receives the this value of its surrounding scope at the
time it is created.
Can you give an example of one of the ways that working with this
has changed in ES6?
ES6 allows you to use arrow functions which uses the enclosing lexical
scope. This is usually convenient, but does prevent the caller from
controlling context via .call or .apply —the consequences being
that a library such as jQuery will not properly bind this in your event
handler functions. Thus, it's important to keep this in mind when
refactoring large legacy applications.
References
• https://codeburst.io/the-simple-rules-to-this-in-javascript-
35d97f31bde3
• https://stackoverflow.com/a/3127440/1751946
child.cry = function() {
console.log("waaaaaahhhh!");
}
child.cry();
// Outputs: waaaaaahhhh!
child.greet();
// Outputs: hello from Parent
child.constructor
ƒ () {
this.name = "Parent";
}
child.constructor.name
"Parent"
• If we'd like to correct this, one option would be to do:
function Child() {
Parent.call(this);
this.name = 'child';
}
Child.prototype = Parent.prototype;
Child.prototype.constructor = Child;
c.cry();
// Outputs: waaaaaahhhh!
c.greet();
// Outputs: hello from Parent
c.constructor.name;
// Outputs: "Child"
References
• https://www.quora.com/What-is-prototypal-
inheritance/answer/Kyle-Simpson
• https://davidwalsh.name/javascript-objects
• https://crockford.com/javascript/prototypal.html
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
I'm glad that with ES2015 modules, that has support for both
synchronous and asynchronous loading, we can finally just stick to one
approach. Although it hasn't been fully rolled out in browsers and in
Node, we can always use transpilers to convert our code.
References
• https://auth0.com/blog/javascript-module-systems-showdown/
• https://stackoverflow.com/questions/16521471/relation-between-
commonjs-amd-and-requirejs
Here are two ways to fix it that involves adding more parentheses:
(function foo(){ })() and (function foo(){ }()) . Statements that
begin with function are considered to be function declarations; by
wrapping this function within () , it becomes a function expression
which can then be executed with the subsequent () . These functions
are not exposed in the global scope and you can even omit its name if
you do not need to reference itself within the body.
You might also use void operator: void function foo(){ }(); .
Unfortunately, there is one issue with such approach. The evaluation of
given expression is always undefined , so if your IIFE function returns
anything, you can't use it. An example:
console.log(foo); // undefined
References
• http://lucybain.com/blog/2014/immediately-invoked-function-
expression/
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Operators/void
function foo() {
x = 1; // Throws a ReferenceError in strict mode
}
foo();
console.log(x); // 1
A variable that is undefined is a variable that has been declared, but
not assigned a value. It is of type undefined . If a function does not
return any value as the result of executing it is assigned to a variable,
the variable also has the value of undefined . To check for it, compare
using the strict equality ( === ) operator or typeof which will give the
'undefined' string. Note that you should not be using the abstract
equality operator to check, as it will also return true if the value is
null .
var foo;
console.log(foo); // undefined
console.log(foo === undefined); // true
console.log(typeof foo === 'undefined'); // true
function bar() {}
var baz = bar();
console.log(baz); // undefined
A variable that is null will have been explicitly assigned to the null
value. It represents no value and is different from undefined in the
sense that it has been explicitly assigned. To check for null, simply
compare using the strict equality operator. Note that like the above,
you should not be using the abstract equality operator ( == ) to check,
as it will also return true if the value is undefined .
• https://stackoverflow.com/questions/15985875/effect-of-
declared-and-undeclared-variables
•
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/
Global_Objects/undefined
References
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Closures
• https://medium.com/javascript-scene/master-the-javascript-
interview-what-is-a-closure-b2f0d2152b36
forEach
• Iterates through the elements in an array.
• Executes a callback for each element.
• Does not return a value.
// doubled = undefined
map
// doubled = [2, 4, 6]
References
• https://codeburst.io/javascript-map-vs-foreach-f38111822c0f
As a callback that is used once and does not need to be used anywhere
else. The code will seem more self-contained and readable when
handlers are defined right inside the code calling them, rather than
having to search elsewhere to find the function body.
setTimeout(function() {
console.log('Hello world!');
}, 1000);
References
• https://www.quora.com/What-is-a-typical-usecase-for-
anonymous-functions
• https://stackoverflow.com/questions/10273185/what-are-the-
benefits-to-using-anonymous-functions-instead-of-named-
functions-fo
References
• https://stackoverflow.com/questions/7614317/what-is-the-
difference-between-native-objects-and-host-objects
function Person(name) {
this.name = name;
}
References
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Operators/new
Both .call and .apply are used to invoke functions and the first
parameter will be used as the value of this within the function.
However, .call takes in comma-separated arguments as the next
arguments while .apply takes in an array of arguments as the next
argument. An easy way to remember this is C for call and comma-
separated and A for apply and an array of arguments.
function add(a, b) {
return a + b;
}
console.log(add.call(null, 1, 2)); // 3
console.log(add.apply(null, [1, 2])); // 3
Explain Function.prototype.bind .
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.
References
•
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/
Global_objects/Function/bind
References
•
https://www.quirksmode.org/blog/archives/2005/06/three_javascri
p_1.html
• https://github.com/h5bp/html5-boilerplate/wiki/Script-Loading-
Techniques#documentwrite-script-tag
if ('geolocation' in navigator) {
// Can use navigator.geolocation
} else {
// Handle lack of feature
}
Feature Inference
Feature inference checks for a feature just like feature detection, but
uses another function because it assumes it will also exist, e.g.:
if (document.getElementsByTagName) {
element = document.getElementById(id);
}
UA String
References
• https://developer.mozilla.org/en-
US/docs/Learn/Tools_and_testing/Cross_browser_testing/Feature_
detection
• https://stackoverflow.com/questions/20104930/whats-the-
difference-between-feature-detection-feature-inference-and-
using-th
• https://developer.mozilla.org/en-
US/docs/Web/HTTP/Browser_detection_using_the_user_agent
References
• https://en.wikipedia.org/wiki/Ajax_(programming)
• https://developer.mozilla.org/en-US/docs/AJAX
Disadvantages
Explain how JSONP works (and how it's not really Ajax).
JSONP (JSON with Padding) is a method commonly used to bypass the
cross-domain policies in web browsers because Ajax requests from the
current page to a cross-origin domain is not allowed.
<script src="https://example.com?callback=printData"></script>
The client has to have the printData function in its global scope and
the function will be executed by the client when the response from the
cross-origin domain is received.
• https://stackoverflow.com/a/2067584/1751946
Explain "hoisting".
Hoisting is a term used to explain the behavior of variable declarations
in your code. Variables declared or initialized with the var keyword
will have their declaration "moved" up to the top of the current scope,
which we refer to as hoisting. However, only the declaration is hoisted,
the assignment (if there is one), will stay where it is.
Note that the declaration is not actually moved - the JavaScript engine
parses the declarations during compilation and becomes aware of
declarations and their scopes. It is just easier to understand this
behavior by visualizing the declarations as being hoisted to the top of
their scope. Let's explain with a few examples.
// Function Declaration
console.log(foo); // [Function: foo]
foo(); // 'FOOOOO'
function foo() {
console.log('FOOOOO');
}
console.log(foo); // [Function: foo]
// Function Expression
console.log(bar); // undefined
bar(); // Uncaught TypeError: bar is not a function
var bar = function() {
console.log('BARRRR');
};
console.log(bar); // [Function: bar]
But after you change the value of the text field by adding "World!" to
it, this becomes:
console.log(input.getAttribute('value')); // Hello
console.log(input.value); // Hello World!
References
• https://stackoverflow.com/questions/6003819/properties-and-
attributes-in-html
The only time you may want to extend a native object is when you
want to create a polyfill, essentially providing your own
implementation for a method that is part of the JavaScript specification
but might not exist in the user's browser due to it being an older
browser.
References
• http://lucybain.com/blog/2014/js-extending-built-in-objects/
window 's load event is only fired after the DOM and all dependent
resources and assets have loaded.
References
• https://developer.mozilla.org/en-
US/docs/Web/Events/DOMContentLoaded
• https://developer.mozilla.org/en-US/docs/Web/Events/load
1 == '1'; // true
1 == [1]; // true
1 == true; // true
0 == ''; // true
0 == '0'; // true
0 == false; // true
var a = null;
console.log(a == null); // true
console.log(a == undefined); // true
References
• https://stackoverflow.com/questions/359494/which-equals-
operator-vs-should-be-used-in-javascript-comparisons
References
• https://en.wikipedia.org/wiki/Same-origin_policy
function duplicate(arr) {
return arr.concat(arr);
}
Or with ES6:
References
•
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/
Operators/Conditional_Operator
Advantages:
Disadvantages:
References
• http://2ality.com/2011/10/strict-mode-hatred.html
• http://lucybain.com/blog/2014/js-use-strict/
I would not advise you to write the above during interviews though.
Just stick with the long but clear approach. For more wacky versions of
FizzBuzz, check out the reference link below.
References
• https://gist.github.com/jaysonrowe/1592432
The DOM event DOMContentLoaded will fire after the DOM for the page
has been constructed, but do not wait for other resources to finish
loading. This is preferred in certain cases when you do not need the full
page to be loaded before initializing.
TODO.
References
• https://developer.mozilla.org/en-
US/docs/Web/API/GlobalEventHandlers/onload
Web developers these days refer to the products they build as web
apps, rather than websites. While there is no strict difference between
the two terms, web apps tend to be highly interactive and dynamic,
allowing the user to perform actions and receive a response to their
action. Traditionally, the browser receives HTML from the server and
renders it. When the user navigates to another URL, a full-page refresh
is required and the server sends fresh new HTML to the new page. This
is called server-side rendering.
However, in modern SPAs, client-side rendering is used instead. The
browser loads the initial page from the server, along with the scripts
(frameworks, libraries, app code) and stylesheets required for the
whole app. When the user navigates to other pages, a page refresh is
not triggered. The URL of the page is updated via the HTML5 History
API. New data required for the new page, usually in JSON format, is
retrieved by the browser via AJAX requests to the server. The SPA then
dynamically updates the page with the data via JavaScript, which it has
already downloaded in the initial page load. This model is similar to
how native mobile apps work.
The benefits:
• The app feels more responsive and users do not see the flash
between page navigations due to full-page refreshes.
• Fewer HTTP requests are made to the server, as the same assets
do not have to be downloaded again for each page load.
• Clear separation of the concerns between the client and the server;
you can easily build new clients for different platforms (e.g.
mobile, chatbots, smart watches) without having to modify the
server code. You can also modify the technology stack on the
client and server independently, as long as the API contract is not
broken.
The downsides:
• https://github.com/grab/front-end-guide#single-page-apps-spas
• http://stackoverflow.com/questions/21862054/single-page-app-
advantages-and-disadvantages
• http://blog.isquaredsoftware.com/presentations/2016-10-
revolution-of-web-dev/
• https://medium.freecodecamp.com/heres-why-client-side-
rendering-won-46a349fadb52
Some common polyfills are $.deferred , Q and Bluebird but not all of
them comply with the specification. ES2015 supports Promises out of
the box and polyfills are typically not needed these days.
References
• https://medium.com/javascript-scene/master-the-javascript-
interview-what-is-a-promise-27fc71e77261
Cons
References
• https://github.com/getify/You-Dont-Know-
JS/blob/master/async%20%26%20performance/ch3.md
Advantages:
Disadvantages:
• Require a build/compile process as browsers only run JavaScript
and your code will need to be compiled into JavaScript before
being served to browsers.
• Debugging can be a pain if your source maps do not map nicely
to your pre-compiled source.
• Most developers are not familiar with these languages and will
need to learn it. There's a ramp up cost involved for your team if
you use it for your projects.
• Smaller community (depends on the language), which means
resources, tutorials, libraries, and tooling would be harder to find.
• IDE/editor support might be lacking.
• These languages will always be behind the latest JavaScript
standard.
• Developers should be cognizant of what their code is being
compiled to — because that is what would actually be running, and
that is what matters in the end.
References
•
https://softwareengineering.stackexchange.com/questions/72569/
what-are-the-pros-and-cons-of-coffeescript
• https://hackernoon.com/twelve-fancy-chrome-devtools-tips-
dc1e39d10d9d
• https://raygun.com/blog/javascript-debugging/
For arrays:
Most of the time, I would prefer the .forEach method, but it really
depends on what you are trying to do. Before ES6, we used for loops
when we needed to prematurely terminate the loop using break . But
now with ES6, we can do that with for-of loops. I would use for
loops when I need even more flexibility, such as incrementing the
iterator more than once per loop.
Also, when using the for-of loop, if you need to access both the
index and value of each array element, you can do so with the ES6
Array entries() method and destructuring:
References
• http://2ality.com/2015/08/getting-started-es6.html#from-for-to-
foreach-to-for-of
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Array/entries
Prevent Extensions
var myObject = {
a: 2
};
Object.preventExtensions(myObject);
myObject.b = 3;
myObject.b; // undefined
So, not only can you not add any more properties, but you also cannot
reconfigure or delete any existing properties (though you can still
modify their values).
Freeze
This approach is the highest level of immutability that you can attain
for an object itself, as it prevents any changes to the object or to any of
its direct properties (though, as mentioned above, the contents of any
referenced other objects are unaffected).
Pros
Cons
References
• https://stackoverflow.com/questions/1863515/pros-cons-of-
immutability-vs-mutability
Examples:
// Array Example
const arr = [1, 2, 3];
const newArr = [...arr, 4]; // [1, 2, 3, 4]
// Object Example
const human = Object.freeze({race: 'human'});
const john = { ...human, name: 'John' }; // {race: "human", name: "John"}
const alienJohn = { ...john, race: 'alien' }; // {race: "alien", name: "John"}
References
• https://stackoverflow.com/questions/1863515/pros-cons-of-
immutability-vs-mutability
• https://www.sitepoint.com/immutability-javascript/
• https://wecodetheweb.com/2016/02/12/immutable-javascript-
using-es6-and-beyond/
If you haven't already checked out Philip Robert's talk on the Event
Loop, you should. It is one of the most viewed videos on JavaScript.
References
• https://2014.jsconf.eu/speakers/philip-roberts-what-the-heck-is-
the-event-loop-anyway.html
• http://theproactiveprogrammer.com/javascript/the-javascript-
event-loop-a-stack-and-a-queue/
Function Declaration
foo(); // 'FOOOOO'
function foo() {
console.log('FOOOOO');
}
Function Expression
References
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Statements/function
Variables declared using the var keyword are scoped to the function
in which they are created, or if created outside of any function, to the
global object. let and const are block scoped, meaning they are only
accessible within the nearest set of curly braces (function, if-else block,
or for-loop).
function foo() {
// All variables are accessible within functions.
var bar = 'bar';
let baz = 'baz';
const qux = 'qux';
console.log(bar); // bar
console.log(baz); // baz
console.log(qux); // qux
}
if (true) {
var bar = 'bar';
let baz = 'baz';
const qux = 'qux';
}
console.log(foo); // undefined
Redeclaring a variable with var will not throw an error, but 'let' and
'const' will.
let and const differ in that let allows reassigning the variable's
value while const does not.
// This is fine.
let foo = 'foo';
foo = 'bar';
References
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Statements/let
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Statements/var
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Statements/const
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
// ES6 Class
class Student extends Person {
constructor(name, studentId) {
super(name);
this.studentId = studentId;
}
}
It's much more verbose to use inheritance in ES5 and the ES6 version is
easier to understand and remember.
References
• https://developer.mozilla.org/en-
US/docs/Learn/JavaScript/Objects/Inheritance
• https://eli.thegreenplace.net/2013/10/22/classical-inheritance-in-
javascript-es5
john.sayName1(); // John
john.sayName2(); // John
// The regular function can have its 'this' value changed, but the arrow function can
john.sayName1.call(dave); // Dave (because "this" is now the dave object)
john.sayName2.call(dave); // John
The main takeaway here is that this can be changed for a normal
function, but the context always stays the same for an arrow function.
So even if you are passing around your arrow function to different
parts of your application, you wouldn't have to worry about the
context changing.
References
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
• https://medium.com/@machnicki/handle-events-in-react-with-
arrow-functions-ede88184bbb
Map
• https://medium.com/javascript-scene/higher-order-functions-
composing-software-5365cf2cbe99
• https://hackernoon.com/effective-functional-javascript-first-class-
and-higher-order-functions-713fde8df50a
• https://eloquentjavascript.net/05_higher_order.html
Array destructuring
// Variable assignment.
const foo = ['one', 'two', 'three'];
// Swapping variables
let a = 1;
let b = 3;
Object destructuring
// Variable assignment.
const o = { p: 42, q: true };
const { p, q } = o;
console.log(p); // 42
console.log(q); // true
References
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Operators/Destructuring_assig
nment
• https://ponyfoo.com/articles/es6-destructuring-in-depth
With template literals, you can now create that same output like this
instead:
Note that you use backticks, not quotes, to indicate that you are using
a template literal and that you can insert expressions inside the ${}
placeholders.
References
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Template_literals
function curry(fn) {
if (fn.length === 0) {
return fn;
}
function add(a, b) {
return a + b;
}
References
• https://hackernoon.com/currying-in-js-d9ddc64f162e
function putDookieInAnyArray(arr) {
return [...arr, 'dookie'];
}
const person = {
name: 'Todd',
age: 29,
};
function addFiveToABunchOfNumbers(...numbers) {
return numbers.map(x => x + 5);
}
const { e, f, ...others } = {
e: 1,
f: 2,
g: 3,
h: 4,
}; // e: 1, f: 2, others: { g: 3, h: 4 }
References
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Functions/rest_parameters
• https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Operators/Destructuring_assig
nment
On the server (Node.js), the common way has been to use CommonJS.
Each file is treated as a module and it can export variables and
functions by attaching them to the module.exports object.
ES2015 defines a module syntax which aims to replace both AMD and
CommonJS. This will eventually be supported in both browser and
Node environments.
References
• http://requirejs.org/docs/whyamd.html
• https://nodejs.org/docs/latest/api/modules.html
• http://2ality.com/2014/09/es6-modules-final.html
Why you might want to create static class members?
Static class members (properties/methods) are not tied to a specific
instance of a class and have the same value regardless of which
instance is referring to it. Static properties are typically configuration
variables and static methods are usually pure utility functions which do
not depend on the state of the instance.
References
• https://stackoverflow.com/questions/21155438/when-to-use-
static-variables-methods-and-when-to-use-instance-variables-
methods
Other Answers
• http://flowerszhong.github.io/2013/11/20/javascript-
questions.html