Legend:
- β : complete
- ππ»ββοΈ: still need more work
- π§: have not started yet
β
Explain the difference between new String(1)
and String(1)
.
-
new String(1)
creates a string object.typeof new String(1) === 'object'
-
String(1)
creates a primitive string variable.typeof String(1) === 'string'
. But we can still call String object method on this variable because the browser will auto-box this object. -
new
keyword is used to execute a function and return an object. This happens whennew
is used:- A new object is created
this
is bound to the new object- The new (empty) object is returned, unless the function returns its own object
- The newly created object is assigned as value to the variable
Remember you can always call new
on classes as well as functions:
function Person(name){
return {
name
}
}
const person = new Person('Joel') // { name: 'Joel' }
// or this way:
function Person(name){
this.name = name
}
// or ES6 class:
class Person{
constructor(name){
this.name = name
}
}
const person = new Person('Joel') // { name: 'Joel' }
See more at:
β
Explain the difference between const person = Person()
vs const person = new Person()
provided function Person(){...}
const person = Person()
On the other hand, this just calls the function and assigns the function output to the variable person
.
const person = new Person()
This creates an instance of the Person object using the new operator, which inherits from Person.prototype
.
In short, Person
gets called as a constructor.
β
Explain this
binding.
To brief it, this
keyword refers to the object it belongs to. But it's more complicated than that.
this
is NOT author-time binding. Itβs a runtime binding. It depends on contexts. Itβs not about WHERE the function is called from, but HOW the function is called.
Without the strict mode in effect, the global object is eligible for the default binding:
function foo() { console.log( this.a ); }
const a = 2;
foo(); // 2
When there is a context object (object having a reference to a function or a variable) for a function reference, the implicit binding rule says that itβs that object which should be used for the function callβs this
binding.
function foo() {
console.log( this.a );
}
const obj = {
a: 2,
foo: foo
};
obj.foo(); // 2
Explicit binding uses call
and apply
to use a selected object for this binding. (For call
and apply
, see the next question)
function foo() {
console.log( this.a );
}
const obj = {
a: 2
};
foo.call( obj ); // 2
// or
foo.apply(obj) // 2
This is what happens if you call a function with new
:
- a brand new object is created (aka, constructed) out of thin air
- the newly constructed object is
[[Prototype]]
-linked (linked to the function object's prototype) - the newly constructed object is set as the this binding for that function call
- unless the function returns its own alternate object, the new-invoked function call will automatically return the newly constructed object.
Default < Implicit < Explicit < `new`
Calling call
or apply
with null
or undefined
makes this
ignored. This means calling call
/apply
with null
as the first argument is like calling the function without providing any object for this
.
function foo() {
console.log( this.a );
}
const a = 2;
foo.call( null ); // 2 because `this` now points to global object.
important note: The lexical binding of an arrow-function cannot be overridden (even with new
).
function Foo() {
this.a = 0
// return an arrow function
return () => {
// `this` here is lexically adopted from `foo()`
console.log( this.a );
};
}
function Foo2() {
this.a = 0
// return an arrow function
return function(){
// `this` here is NOT lexically adopted from `foo()`
console.log( this.a );
};
}
const foo = new Foo()
foo() // logs 0
const foo2 = new Foo2()
foo2() // logs undefined, because now this inside the returned function binds to the global scope
See more at:
β
Explain the difference between call
and apply
.
Both call
and apply
are used to call a function with a given this
value and arguments provided.
From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call:
While the syntax of this function is almost identical to that of apply(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.
call
:function.call(thisArg, arg1, arg2, ...)
apply
:function.apply(thisArg, [argsArray])
This is how you can use call
:
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name);
// expected output: "cheese"
β
Explain how to use async
, await
and Promise
and why they are good (and better than callbacks).
- it is a proxy for a value not necessarily known when the promise is created.
- it allows you to solve these problems Kyle Simpson mentions. For more, refer to the link as it is somewhat complicated:
- Call the callback too early
- Call the callback too late (or never):
- Call the callback too few or too many times
- Fail to pass along any necessary environment/parameters
- Swallow any errors/exceptions that may happen
Promise has 3 states:
- pending: initial state, neither fulfilled nor rejected.
- fulfilled: meaning that the operation completed successfully.
- rejected: meaning that the operation failed.
Plug a function receiving resolve
and reject
as arguments into the Promise
constructor.
function test(){
return new Promise((resolve, reject) => {
setTimeout(()=>resolve('resolved'), 2000)
})
}
const foo = test()
foo.then(msg=>console.log(msg)) // logs "resolved"
then
can take in two functions as its parametersβthe former for resolve
, and the latter for reject
.
p.then(
(value)=>{
// value from resolve.
},
(error)=>{
// probably error object was passed from reject
}
)
or you can use catch
:
p
.then((val) => console.log("fulfilled:", val))
.catch((err) => console.log("rejected:", err))
all
: waits for all promises inside the iterable object (array) to be fulfilled or at least one of them to be rejected.race
: waits until any one of the promises inside the iterable object rejects or resolves. These methods of course return aPromise
.
async
and await
are ES8 (2017) syntax.
The async
function:
- the declaration, namely:
async test(){...}
becomesAsyncFunction
object. - it operates asynchronously via the event loop, using an implicit Promise to return its result.
- it returns a promise resolved with the value returned by the function, or rejected with an uncaught exception thrown from within the function.
- if it returns something other than a promise, it will be wrapped automatically into a resolved promise with the value in it:
- can have
await
keyword inside.
The await
keyword:
-
waits for the promise to be fulfilled. It pauses the execution of the async function. Once itβs got the value, it resumes execution.
-
is only valid inside
async
function:function test(){ // syntax error because of no async keyword await new Promise((resolve,reject)=>resolve(1)) }
-
This also means that:
async function test() { console.log(1) console.log(await someAsyncJob()) console.log(2) }
This code will give you something like
1 [result from someAsyncJob()] 2
because we pause the execution of the function.
This code:
console.log('a') test(); console.log('b')
will output:
a 1 b [result from someAsyncJob()] 2
because we are not
await
ing the promise returned bytest()
. To wait at the outer level, you could do (actually in the newst spec, you don't have to write top level async, but just for the sake of fundamentals, I'm just gonna write it like this):(async () => { console.log('a') await test(); console.log('b') })();
Then it is going to give you:
a 1 [result from someAsyncJob()] 2 b
because you stop in the middle by using
await
.Then another question: javascript is single-threaded. Then how could you even pause and run another thing like
console.log
? That's going to be answered in the next question.
β
Explain how await
can pause the execution of a function and still run other tasks although it is single-threaded
So, we talked about this in the above question:
async function a(){
console.log(1)
console.log(await fetch('https://baconipsum.com/api/?type=meat-and-filler'))
console.log(2)
}
console.log(0)
a();
console.log(4)
the output is, of course,
0
1
4
[whatever the result is from fetch]
2
Then ok. Javascript is single threaded. So how can you wait on another function and still execute statements in the outer scope?
job queue does the work. In other words, event loop (named in the browser likewise).
what....? ok. let me explain. Javascript implements run-to-completion model. This just means: Each message is processed completely before any other message is processed..
A simplified model of javascript runtime looks like this (from MDN docs):
- A queue (job queue) is a list of messages to be processed.
- Each message associates with a function to be called.
- the runtime will handle messages from the oldest one by taking the message out of the queue and calling it.
- the runtime will do it until the stack is empty. Then it will process the next message in the queue again.
So..
async function a(){
console.log(1)
console.log(await fetch('https://baconipsum.com/api/?type=meat-and-filler'))
console.log(2)
}
~ other codes ~
a();
~ other codes ~
console.log('other codes');
In this code,
- the main thread runs
console.log(0)
- the main thread finds that
await fetch('https://baconipsum.com/api/?type=meat-and-filler')
is an async operation, so it adds this callback to the job queue (instead of adding it to the end of the call stack) - the browser will run
~ other codes ~
belowa()
because they are synchronous. - once
fetch
gets the result back, the async callback in the job queue gets into the call stack (by callback, don't be confused. maybe think of this way:fetch('https://baconipsum.com/api/?type=meat-and-filler').then((a) => callback(a))
), which actually in this case is justconsole.log
. And this gets executed. console.log(2)
goes into the main stack and gets executed by the event loop
One more thing to remember:
- Promises get higher priority than callback queues. In other words, setTimeout executes lather than a promise.
Sources
- https://blog.bitsrc.io/understanding-asynchronous-javascript-the-event-loop-74cd408419ff
- https://flaviocopes.com/javascript-event-loop/
- https://hashnode.com/post/task-queue-and-job-queue-deep-dive-into-javascript-event-loop-model-cjui19qqa005wdgs1742fa4wz
- https://medium.com/@chaudharypulkit93/how-does-nodejs-work-beginner-to-advanced-event-loop-v8-engine-libuv-threadpool-bbe9b41b5bdd
- https://itnext.io/javascript-promises-and-async-await-as-fast-as-possible-d7c8c8ff0abc
- https://stackoverflow.com/questions/51007636/how-javascript-single-threaded-and-asynchronous
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Event_loop
Note: this is a very confusing topic and lots of people say different terms for the same things and so on. It is VERY confusing. Study this hard.
β Are event loop and job queue the same thing?
- Event loop: According to MDN docs: event loop waits for a new message to arrive and processes the next message. In other words, it runs continuously and checks if the main stack has any frames left to execute. If not, it looks at the callback queue to see if it has any callbacks to execute too.
- Callback queue (sometimes called event loop queue): async callbacks other than promises (ex.
setTimeout
) - Job queue: for all async callbacks using promises
So.. no. They are not the same things.
π§ Is it valid to say that javascript is single-threaded?
β
Explain the difference between undeclared vs undefined
vs null
and how to check for each of them in code.
Undeclared variables:
- are created when you assign a value to an identifier that is not previously created using
var
,let
orconst
. - are defined globally (regardless of scope)
- causes a
ReferenceError
instrict
mode.
undefined
variable:
- is a variable that has been declared, but not assigned a value.
typeof <an undefined variable>
returns'undefined'
.
null
variable:
- needs to be explicitly assigned a
null
value - pitfall:
typeof null
returnsobject
.
β
Explain the difference between ==
and ===
.
==
operator compares two sides with type conversion if needed.===
operator compares two sides without type conversion (strongly recommneded).
To know what's true
and what's not, just look into the table from https://dorey.github.io/JavaScript-Equality-Table/:
Notice that the table for ===
comparison is crystal clear. There's no reason not to use this.
β
Explain the order of execution between type conversion and calculation. e.g. what is the answer of 3+2+"7"
and 3+"7"+2
and "7"+3+2
?
3+2+"7"
: "57"
3 + 2 = 5
5 + "7" = "57"
3+"7"+2
: "372"
3 + "7" = "37"
"37" + 2 = "372"
"7"+3+2
: "732"
"7"+3 = "73"
"73" + 2 = "732"
Moral:
- Addition operations containing a mix of
number
s andstring
s will outputstring
. - When javascript engine faces a
number
and astring
added together, it will thenumber
intostring
to concatenate the two. e.g.1+"st" = "1st"
β
Explain how you could deal with a var
variable in a for loop to have it reset every loop: e.g. for(var i = 0; i < 10; i++){ setTimeout( ()=>console.log(i), i*1000 ) }
The problem is that there is only one variable created in the scope of for
loop. Then the i
inserted inside the callback of setTimeout
is only from one variable. At the end of the loop, i
would be come 10
, and then console.log(i)
would naively output ten lines of of 10
.
let
simply creates a new scope for every loop.
for(let i = 0; i < 10; i++){
setTimeout(()=>{
console.log(i)
}, i * 1000)
}
Similarly, IIFE would allow you to create a new scope for every loop.
for(var i = 0; i < 10; i++){
(function(j){
setTimeout(()=>{
console.log(j)
}, j*1000)
})(i)
}
This problem is kind of pre-ES6; from ES6 on, this should not be a problem at all because you could simply use let
and never use var
. Personally, I never find a situation to use var
.
Explain javascript design patterns: most prominently, Singleton, Observer, Factory.
Ensures a class has only one instance and provide a global point of access to it.
const mySingleton = (function () {
// Instance stores a reference to the Singleton
let instance;
function init() {
// Singleton
// Private methods and variables
function privateMethod(){
console.log( "I am private" );
}
let privateVariable = "Im also private";
let privateRandomNumber = Math.random();
return {
// Public methods and variables
publicMethod: function () {
console.log( "The public can see me!" );
},
publicProperty: "I am also public",
getRandomNumber: function() {
return privateRandomNumber;
}
};
};
return {
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance: function () {
if ( !instance ) {
instance = init();
}
return instance;
}
};
})();
const singleA = mySingleton.getInstance();
const singleB = mySingleton.getInstance();
console.log( singleA.getRandomNumber() === singleB.getRandomNumber() ); // true
- An object (known as a subject) maintains a list of objects depending on it (observers), automatically notifying them of any changes to state.
- When a subject needs to notify observers, it broadcasts a notification to the observers.
- When a subject does not need an observer anymore, it can remove it from the list of observers.
class ObserverList{
constructor(){
let observerList = []
this.get = () => observerList
}
add(obj){
return this.get().push(obj)
}
count(){
return this.get().length;
}
getObserverAt(index){
if( index > -1 && index < this.get().length ){
return this.get()[ index ];
}
}
indexOf(obj){
return this.get().findIndex(ob=>ob===obj)
}
removeAt(index){
return this.get().splice(index, 1)
}
}
class Subject{
constructor(updateFunc){
let observers = new ObserverList()
this.get = () => observers
this.update = updateFunc
}
addObserver(observer){
this.get().add(observer)
}
removeObserverAt(index){
this.get().removeAt(index)
}
notify(context){
this.get().forEach(observer => this.update(context))
}
}
- Factory provides a generic interface for creating objects specified with the type of factory object.
- e.g. UI factory creates different types of UI components. You don't need
new
operator. You inform the Factory the type (e.g "Button", "Panel") and it instantiates this, returning it to us for use.
const Animal = function(name){
const animal = {};
animal.name = name;
animal.walk = function(){
console.log(this.name + " walks");
}
return animal;
};
See more at:
β How does prototypal inheritance work?
- All JavaScript objects have a prototype property, that is a reference to another object. When a property is accessed on an object and if the property is not found on that object, the JavaScript engine looks at the object's prototype, and the prototype's prototype and so on, until it finds the property defined on one of the prototypes or until it reaches the end of the prototype chain. This mimics inheritance in other languages.
- The top-end of every normal
[[Prototype]]
chain is the built-in Object.prototype. This object includes a variety of common utilities used all over JS:constructor: f constructor() hasOwnProperty: Ζ hasOwnProperty() isPrototypeOf: Ζ isPrototypeOf() propertyIsEnumerable: Ζ propertyIsEnumerable() toLocaleString: Ζ toLocaleString() toString: Ζ toString() valueOf: Ζ valueOf()
const linked = Object.create(obj)
creates an objectlinked
linked toobj
.- "Inheritance" implies a copy operation, and JavaScript doesn't copy object properties (natively, by default). Instead, JS creates a link between two objects, where one object can essentially delegate property/function access to another object.
- You don't create multiple instances of a class. You can create multiple objects that
[[Prototype]]
link to a common object.
The diagrams suggest somewhere in the code Bar extends Foo
was present.
Here in the picture, a1
, a2
, b1
, and b2
are instances of Foo
and Bar
respectively. Note that instances in javascript point back to [[Prototype]]
and then [[Prototype]]
's [[Prototype]]
. In contrast, in other normal languages,
See more at:
β
Explain the difference among forEach
vs for ... in
vs for ... of
vs map
.
forEach
does NOT return anything from the callback. If you want to, you should use map
.
[..].forEach(elem, index, arr) => {...})
Creates a new array with the results of calling a provided function on every element in the calling array.
const mappedArray = [..].forEach(elem, index, arr) => {...})
The for...of statement creates a loop iterating over iterable objects, including: built-in String, Array, Array-like objects (e.g., arguments or NodeList), TypedArray, Map, Set, and user-defined iterables. DOES NOT loop over objects.
for (let value of [1,2,3]) {
console.log(value);
} // 1 2 3
The for...in statement iterates over all non-Symbol, enumerable properties of an OBJECT.. Normally used to iterate over the keys of object (Alternative: Object.keys(obj).forEach(key=>{...}
))
obj = {
[Symbol()]: 1,
test: 2,
hi: 3
}
for(let key in obj){
console.log(obj[key])
} // outputs 2 3
obj.propertyIsEnumerable('test') // true
obj.propertyIsEnumerable(Symbol()) // false
See more at:
β Explain the difference between jsonp vs ajax.
When requesting a resource from another domain that is not under our control from a web application, we may be presented with a message Failed to load resource: Origin * is not allowed by Access-Control-Allow-Origin..
This means that the browser is blocking our request to access a given resource - the resource being an API endpoint.
- Cross-Origin Resources Sharing (CORS) is a security protocol implemented by browsers.
- By default, web browsers do not allow AJAX requests to servers other than the site youβre visiting. This is called the same-origin policy and itβs an important part of the web security model. You never know what those servers will send back
- It allows resources to be shared coming from a variety of origins.
- domain1.com is said to make a cross-origin request when it accesses a resource from domain2.com (the resource being an image, a CSS file or anything else).
JSON with padding.
- can avoid CORS errors
- only applies to
GET
methods - cannot handle errors (either CORS or 404 error). Cannot handle using
catch
. - exposes CSRF (Cross-Site Request Forgery) vulnerabilities.
- normally you don't write the script tag yourself (you use jQuery)
JSONP works like this (schier provided a great explanation for this):
- create a function in the global space to handle the JSON returned from the API.
function myCallbackFunction(data) {
console.log(data);
}
- create a new
<script>
tag usingwindow.createElement()
- set the
src
attribute to the desired JSONP endpoint
<script src="http://cool-stuff.com/api.json?callback=myCallbackFunction"></script>
- add the
<script>
to the<head>
of the DOM (or any valid tags, like<body>
) - the API endpoint returns the JSON wrapped (Padded) with the name of the callback:
myCallbackFunction({'awesome': 'data'});
- The callback is immediately executed since it's inside a script tag.
myCallbackFunction
gets called and logs{'awesome': 'data'}
.
See more at:
- https://blog.fullstacktraining.com/why-jsonp-shouldnt-be-used/
- https://mobilejazz.com/blog/which-security-risks-do-cors-imply/
- https://blog.fullstacktraining.com/what-is-cors/
- https://stackoverflow.com/questions/10193085/confused-on-how-a-jsonp-request-works
- https://schier.co/blog/2013/09/30/how-jsonp-works.html
- https://lucybain.com/blog/2015/how-does-jsonp-work/
β
Explain the difference between 'DOMContentLoaded'
vs 'load'
- The
DOMContentLoaded
event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading. - The
load
event is fired when the whole page has loaded, including all dependent resources such as stylesheets images.
See more at:
β
Explain the difference between ()=>{}
and function(){}
in relation to binding.
Before arrow functions, every new function defined its own this value based on how the function was called. But an arrow function does not have its own this
. The this
value of the enclosing lexical scope is used; arrow functions follow the normal variable lookup rules. So while searching for this
which is not present in current scope, an arrow function ends up finding the this
from its enclosing scope.
Pre-ES6:
function Person() {
// The Person() constructor defines `this` as an instance of itself.
this.age = 0;
setInterval(function growUp() {
// In non-strict mode, the growUp() function defines `this`
// as the global object (because it's where growUp() is executed.),
// which is different from the `this`
// defined by the Person() constructor.
// this will not work as intended
// resulting in: undefined++; which is nothing
this.age++;
}, 1000);
}
var p = new Person();
The 'that' fix in pre-ES6:
function Person() {
var that = this;
that.age = 0;
setInterval(function growUp() {
// The callback refers to the `that` variable of which
// the value is the expected object.
that.age++;
}, 1000);
}
ES6:
function Person(){
this.age = 0;
setInterval(() => {
this.age++; // |this| properly refers to the Person object
}, 1000);
}
var p = new Person();
'use strict';
var obj = {
i: 10,
b: () => console.log(this.i, this),
c: function() {
console.log(this.i, this);
}
}
obj.b(); // prints undefined, Window {...} (or the global object)
obj.c(); // prints 10, Object {...}
See more at:
β
Explain the usage of static
keyword in class
class ClassWithStaticMethod {
static staticMethod() {
return 'static method has been called.';
}
}
console.log(ClassWithStaticMethod.staticMethod());
// expected output: "static method has been called."
It's just the same as other languages.
See more at:
β Explain event bubbling and capturing.
Event bubbling and capturing(trickling) are two different ways of event propagation in HTML DOM API.
- bubbling: event captured by the innermost element and propagates to outer elements
- capturing: event captured by the outermost element and propagates to inner elements
You can actually specify whether you want to use capturing in the third parameter (default is false
): addEventListener(type, listener, useCapture)
See more at:
β Explain how javascript works on the browser (memory heap, call stack, event loop, callback queue, gc, web APIs...)
- A compiled program is not human readable, but instead is in an architecture-specific machine language.
- In an interpreted program, on the other hand, the source code typically is the program. Programs of this type (often known as scripts) require an interpreter, which parses the commands in the program and then executes them.
- The advantage of a script is that it is very portable. Any computer that has the appropriate interpreter installed may run the program more or less unchanged. This is a disadvantage as well, because the program will not run at all if the interpreter is not available. In general, interpreted programs are slower than compiled programs, but are easier to debug and revise.
Eh. Both-ish. This is what Stanford javascript course says: JavaScript is an interpreted language, not a compiled language.
- C++ or Java need to be compiled before it is run. Compiler translates the code into bytecode that the machine understands and can execute.
- Javascript has no compilation step. The interpreter in the browser reads the code, interprets each line, and runs it. More modern browser javascript runtimes (including V8) use a technology known as Just-In-Time (JIT) compilation, which compiles JavaScript to executable bytecode just as it is about to run.
The javascript runtime largely consists of:
- The javascript engine - Memory heap: memory allocation happens here - Call stack: stack frames (each entry in the call stack, probably a function) are executed here.
- Web APIs provided by the browser
- DOM
- Basic methods like
setTimeout
- Callback queue
- Methods like
onClick
,onLoad
, ... - Event loop
- JavaScript automatically allocates memory when objects are created and frees it when they are not used anymore (garbage collection).
- There are two types of GC: reference-counting and mark-and-sweep.
- Reference-counting: An object is said to be "garbage", or collectible if there are zero references pointing to it:
const x = {
a: {
b: 2
}
};
var y = x; // The 'y' variable is the second thing that has a reference to the object.
x = 1; // Now, the object that was originally in 'x' has a unique reference
// embodied by the 'y' variable
var z = y.a; // Reference to 'a' property of the object.
// This object now has 2 references: one as a property,
// the other as the 'z' variable
y = 'mozilla'; // The object that was originally in 'x' has now zero
^^^^^^^^^^ // references to it. It can be garbage-collected.
this part // However its 'a' property is still referenced by
// the 'z' variable, so it cannot be freed
- Limitation for reference-counting: circular references. Circular references inside a certain scope will not be needed anymore once the scope is gone. However reference-counting algorithm will not free the memory allocated for the circular references because memory locations are still pointing to each other.
- Mark-and-sweep: Improved version of reference-counting method. reduces the definition of "an object is no longer needed" to "an object is unreachable". In JavaScript, the root is the global object. GC, starting from the root, finds all objects referenced from it, then all objects referenced from this, etc. The GC will thus find all reachable objects and collect all non-reachable objects.
- As of 2012, all modern browsers ship a mark-and-sweep garbage-collector.
- Javascript has one thread, and thus one call stack. It can do only one thing at a time.
- What happens when a function call in a call stack takes a lot of time to be processed?: 1. the browser canβt do anything else β itβs getting blocked. It does not render/run other codes. 2. It may stop being responsive, asking you if you want to wait or leave. So how do we get around with this? Asynchronous callbacks.
const bar = () => console.log('bar')
const baz = () => console.log('baz')
const foo = () => {
console.log('foo')
setTimeout(bar, 0)
baz()
}
foo()
This will output
foo
baz
bar
Because: When setTimeout()
is called, the Browser or Node.js starts the timer. Once the timer expires, in this case immediately as we put 0 as the timeout, the callback function is put in the callback queue.
- A process that checks the call stack and then trigger the callback queue continuously (if the stack's empty).
See more at:
- https://www.valentinog.com/blog/engines/
- https://codeburst.io/js-essentials-the-javascript-engine-302ff38e8465
- https://kb.iu.edu/d/agsz
- https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf (pictures source)
- https://blog.sessionstack.com/how-javascript-works-inside-the-v8-engine-5-tips-on-how-to-write-optimized-code-ac089e62b12e
- https://flaviocopes.com/javascript-event-loop/
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
β Explain the limitation of floating point number system in javascript.
In JavaScript all numbers are IEEE 754 floating point numbers. Due to the binary nature of their encoding, some decimal numbers cannot be represented with perfect accuracy.
- s: the sign of the number. 1 means negative, 0 positive.
- F: the fraction (also called mantissa)
- E: the exponent.
It consists of bits for different parts:
Example: -1.23 * 10^56
- Floating-point numbers are represented as binary (base 2) fractions. Most decimal fractions cannot be represented exactly as binary fractions. Example:
0.2 + 0.1 = 0.30000000000000004
- Sometimes you also lose precision:
99999999999.0123 + 0.00231432423 = 99999999999.01462
- Use
Number.EPSILON
, the difference between 1 and the smallest floating point number greater than 1.
0.2+0.1-0.3 // this is actually 5.551115123125783e-17
equal = (Math.abs(0.2+0.1-0.3) < Number.EPSILON) // is 5.551115123125783e-17 negligible (caused by the nature of floating point numbers)
equal // true
See more at:
- https://hackernoon.com/understanding-the-problem-javascript-maths-2119d85dad2a
- https://www.doc.ic.ac.uk/~eedwards/compsys/float/
- https://medium.com/coderscorner/floating-point-representation-63114653c9ee
- https://www.avioconsulting.com/blog/overcoming-javascript-numeric-precision-issues
- https://medium.com/@sarafecadu/64-bit-floating-point-a-javascript-story-fa6aad266665
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON
β
Explain map
and reduce
.
map
: maps array elements to something else through a function.
[...Array(10)].map((elem, index, array) => index) // 0 1 2 3 4 5 6 7 8 9
reduce
: reduces array elements to a single value.
const initialValue = 15
[...Array(10)]
.map((elem, index, array) => index)
.reduce((accumulator, currentValue, currentIndex, array) => {
const calc = accumulator + currentValue
console.log(calc) // 15 16 18 21 25 30 36 43 51 60
return accumulator + currentValue
}, initialValue)
See more at:
β Explain the use of javascript profiler.
I wrote an entire article on it. Check it out: https://medium.com/swlh/learn-major-functionalities-on-chromes-performance-tab-and-practice-it-with-a-simple-react-project-98e0306aa7
See more at:
β Explain main features of React.
- Uses VirtualDOM.
- In React, you have VirtualDOM and DOM. For every DOM object, there is a corresponding βvirtual DOM object, like a lightweight copy. Manipulating the DOM is slow. Manipulating the virtual DOM is much faster, because nothing gets drawn onscreen. Think of manipulating the virtual DOM as editing a blueprint, as opposed to moving rooms in an actual house.
- The entire virtual DOM gets updated on
render
. - The virtual DOM gets compared to the snapshot taken right before the update. React figures out which objects have changed.
- Only the changed objects get updated on the real DOM.
- Changes on the real DOM cause the screen to change.
- Supports server-side rendering
- SSR is the ability of a JavaScript application to render on the server rather than in the browser. (Means for every single webpage the user would need to request a whole new HTML file from the server. In essence, you would not need
bundle.js
to render components because they already are rendered) - it allows your site to have a faster first page load time, which is the key to a good user experience
- Better for SEO: search engines cannot efficiently & correctly index applications that exclusively render client-side although Google limitedly can.
- SSR is the ability of a JavaScript application to render on the server rather than in the browser. (Means for every single webpage the user would need to request a whole new HTML file from the server. In essence, you would not need
- Follows Unidirectional data flow or data binding.
- Data has only one way to be transferred to other parts of the application.
- Any data thatβs affected by this state can only affect Components below it: its children.
- Changing state on a Component will never affect its parent, or its siblings, or any other Component in the application: just its children.
- You can know where the state change initiated, but you have to start from the root component to notify other components of the state change (redux takes a different approach. See Redux section for more)
- The parent component(s) will have a container for the state of your app (typically an immutable variable called state, unless you are using Redux or Flux, in which case you would encapsulate your appβs state in a store). The parent component typically passes down a snapshot of its state to its child components via read-only props and then the child components can communicate with the parent to update the state via callbacks which are bound to a button or form in the child component.
- Data has only one way to be transferred to other parts of the application.
- Uses reusable/composable UI components to develop the view.
See more at:
- https://reactjs.org/docs/faq-internals.html
- https://www.codecademy.com/articles/react-virtual-dom
- https://flaviocopes.com/react-server-side-rendering/
- https://flaviocopes.com/react-unidirectional-data-flow/
- https://medium.com/@alialhaddad/https-medium-com-alialhaddad-redux-vs-parent-to-child-2583c8e29509
- https://medium.com/@lizdenhup/understanding-unidirectional-data-flow-in-react-3e3524c09d8e
β Explain JSX.
Javascript XML. XML-like syntax extension for javascript. It is a syntactic sugar for React.createElement()
.
β
What is React.PureComponent
? How can you use it in a code and why would you?
It is exactly the same as React.Component
except it handles shouldComponentUpdate
instead of you. PureComponent
will do a shallow comparison on both props and state on a prop/state change.
Its shouldComponentUpdate
method looks like this:
return (
!shallowEqual(oldProps, newProps) ||
!shallowEqual(oldState, newState)
);
This means:
If the props and the state hasnβt changed, the component is not re-rendered.
- Both functional-based and class-based components have the same downside: they always re-render when their parent component re-renders even if the props donβt change.
- Also, class-based components always re-render when its state is updated (this.setState is called) even if the new state is equal to the old state.
- Moreover, when a parent component re-renders, all of its children are also re-rendered, and their children too, and so on.
You use it with a class
.
class ImPure extends PureComponent {
render(){
<h1>hi</h1>
}
}
See more at:
π§ Why should you bind methods in React class component and how can you do it?
π§ Why would you use ref
and how can you do it?
π§ Explain phases of a component lifecycle.
π§ Explain React hooks, and why and how you would use one.
π§ What is Context in React?
π§ What is the purpose of super
in React class
component's constructor?
π§ Explain how you could lazy import.
π§ What is a portal in React?
π§ How can you catch errors in React?
π§ What is dangerouslySetInnerHTML
in React?
β
Why do we need to use a function in setState
?
Because setState
is asynchronous. The state may not change immediately after setState() is called. That means you should not rely on the current state when calling setState()βsince you can't be sure what that state will be. The solution is toβpass a function to setState(), with the previous state as an argument.
// assuming this.state.count === 0
this.setState({ count: this.state.count + 1 })
this.setState({ count: this.state.count + 1 })
this.setState({ count: this.state.count + 1 })
// this.state.count === 1, not 3
this.setState((prevState, props) => ({
count: prevState.count + props.increment
}))
// this.state.count === 3 as expected
Explain web page redirection methods.
β Explain ASCII, Unicode, UTF-8, and base64
- | ASCII | UTF-8 | UTF-16 | base64 |
---|---|---|---|---|
bit/bytess used | 7 bits (later 8 bits) | 1~6 bytes as the code point increases. UTF-8 is named with 8 because it uses at least 8 bits (or 1 byte) to store the unicode code-points. | Mostly uses 16 bits (or 2 bytes) to encode every character and 32 bits for unusual ones. | 6 bits |
used for | Representing numbers from 0-9, the upper and lower case English letters from A to Z, and some special characters. | Representing every character in every imaginable language systems + numbers + special characters | Mostly the same with UTF-8 | Encoding binary data in ASCII text. Say you want to transfer binary data over a medium. Some media are made for transferring text only, so you cannot transfer bits--you need to encode them because you don't know what is going to happen if you put in bits in there (ex. the medium may interpret your message as a special character). So you convert them into ASCII text first to send. |
backwards compatible with ASCII (superset of ASCII?) | - | O | X | base64 IS made of ASCII. |
- Is not a set of characters. It's just an abstract concept.
- An attempt to create a single character set that could represent every characters in every imaginable language systems
- Assigns each character with a unique number (aka code point)
See more at:
- https://stackoverflow.com/questions/643694/what-is-the-difference-between-utf-8-and-unicode
- https://en.wikipedia.org/wiki/ASCII
- https://medium.com/@apiltamang/unicode-utf-8-and-ascii-encodings-made-easy-5bfbe3a1c45a
- https://en.wikipedia.org/wiki/Comparison_of_Unicode_encodings
- https://stackoverflow.com/questions/130438/do-utf-8-utf-16-and-utf-32-differ-in-the-number-of-characters-they-can-store
- https://stackoverflow.com/questions/201479/what-is-base-64-encoding-used-for
π§ Explain the usage of CDN.
π§ Explain why reflow happens and how to prevent it
See more at:
β Explain pros and cons of typescript
Seriously I've researched on Google for a while about downsides of typescript but they were all trying to make something up, like the things that you are already aware of and that we don't really care about... (like 'additional build step required' (yeah I know, of course...) or 'learning curve'...) What the heck. See the image below for reference.
If you can use typescript, do so. There's no way it's going to give a bad effect on your project.
Pros? Everything. Explain everything that the language offers to you. Compare it with javascript.
π§ Explain why front end is going functional
π§ Explain AMP
π§ Explain WebWorker
π§ Explain IndexedDB
π§ Explain PWA
β Explain WebAssembly
- WebAssembly is NOT C++.
- Web stack based virtual machine. It is a processor that does not actually exist, but it helps compile real complex architectures.
- When you write code in whatever language, compile it to WebAssembly (through what is called emscripten), then code compiles to the instruction set of the target machine(x86, ARM, ...) in
wasm
format. - Virtual machine is designed to compile to real processors. So it can run on any runtimes. You are running the code on the bare metal (securely).
- Even AutoCAD now can runs on browser! Unity too. The browser has an ability to run all this. UI Toolkit QT also supports WebAssembly.
- emscripten. It's a drop-in replacement for the C/C++ compilers. Instead compiling to machine code, it gives you WebAssembly. Whatever code you wrote to run on a system should magically happen to run on the web too. emscripten does a LOT. Origianlly it was the compiler of
asm.js
(another project that would compile C code into javascript to run programs faster). emscripten even pretends to use OpenGL by using WebGL and real file system by using virual things. You can run the code that was never made for the web! - When WebAssembly came out, emscripten just added a new output format but kept all the work for the emulation. It was an accidental match with WebAssembly. It was so fit. There was no problem. Perhaps that's why C++ is so tightly involved with WebAssembly.
- Not for every topic, javascript ecosystem is big, while other languages' may be.
- So you choose to either make yourself a javascript port if you don't find one in javscript, or resort to using other languages.
- "Sqoosh". An image compression app written in javascript only. No server. Developers found that the ecosystem for image codecs and encoders was not so big in javascript, so they looked at C/C++. So? WebAssembly. They found some module in C++ and replaced it with the browser's encoder. Improvements were gained.
- So now, ecosystems are not limited to a language anymore, with WebAssembly. You can now take something that was not used for the web to use it for the web, through emscripten and WASM.
- Compiling the library
- Define functions that you want to use in javascript (bridge functions)
- Run
emcc
(emscripten C compiler) - Then you get
.cpp
,.js
, andwasm
. Note, because emscripten does a lot of job under the hood, always check the file size.
If you have a gap in the web platform (javascript) that has been already filled many times in another language, WASM might be your tool!
- Javascript & WASM are both equally fast as of now.
- But it is easier for you to configure WASM to be faster (because it knows what to do, but you writing a javascript code may not know how you could optimize your code)
- WASM is looking into things like multiple threads and simd -- things javascript will never get access to. Then we can expect it to outperform javascript.
JS: JS file => Ignition (V8 intepretor) => TurboFan(optimizing compiler to generate machine code)
WASM: WASM file => Liftoff (WASM compiler) => TurboFan(optimizing code)
See the difference?
- Ignition is an interpretor, and WASM is a compiler (generates machine code). On average, machine code would be faster.
- But one more thing: the machine code may have to fall back to interpretor (called de-optimization) because not always the machine code is right, for it is making certain assumptions. But it's not the case for WASM (much faster, never de-opted).
- It delievers faster and more predictable performance. This is important because sometimes javscript works at very different rates in different browsers!
- AssemblyScript is a Typescript to WASM compiler. You cannot just throw in the code into WASM because for ex, it does not have a DOM API.
- It uses a perfect Typescript syntax with a different type library! You don't have to learn a new language to write WASM.
- For now, WASM does not have a built-in GC algo. You have to free the memory yourself.
- Putting everything into WASM is not a good idea for now
- JS vs WASM are not opponents. They have things to complement eachother. Find the place where WASM fits in right!
These are current proposals.
- Threads for parallel computation. Why? Many existing libraries in C/C++ work in multi-threads. Performance generally scales with multi-threads. Match on the web? There's Web Worker on the web! Currently stable. It has to formalize things a bit. Threads are shipped in Chrome 74 by default!
- Reference types. WASM can pass around arbitrary JS codes using the 'any' ref value type. WASM may run fundamental JS codes with this.
- WebIDL Binding proposal. It is used to define interfaces that are implemented on the web.
- GC, Exception handling, ....
See more at:
β Explain the significance and details of REST
REST = Representational State Transfer. Concept first developed by Roy Fielding. He speaks of 6 guiding constraints for an interface to be called RESTful.
- Client & Server must be able to evolve separately without depending on each other.
- Everything the client needs to know about is the resource URI.
- Request from client to server contains all information necessary to understand the request.
- Each request is independent of one another.
- Session state is kept entirely on the client.
- Data inside a response have to be either cacheable/non-cacheable.
- Cacheable means the client can use the data again for later requests.
- Identification of resources: you use URI standard to identify a resource (web page). This just means the request needs to include a resource identifier.
- Manipulation of resources through these representations:
- The response the server returns include enough information so the client can modify the resource
- This means you don't need to a client does not need to run a SQL query against the server's database table.
- You just need to run an HTTP GET to retrieve a piece of information (for example, get an user id). This info can be again used to delete/update/... the information.
- Self-descriptive messages:
- Request to API contains all information the server needs
- Response from the server contains all information the client needs
- Hypermedia as the engine of the application state(HATEOAS):
- The server can inform the client of the ways to change the state of the web application.
- If the client asked for a specific user, the server can provide not only the state of that user but also information about how to change the state of the user, for example how to update the userβs name or how to delete the user.
- Ex. Server returning a response in HTML format to a browser (which is the client). It will include tags with links (hypermedia part) to another web page where the user can be updated (for example a link to a βprofile settingsβ page).
- Client should only know the immediate layer it is communicating with, and that will be enough.
- The server may have: security/caching/load-balancing/... layers. These should not affect the request/response. The client is agnostic about the existence of these additional layers.
See more at:
- https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html (Korean)
- https://midnightcow.tistory.com/102 (Korean)
- https://restfulapi.net/
- https://stackoverflow.com/questions/25172600/rest-what-exactly-is-meant-by-uniform-interface
- https://medium.com/extend/what-is-rest-a-simple-explanation-for-beginners-part-2-rest-constraints-129a4b69a582
- https://restful.io/objects-at-rest-part-1-what-is-it-3e26f0978616
- https://www.kennethlange.com/what-are-restful-web-services/
β Explain OSI layers.
The OSI (Open Systems Interconnection) Model is:
a conceptual model that standardises the communication of a computing system without regard to its internal structure
a tool used by IT professionals to model or trace flow of data transfer in networks.
- can divide large data exchange process in smaller segments (layers).
- standardized network components -> can do multiple vendor development
- End-user interacts with this layer
- Examples: anything that an end-user can directly use for a network connection.
- network protocols directly provided to the user:
telnet
,ftp
,tftp
commands on cli - more broadly said: web browsers, mail services
- network protocols directly provided to the user:
-
formats the data to be presented to the application layer
-
translate data from a format used by the application layer into a common format at the sending station, then translate the common format to a format known to the application layer at the receiving station
-
Examples: format conversions and encryption / decryption
-
image formats: PNG, GIF, JPEG...
The focus of this layer is having a common ground to present data between applications. Billions of image files are transferred every day. Each of these files contains an image that ultimately will be displayed or stored on a computer. However, each image file must be the proper specified file format. This way, the application that reads the image file understands the type of data and the format contained in it.
-
text formats: ASCII, UNICODE...
-
audio formats: WAV, MP3, AIFF...
-
even HTML, Javascript, ...
file formats are 'translated'(or interpreted, by a web browser) to display images and text, and play audio.
-
password encrpytion on data
-
more broadly said: HTTP(S)
-
- maintainins communication by establishing, managing and terminating sessions between devices
- Examples:
- TCP/IP Sockets: you know they establish sessions.
- NETBIOS: allows applications on separate computers to communicate over a local area network. (strictly an API, not a protocol. One protocol for this is NETBIOS over TCP/IP)
- decides information sent at a time
- provides reliable process to deliver & recover data.
- Examples:
- TCP(Transmission control protocol) (three-way handshake). Sequence number identifies the order of the bytes sent from each computer so that the data can be reconstructed in order, regardless of any packet reordering, or packet loss. Acknowledgement are sent with a sequence number by the receiver of data to tell the sender that data has been received to the specified byte.
- UDP(User datagram protocol): speed over quality
-
moves packets from source to destination
-
routers work on this level -> IP address is also at this level
-
Example:
When you message your friend, this layer assigns source and destination IP addresses to the data segments. Your IP address is the source, and your friendβs is the destination. It finds the best path for delivery too.
- organises bits into frames and ensures hop to hop delivery
- switches at this level -> Adds sender and receiver MAC addresses to the data packet to form a frame (switches vs routers: switch is designed to connect computers within a network (local area network, LAN), while a router is designed to connect multiple networks together (wide area network, WAN))
- enables frames to be transported via local media (e.g. copper wire, optical fiber, or air), done@device's Network Interface Card
- transmission of data through a medium (a real, physical wire, electrical, light, or radio signal)
All People Seem To Need Data Processing
Illustrations from Plixer.com to grasp the concept in seconds
See more at:
β Explain HTTP/2 and distinguish it from HTTP/1.x
- Google started to develop SPDY in 2009 to address performance issues of HTTP/1.1 and brought a good result after a while
- HTTP-WG(Working group) started working on HTTP/2 based on SPDY, and was accepted as a de facto global standard for web in 2015, surpassing SPDY which is now obsolete.
- HTTP/2 does not modify the application semantics of HTTP in any way. All the core concepts, such as HTTP methods, status codes, URIs, and header fields, remain in place.
- Instead, HTTP/2 modifies how the data is formatted (framed) and transported between the client and server
- | 1.x | 2.0 |
---|---|---|
Stream | 1 connection per 1 stream | 1+ connections per 1 stream (response multiplexing). This greatly reduces latency. |
Stream priority | X | Can set a priority for each stream. A browser may put a higher priority on the stream that requests a more important resource. May be useful when connection is unstable. |
Header compression | X. Hundreds of requests may be sent to see a website. Uncompressed headers worsen latency and bandwidth. | Can compress headers according to HPACK specs. Latency reduced. |
Server push | X. | Server may send multiple resources in a response to a single request. For example, a server may in advance push stylesheets, images, javascript files to which an HTML document has links to when it receives a request for that single HTML document. |
See more at:
β Explain why you should use HTTPS and how it works.
It enforces three things: privacy, integrity, and authentication
Encrypting data such that anything in-between your browser and the website cannot read your traffic.
- Anybody can see what you are looking into over HTTP.
Ensuring that the data received on either end has not been altered unknowingly along the way.
- Plain, unencrypted messages can be caught in the middle, modified, and sent to the receiver (man-in-the-middle attack).
Proving that the website your browser is talking to is who they say they are.
- HTTPS, via SSL certificates, ensures you are connected exactly with the receiver you would expect.
See more at:
β Explain symmetric and asymmetric cryptography.
- There is only one key to encrypt and decrypt
- It's like putting the message in a box and locking the box with a key. Only the person that has a copy of the key can open the box and read the message.
- More technically, HTTPS uses SSL (Secure Socket Layer) with RSA algorithm to encrypt data.
- The key must be kept private. You should not share the key in plain text, or send it with the box.
- Problem with symmetric keys: hard to share. And this brings us to asymmetric keys.
-
You got 2 keys
-
One is public, the other private.
-
Public key can be shared anywhere.
A sends its public key to B B sends a message back, encrypting it with the public key A decrypts the message with his private key
-
Only the private key can open a box locked with the public key pair.
The server generates two large prime numbers, and multiplies them together. This is called the "public key". This key is made available to any client which wishes to transmit data securely to the server. The client uses this "public key" to encrypt data it wishes to send. Now because this is an asymmetric algorithm, the public key cannot be used to decrypt the transmitted data, only encrypt it. In order to decrypt, you need the original prime numbers, and only the server has these (the "private key"). On receiving the encrypted data, the server uses its private key to decrypt the transmission.
In the case of you browsing the web, your browser gives the server its public key. The server uses this key to encrypt data to be sent to your browser, which then uses its private key to decrypt.
β Explain HTTPS handshake (in relation to SSL/TLS)
The negotiation between a browser and a server, is called "the handshake".
- [CLIENT HELLO] CLIENT sends a list of SSL/LTS versions and encryption algorithms (called cypher suite) that it can work with the server.
- [SERVER HELLO 1] SERVER chooses the best SSL/TLS version and encryption algorithm based on its preferences.
- [SERVER HELLO 2] SERVER replies with its certificate (includes public key)
- [Client Key Exchange 1] CLIENT verifies legitimacy of the certificate.
- [Client Key Exchange 2] CLIENT generates a code-master key, encrypts it with the public key, a**nd sends it back to SERVER. The code-master key is a random byte string that enables both the client and the server to compute the secret key to be used for encrypting subsequent message.
- [Change Cypher spec 1] SERVER decrypts with its private key to get the code-master key.
- [Change Cypher spec 2] SERVER and CLIENT both generate the same 'shared secret' to use for subsequent messaging
- ["Finished"] CLIENT sends "finished" message encrypted with the secret key. SERVER decrypts it.
- ["Finished"] SERVER sends "finished" message encrypted with the secret key. CLIENT decrypts it.
- The SERVER and CLIENT can now exchange messages that are symmetrically encrypted with the shared secret key.
Illustration from SSL.com to help
See more at:
- https://stackoverflow.com/questions/3968095/how-does-https-provide-security
- https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.1.0/com.ibm.mq.doc/sy10660_.htm
- https://howhttps.works/the-handshake/
- https://medium.com/@kasunpdh/ssl-handshake-explained-4dabb87cdce
TLS is the new name for SSL. Namely, SSL protocol got to version 3.0; TLS 1.0 is "SSL 3.1". TLS versions currently defined include TLS 1.1 and 1.2. Each new version adds a few features and modifies some internal details. We sometimes say "SSL/TLS".
See more at:
β Explain why SSL/TLS are not safe anymore
IMPORTANT: as of February 2019, TLS v1.3 (state-of-art protocol) is no longer safe. More easily said: NOTHING IS SAFE.
- All SSL versions: vulnerable
- TLS 1.0: vulnerable
- TLS 1.1: vulnerable
- TLS 1.2: vulnerable
- TLS 1.3: now vulnerable.
Some known vulnerabilities: POODLE, BEAST, CRIME, BREACH, Heartbleed
See more at:
- https://kb.iweb.com/hc/en-us/articles/230268628-SSL-TLS-issues-POODLE-BEAST-SWEET32-attacks-and-the-End-of-SSLv3-OpenSSL-Security-Advisory
- https://www.acunetix.com/blog/articles/tls-ssl-cipher-hardening/
- https://www.zdnet.com/article/new-tls-encryption-busting-attack-also-impacts-the-newer-tls-1-3/
- https://kinsta.com/blog/tls-1-3/
- https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2019/february/downgrade-attack-on-tls-1.3-and-vulnerabilities-in-major-tls-libraries/
- https://securityboulevard.com/2019/02/security-researchers-discloses-vulnerabilities-in-tls-libraries-and-the-downgrade-attack-on-tls-1-3/
π§ Explain different types of wifi network encryptions: WEP, WPA, WPA2, WPA3.
β Explain the difference among PNG vs JPG vs Bitmap vs GIF
PNG | JPG(=JPEG) | BMP | GIF | |
---|---|---|---|---|
Name | Portable Networks Graphic | Joint Photographic Experts Group | Bitmap | Graphics Interchange Format |
Compression ratio (file size) | 10-30% | 10:1 ~ 100:1 | 1:1 (large) | 4:1 ~ 10:1 |
Loseless (compressed but no loss in quality) vs Lossy (more compressed and loss in quality) | Loseless | Lossy | Loseless | Loseless |
Support transparency (alpha) | O | X | O | O (partially) |
Color depths in bits (indexed vs direct palette) | 48 (= 281,474,976,710,656 colors) | 24 (= 16,777,216 colors) | 24 / indexed AND direct | 8 (= 256 colors) / indexed |
Animation | X | X | X | O |
Used for | Recommended for static graphics/icons | Photographs (small size, fairly good quality, many colors) | Almost nothing | Logos, line drawings, and other simple images that need to be small. |
See more at:
Explain how compression works. What's lossy and loseless compression?
- Exploits statistical redundancy to represent data without losing any information
- For example, an image with same red pixels: "red pixel, red pixel, ..." -> "279 red pixels"
- Drops unimportant details to save storage
- Examples: JPEG, DVD, Blu-ray
See more at:
β Explain the use of cache.
- is high-speed static random access memory (SRAM) that a CPU can access more quickly than RAM
- often located within the CPU or along with the bus connected with CPU
- holds frequently requested data and instructions immediately available to the CPU when needed.
- reduces the average time to access data from RAM
- Fast, smallest, embedded in CPU.
- Examples: accumulator, Program counter, address register
- Located between the CPU and the DRAM (sometimes within CPU)
- Larger than L1
- Larger and larger
- Speed, about double the RAM
cache
object would store the input num
as its key to store the output of the function. If there's a corresponding key in cache
, it would simply return the value matching the key. Otherwise result
would be calculated, stored in cache, and return
ed.
const createCacheFunc = () => {
let cache = {}
return function cacheFunc(num){
if(cache[num]){
console.log('from cache')
return cache[num]
}
else{
console.log('not from cache')
const result = num * 3 / 2 + 9
cache[num] = result
return result
}
}
}
const func = createCacheFunc()
console.log(func(2))
// not from cache
// 12
console.log(func(2))
// from cache
// 12
See more at: for Cache memory
- https://searchstorage.techtarget.com/definition/cache-memory
- https://www.webopedia.com/TERM/C/cache.html
- https://www.bbc.com/bitesize/guides/zmb9mp3/revision/3
- https://www.geeksforgeeks.org/cache-memory/
See more at: for Cache in programming
β Explain the difference between HDD and SSD.
SSD(Solid State Drive) | HDD(Hard Disk Drive) | |
---|---|---|
Implementation | better. Uses semiconductor chips to store data and have no moving parts. SSD is electronic. No moving parts. They read from flash modules. | Uses magnetic (spinning) platters and moving parts to store data (mechanical arm with a read/write head to move around and read information from the right location on a storage platter) Physical. Physical is slower than electronic. |
Physical size | better (Small) | Big |
Access time | better (0.1ms) | 5.5+ms |
Random io/s | better (6000) | 400 |
Failure rate | better (<0.5%) | <2+% |
Energy consumption | better (low) | high |
I/O Wait | better (1%) | 7% |
Request time (data access speed) | better (20ms) | 400+ms |
See more at:
β Explain the difference between DRAM vs SRAM.
DRAM(Dynamic Random Access Memory) | SRAM(Static Random Access Memory) | Reason | |
---|---|---|---|
Reason for the name | Dynamic means that it needs to be refreshed frequently. | Static means it does not need to be refreshed. | Random means any storage location can be accessed directly. (Tape-based memory is NOT random but serial: If you want a byte of memory in the middle of the tape, you have to start at one end of the tape and spool through to the location you want. Thatβs clumsy and slow.) |
Implementation | Simple. Uses capacitors & few transistors. 1 block of memory requires 1 transistor to store data. | Complex. Uses transistors & latches. 1 block of memory requires 6 transistors. | |
Speed | Low -> used for main memory (typical RAM in computers) | High -> used for cache memory | SRAM does not need to refresh (see power leakage section), it is typically faster. The average access time of DRAM is about 60 nanoseconds, while SRAM can give access times as low as 10 nanoseconds. + DRAM = off-chip vs SRAM = on-chip |
Cost | Low | High | Memory designers reduced the number of elements per bit and eliminated differential bit lines to save chip area to create DRAM. Since SRAM uses flip-flops, made of up to 6 transistors, it needs more transistors to store 1 bit than DRAM does. This increases the production cost of SRAM. |
Density | High | Low | DRAM's got less transistor per chip, so it can pack more cells into space. Opposite for SRAM. |
Power consumption | High | Low | DRAM: Capacitors leak power thanks to imperfect insulation, requiring regular power refreshes. SRAM: No charge leakage since it changes direction of current through switches instead of leaking power through the capacitor. However, this depends on the application environment and it can consume as much or more power as DRAM. |
Volatile | O | O | Any non-volatile memory must store its bits in two states which have a large energy barrier between them, or else the smallest influence would change the bit. Set it low 0 . 1 , and you get memory which can be rewritten a lot without generating a lot of heat: fast and volatile. Set the energy barrier high `0 |
Power leakage | O | X | DRAM needs to be refreshed or given a new electronic charge every few milliseconds to compensate for charge leaks from the capacitor. SRAM does not need to be refreshed because it operates on the principle of switching the current flow in one of two directions rather than holding a charge in place within a storage cell. |
See more at:
- https://techdifferences.com/difference-between-sram-and-dram.html
- https://www.diffen.com/difference/Dynamic_random-access_memory_vs_Static_random-access_memory
- https://searchstorage.techtarget.com/definition/DRAM
- https://www.atpinc.com/blog/computer-memory-types-dram-ram-module
- https://superuser.com/questions/638675/why-does-ram-have-to-be-volatile/638809
- https://www.enterprisestorageforum.com/storage-hardware/sram-vs-dram.html
π§ Explain the use of virtual memory.
See more at:
Explain the inner structure of apk
Explain GC in Android or iOS
Explain B+ tree.
Explain linear map.
Explain multi-column index.
Pros & cons of NoSQL.
Explain Node.js.
Explain infrastructure as code.
Explain MV* patterns.
Explain RDBMS vs DBMS.
See more at: