Good day, friends!I hope this article will be useful to both novice developers and experienced ones.In questions which seemed to me more difficult than others, references to additional literature are given.I would be grateful for the detailed comments. All comments will be taken into account when editing the article.So let's go.70 Javascript Interview Questions
Questions:1. What is the difference between null and undefined?2. What is the && operator used for?3. What is the "||" operator used for?4. Is using the unary plus (+ operator) the fastest way to convert a string to a number?5. What is a DOM?6. What is Event Propogation?7. What is Event Bubbling?8. What is Event Capturing?9. What is the difference between the event.preventDefault () and event.stopPropagation () methods?10. How to learn about using the event.preventDefault () method?11. Why does obj.someprop.x lead to an error?12. What is an event target or target element (event.target)?13. (event.currentTarget)?14. "==" "==="?15. false?16. "!!"?17. ?18. (Hoisting)?19. (Scope)?20. (Closures)?21. JS ?22. , ?23. «use strict»?24. this?25. ?26. IIFE?27. Function.prototype.apply?28. Function.prototype.call?29. call apply?30. Function.prototype.bind?31. JS ?32. (Higher Order Functions)?33. JS (First-class Objects)?34. Array.prototype.map?35. Array.prototype.filter?36. Array.prototype.reduce?37. arguments?38. , ?39. b ?40. ECMAScript?41. JS ES6 ECMAScript2015?42. «var», «let» «const»?43. (Arrow Functions)?44. (Classes)?45. (Template Literals)?46. (Object Destructuring)?47. (Modules)?48. Set?49. (Callback Function)?50. (Promises)?51. async/await?52. spread- rest-?53. (Default Parameters)?54. (Wrapper Objects)?55. (Implicit and Explicit Coercion)?56. NaN? , NaN?57. , ?58. , , ( "%")?59. ?60. AJAX?61. JS ?62. Object.freeze Object.seal?63. «in» hasOwnProperty?64. What techniques of working with asynchronous code in JS do you know?65. What is the difference between a normal function and a functional expression?66. How to call a function in JS?67. What is memorization or memoization?68. How would you implement the auxiliary function of memorization?69. Why typeof null returns object? How to check if a value is null?70. What is the “new” keyword used for?1. What is the difference between null and undefined?
To begin, let's talk about what they have in common.Firstly, they belong to 7 JS "primitives" (primitive types):let primitiveTypes = ['string', 'number', 'null', 'undefined', 'boolean', 'symbol', 'bigint']
Secondly, they are false values, i.e. the result of converting them to a boolean using Boolean () or the operator "!!" is false:console.log(!!null)
console.log(!!undefined)
console.log(Boolean(null))
console.log(Boolean(undefined))
Okay, now about the differences.undefined is the default value:- a variable to which no value has been assigned, i.e. a declared but not initialized variable;
- a function that does not return anything explicitly, for example, console.log (1);
- nonexistent property of the object.
In these cases, the JS engine sets the value to undefined.let _thisIsUndefined
const doNothing = () => {}
const someObj = {
a: 'ay',
b: 'bee',
c: 'si'
}
console.log(_thisIsUndefined)
console.log(doNothing())
console.log(someObj['d'])
null is the "value of no value". null is the value that is assigned to the variable explicitly. In the example below, we get null when the fs.readFile method works without errors:fs.readFile('path/to/file', (e, data) => {
console.log(e)
if(e) {
console.log(e)
}
console.log(data)
})
When comparing null and undefined, we get true when using the "==" operator, and false when using the "===" operator. About why this happens, see below.console.log(null == undefined)
console.log(null === undefined)
2. What is the && operator used for?
The && operator (logical and) finds and returns the first false value or the last operand when all values are true. It uses a short circuit to avoid unnecessary costs:console.log(false && 1 && [])
console.log(' ' && true && 5)
With the if statement:const router: Router = Router()
router.get('/endpoint', (req: Request, res: Response) => {
let conMobile: PoolConnection
try {
} catch (e) {
if (conMobile) {
conMobile.release()
}
}
})
Same thing with the && operator:const router: Router = Router()
router.get('/endpoint', (req: Request, res: Response) => {
let conMobile: PoolConnection
try {
} catch (e) {
conMobile && conMobile.release()
}
})
3. What is the "||" operator used for?
The operator "||" (boolean or) finds and returns the first true value. It also uses a short circuit. This operator was used to assign default parameters in functions before the default parameters were standardized in ES6.console.log(null || 1 || undefined)
function logName(name) {
let n = name || Mark
console.log(n)
}
logName()
4. Is using the unary plus (+ operator) the fastest way to convert a string to a number?
According to MDN , the + operator is indeed the fastest way to convert a string to a number, since it does not perform any operations on a value that is a number.5. What is a DOM?
The DOM or Document Object Model is an application programming interface (API) for working with HTML and XML documents. When the browser first reads (“parses”) the HTML document, it forms a large object, a really large object based on the document - the DOM. The DOM is a tree structure (document tree). The DOM is used to interact and change the structure of the DOM itself or its individual elements and nodes.Let's say we have this HTML:<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document Object Model</title>
</head>
<body>
<div>
<p>
<span></span>
</p>
<label></label>
<input>
</div>
</body>
</html>
The DOM of this HTML looks like this:
In JS, the DOM is represented by a Document object. The Document object has a large number of methods for working with elements, their creation, modification, deletion, etc.6. What is Event Propagation?
When an event occurs in a DOM element, it actually occurs not only in it. The event "propagates" from the Window object to the element that called it (event.target). In this case, the event sequentially permeates (affects) all the ancestors of the target element. An event propagation has three stages or phases:- Immersion (capture, interception) phase - an event occurs in the Window object and descends to the event target through all its ancestors.
- The target phase is when the event reaches the target element.
- Ascending phase - an event rises from event.target, sequentially passes through all its ancestors and reaches the Window object.
Read more about the distribution of events here and here .7. What is an event popup?
When an event occurs in a DOM element, it affects not only this element. An event “pops up” (like an air bubble in water), passes from the element that caused the event (event.target) to its parent, then rises even higher, to the parent of the element’s parent, until it reaches the Window object.Let's say we have this markup:<div class="grandparent">
<div class="parent">
<div class="child">1</div>
</div>
</div>
And such a JS:function addEvent(el, event, callback, isCapture = false) {
if (!el || !event || !callback || typeof callback !== 'function') return
if (typeof el === 'string') {
el = document.querySelector(el)
}
el.addEventListener(event, callback, isCapture)
}
addEvent(document, 'DOMContentLoaded', () => {
const child = document.querySelector('.child')
const parent = document.querySelector('.parent')
const grandparent = document.querySelector('.grandparent')
addEvent(child, 'click', function(e) {
console.log('child')
})
addEvent(parent, 'click', function(e) {
console.log('parent')
})
addEvent(grandparent, 'click', function(e) {
console.log('grandparent')
})
addEvent('html', 'click', function(e) {
console.log('html')
})
addEvent(document, 'click', function(e) {
console.log('document')
})
addEvent(window, 'click', function(e) {
console.log('window')
})
})
The addEventListener method has a third optional parameter - useCapture. When its value is false (the default), the event begins with the ascent phase. When its value is true, the event begins with the immersion phase (for the "listeners" of events attached to the target of the event, the event is in the target phase, and not in the dive or ascent phases. Events in the target phase are triggered by all listeners on the element in the in which they were registered regardless of the useCapture parameter - approx. If we click on the child element, the console will display: child, parent, grandparent, html, document, window. Here's what an event popup is.8. What is an immersion event?
When an event occurs in a DOM element, it occurs not only in it. In the immersion phase, the event descends from the Window object to the event target through all its ancestors.Markup:<div class="grandparent">
<div class="parent">
<div class="child">1</div>
</div>
</div>
JS:function addEvent(el, event, callback, isCapture = false) {
if (!el || !event || !callback || typeof callback !== 'function') return
if (typeof el === 'string') {
el = document.querySelector(el);
}
el.addEventListener(event, callback, isCapture)
}
addEvent(document, 'DOMContentLoaded', () => {
const child = document.querySelector('.child')
const parent = document.querySelector('.parent')
const grandparent = document.querySelector('.grandparent')
addEvent(child, 'click', function(e) {
console.log('child');
}, true)
addEvent(parent, 'click', function(e) {
console.log('parent')
}, true)
addEvent(grandparent, 'click', function(e) {
console.log('grandparent')
}, true)
addEvent('html', 'click', function(e) {
console.log('html')
}, true)
addEvent(document, 'click', function(e) {
console.log('document')
}, true)
addEvent(window, 'click', function(e) {
console.log('window')
}, true)
})
The addEventListener method has a third optional parameter - useCapture. When its value is false (the default), the event begins with the ascent phase. When its value is true, the event begins with the dive phase. If we click on the child element, we will see the following in the console: window, document, html, grandparent, parent, child. This is the immersion of the event.9. What is the difference between the event.preventDefault () and event.stopPropagation () methods?
The event.preventDefault () method disables the default behavior of an element. If you use this method in the form element, it will prevent the form from submitting. If you use it in contextmenu, the context menu will be disabled (this method is often used in keydown to redefine the keyboard, for example, when creating a music / video player or text editor - approx. The event.stopPropagation () method disables the event propagation (its ascent or immersion).10. How to learn about using the event.preventDefault () method?
To do this, we can use the event.defaulPrevented property, which returns a Boolean value that serves as an indicator of application to the element of the event.preventDefault method.11. Why does obj.someprop.x lead to an error?
const obj = {}
console.log(obj.someprop.x)
The answer is obvious: we are trying to access the x property of someprop property, which is undefined. obj .__ proto __.__ proto = null, so undefined is returned, and undefined does not have the x property.12. What is an event target or target element (event.target)?
In simple words, event.target is the element in which the event occurs, or the element that raised the event.We have the following markup:<div onclick="clickFunc(event)" style="text-align: center; margin: 15px;
border: 1px solid red; border-radius: 3px;">
<div style="margin: 25px; border: 1px solid royalblue; border-radius: 3px;">
<div style="margin: 25px; border: 1px solid skyblue; border-radius: 3px;">
<button style="margin: 10px">
Button
</button>
</div>
</div>
</div>
And such a simple JS:function clickFunc(event) {
console.log(event.target)
}
We attached a “listener” to the outer div. However, if we click on the button, we get the layout of this button in the console. This allows us to conclude that the element that caused the event is the button itself, and not the external or internal divs.13. What is the current purpose of the event (event.currentTarget)?
Event.currentTarget is the element to which the event listener is attached.Similar markup:<div onclick="clickFunc(event)" style="text-align: center;margin:15px;
border:1px solid red;border-radius:3px;">
<div style="margin: 25px; border:1px solid royalblue;border-radius:3px;">
<div style="margin:25px;border:1px solid skyblue;border-radius:3px;">
<button style="margin:10px">
Button
</button>
</div>
</div>
</div>
And a slightly modified JS:function clickFunc(event) {
console.log(event.currentTarget)
}
We attached the listener to the outer div. Wherever we click, whether it be a button or one of the internal divs, in the console we always get the layout of the external div. This allows us to conclude that event.currentTarget is the element to which the event listener is attached.14. What is the difference between the operators "==" and "==="?
The difference between the operator == (abstract or non-strict equality) and the operator === (strict equality) is that the first compares the values after they are converted or cast to one type (Coersion), and the second - without such a conversion .Let's dig deeper. And first, let's talk about the transformation.A conversion is a process of casting a value to another type, or rather, a process of casting the compared values to one type. When comparing, the operator "==" produces the so-called implicit comparison. The operator "==" performs some operations before comparing two values.Suppose we compare x and y.The algorithm is as follows:- If x and y are of the same type, the comparison is performed using the "===" operator.
- x = null y = undefined true.
- x = undefined y = null true.
- x = , y = , x == toNumber(y) ( y ).
- x = , y = , toNumber(x) == y ( x ).
- x = , toNumber(x) == y.
- y = , x == toNumber(y).
- x = , , y = , x == toPrimitive(y) ( y ).
- x = , y = , , toPrimitive(x) == y.
- false.
Remember: to cast an object to a "primitive", the toPrimitive method first uses the valueOf method, then the toString method.Examples:
All examples return true.The first example is the first condition of the algorithm.The second example is the fourth condition.The third is the second.The fourth is the seventh.Fifth - eighth.And the last is the tenth.
If we use the "===" operator, all examples except the first will return false, since the values in these examples are of different types.15. Why is the result of comparing two similar objects false?
let a = {
a: 1
}
let b = {
a: 1
}
let c = a
console.log(a === b)
console.log(a === c)
In JS, objects and primitives are compared differently. Primitives are compared by value. Objects - by reference or address in memory where the variable is stored. This is why the first console.log returns false and the second returns true. Variables “a” and “c” refer to the same object, while variables “a” and “b” refer to different objects with the same properties and values.16. What is the operator "!!" used for?
The operator "!!" (double negation) leads the value to its right to a logical value.console.log(!!null)
console.log(!!undefined)
console.log(!!'')
console.log(!!0)
console.log(!!NaN)
console.log(!!' ')
console.log(!!{})
console.log(!![])
console.log(!!1)
console.log(!![].length)
17. How to write multiple expressions on one line?
For this we can use the operator "," (comma). This operator "moves" from left to right and returns the value of the last expression or operand.let x = 5
x = (x++, x = addFive(x), x *= 2, x -= 5, x += 10)
function addFive(num) {
return num + 5
}
If we print the value of x to the console, we get 27. First, we increase the value of x by one (x = 6). Then we call the addFive () function with parameter 6, to which we add 5 (x = 11). After that, we multiply the value of x by 2 (x = 22). Then subtract 5 (x = 17). And finally, add 10 (x = 27).18. What is hoisting?
Lift is a term that describes the rise of a variable or function in a global or functional scope.In order to understand what Hoisting is, you need to understand what the execution context is.The execution context is the environment in which the code is executed. The execution context has two phases - compilation and execution itself.Compilation. In this phase, functional expressions and variables declared using the “var” keyword with the value undefined rise to the very top of the global (or functional) scope (as if moving to the beginning of our code. This explains why we can call functions before they announcements - approx.Performance. In this phase, variables are assigned values, and functions (or methods of objects) are called or executed.Remember: only functional expressions and variables declared using the “var” keyword are raised. Ordinary functions and arrow functions, as well as variables declared using the keywords “let” and “const”, are not raised.Suppose we have code like this:console.log(y)
y = 1
console.log(y)
console.log(greet('Mark'))
function greet(name) {
return 'Hello ' + name + '!'
}
var y
We get undefined, 1 and 'Hello Mark!'.Here's what the compilation phase looks like:function greet(name) {
return 'Hello ' + name + '!'
}
var y
After the compilation phase is completed, the execution phase begins when the variables are assigned values and functions are called.More about Hoisting can be found here .19. What is a scope?
A scope is a place where (or from where) we have access to variables or functions. JS we have three types of scopes: global, functional and block (ES6).Global scope - variables and functions declared in the global namespace have a global scope and are accessible from anywhere in the code.
var g = 'global'
function globalFunc() {
function innerFunc() {
console.log(g)
}
innerFunc()
}
Functional scope (scope of a function) - variables, functions and parameters declared inside a function are available only inside this function.function myFavouriteFunc(a) {
if (true) {
var b = 'Hello ' + a
}
return b
}
myFavouriteFunc('World')
console.log(a)
console.log(b)
Block scope - variables (declared using the keywords "let" and "const") inside the block ({}) are available only inside it.function testBlock() {
if (true) {
let z = 5
}
return z
}
testBlock()
A scope is also a set of rules by which a variable is searched. If the variable does not exist in the current scope, its search is performed higher in the external visibility of the current scope. If there is no variable in the external scope, its search continues up to the global scope. If a variable is found in the global scope, the search stops; if not, an exception is thrown. The search is carried out by the closest to the current visibility areas and stops with finding the variable. This is called the Scope Chain.
var variable1 = 'Comrades'
var variable2 = 'Sayonara'
function outer() {
var variable1 = 'World'
function inner() {
var variable2 = 'Hello'
console.log(variable2 + ' ' + variable1)
}
inner()
}
outer()

20. What is a closure (Closures)?
This is probably the most difficult question from the list. I will try to explain how I understand closure.In fact, closure is the ability of a function to create links to variables and parameters that are in the current scope, in the scope of the parent function, in the scope of the parent of the parent function, and so on to the global scope using the chain of scopes at creation time. Typically, scope is determined when a function is created.Examples are a great way to explain closure:
var globalVar = 'abc'
function a() {
console.log(globalVar)
}
a()
In this example, when we declare a function, the global scope is part of the closure.
The “globalVar” variable does not matter in the picture, because its value may change depending on where and when the function will be called. But in the example above, globalVar will have the value “abc”.Now the example is more complicated:var globalVar = 'global'
var outerVar = 'outer'
function outerFunc(outerParam) {
function innerFunc(innerParam) {
console.log(globalVar, outerParam, innerParam)
}
return innerFunc
}
const x = outerFunc(outerVar)
outerVar = 'outer-2'
globalVar = 'guess'
x('inner')
The result is “guess outer inner”. The explanation is this: when we call the outerFunc function and assign the variable "x" the value returned by the innerFunc function, the parameter "outerParam" is equal to "outer". Despite the fact that we assigned the variable “outerVar” to “outer-2”, this happened after calling the outerFunc function, which “managed” to find the value of the variable “outerVar” in the scope chain, this value was “outer”. When we call "x" that refers to innerFunc, the value of "innerParam" is "inner" because we pass this value as a parameter when calling "x". globalVar has a value of “guess” because we assigned it that value before calling “x”.An example of a misunderstanding of a circuit.const arrFunc = []
for (var i = 0; i < 5; i++) {
arrFunc.push(function() {
return i
})
}
console.log(i)
for (let i = 0; i < arrFunc.length; i++) {
console.log(arrFunc[i]())
}
This code does not work as expected. Declaring a variable using the var keyword makes this variable global. After adding functions to the arrFunc array, the value of the global variable “i” becomes “5”. Therefore, when we call the function, it returns the value of the global variable “i”. A closure stores a reference to a variable, not its value at creation time. This problem can be solved by using IIFE or by declaring a variable using the “let” keyword.Read more about the closure here and here .21. What values in JS are false?
const falsyValues = ['', 0, null, undefined, NaN, false]
False are values whose conversion to a boolean value is false.22. How to check if a value is false?
Use the Boolean function or the operator "!!" (twice no).23. What is the use strict directive used for?
“Use strict” is an ES5 directive that forces all of our code or the code of an individual function to execute in strict mode. Strict mode introduces some restrictions on writing code, thereby avoiding errors in the early stages.Here are the limitations of strict mode.You cannot assign values or access undeclared variables:function returnY() {
'use strict'
y = 123
return y
}
returnY()
It is forbidden to assign global values to read-only or write-only variables:'use strict'
var NaN = NaN
var undefined = undefined
var Infinity = 'and beyond'
You cannot delete the “undeletable” property of an object:'use strict'
const obj = {}
Object.defineProperties(obj, 'x', {
value: 1
})
delete obj.x
Duplication of parameters is prohibited:'use strict'
function someFunc(a, b, b, c) {}
You cannot create functions using the eval function:'use strict'
eval('var x = 1')
console.log(x)
The default value for this is undefined:'use strict'
function showMeThis() {
return this
}
showMeThis()
… etc.24. What does this mean?
This usually refers to the value of the object that is currently executing or calling the function. “Right now” means that the value of this varies depending on the execution context, where we use this.const carDetails = {
name: 'Ford Mustang',
yearBought: 2005,
getName() {
return this.name
}
isRegistered: true
}
console.log(carDetails.getName())
In this case, the getName method returns this.name, and this refers to carDetails, the object in which getName is run, which is its "owner".Add three lines after console.log:var name = 'Ford Ranger'
var getCarName = carDetails.getName
console.log(getCarName())
The second console.log produces a Ford Ranger, and this is weird. The reason for this behavior is that the "owner" of getCarName is the window object. Variables declared with the var keyword in the global scope are written to the properties of the window object. this in the global scope refers to the window object (unless it is a strict mode).console.log(getCarName === window.getCarName)
console.log(getCarName === this.getCarName)
In this example, this and window refer to the same object.One way to solve this problem is to use the call or apply methods:console.log(getCarName.apply(carDetails))
console.log(getCarName.call(carDetails))
Call and apply take as the first argument an object that will be the value of this inside the function.In IIFE, functions that are created in the global scope, anonymous functions, and internal functions of an object's methods, the default value for this is the window object.(function() {
console.log(this)
})()
function iHateThis() {
console.log(this)
}
iHateThis()
const myFavouriteObj = {
guessThis() {
function getName() {
console.log(this.name)
}
getName()
},
name: 'Marko Polo',
thisIsAnnoying(callback) {
callback()
}
}
myFavouriteObj.guessThis()
myFavouriteObj.thisIsAnnoying(function() {
console.log(this)
})
There are two ways to get Marko Polo.First, we can store the value of this in a variable:const myFavoriteObj = {
guessThis() {
const self = this
function getName() {
console.log(self.name)
}
getName()
},
name: 'Marko Polo',
thisIsAnnoying(callback) {
callback()
}
}
Secondly, we can use the arrow function:const myFavoriteObj = {
guessThis() {
const getName = () => {
console.log(this.name)
}
getName()
},
name: 'Marko Polo',
thisIsAnnoying(callback) {
callback()
}
}
Arrow functions do not have this eigenvalue. They copy the meaning of this from the external lexical environment.25. What is a prototype of an object?
In a nutshell, a prototype is a plan (diagram or project) of an object. It is used as a fallback for the properties and methods existing in this object. It is also one of the ways to exchange properties and functionality between objects. This is the basic concept of prototype inheritance in JS.const o = {}
console.log(o.toString())
Although the “o” object does not have the toString property, accessing this property does not cause an error. If a specific property is not in the object, its search is carried out first in the prototype of the object, then in the prototype of the prototype of the object, and so on until the property is found. This is called the prototype chain. At the top of the prototype chain is Object.prototype.console.log(o.toString === Object.prototype.toString)
Read more about prototypes and inheritance here and here .26. What is IIFE?
IIFE or Immediately Invoked Function Expression is a function that is called or executed immediately after creation or declaration. To create IIFE, you need to wrap the function in parentheses (the grouping operator), turning it into an expression, and then call it using another parentheses. It looks like this: (function () {}) ().(function( ) { }( ))
(function( ) { })( )
(function named(params) { })( )
(( ) => { })
(function(global) { })(window)
const utility = (function( ) {
return {
}
})
All of these examples are valid. The penultimate example shows that we can pass parameters to IIFE. The last example shows that we can store the result of IIFE in a variable.The best use of IIFE is to perform initialization configuration functions and prevent name conflicts with other variables in the global scope (pollution of the global namespace). We give an example.<script src="https://cdnurl.com/somelibrary.js"></script>
We have a link to somelibrary.js library that provides some global functions that we can use in our code, but there are two methods in this library, createGraph and drawGraph, which we do not use because they contain errors. And we want to implement these functions on our own.One way to solve this problem is to change the structure of our scripts:<script src="https://cdnurl.com/somelibrary.js"></script>
<script>
function createGraph() {
}
function drawGraph() {
}
</script>
Thus, we redefine the methods provided by the library.The second way is changing the names of our functions:<script src="https://cdnurl.com/somelibrary.js"></script>
<script>
function myCreateGraph() {
}
function myDrawGraph() {
}
</script>
The third way is to use IIFE:<script>
const graphUtility = (function() {
function createGraph() {
}
function drawGraph() {
}
return {
createGraph,
drawGraph
}
})
</script>
In this example, we create a utility variable that contains the IIFE result, which returns an object containing the createGraph and drawGraph methods.Here is another problem that can be solved with IIFE:val li = document.querySelectorAll('.list-group > li')
for (var i - 0, len = li.length; i < len; i++) {
li[i].addEventListener('click', function(e) {
console.log(i)
})
}
Suppose we have an ul element with a list-group class containing 5 child elements li. And we want to display the value “i” in the console when clicking on a separate “li”. However, instead, the console always displays 5. The fault is all the fault.One solution is IIFE:var li = document.querySelectorAll('.list-group > li')
for (var i = 0, len = li.length; i < len; i++) {
(function(currentIndex) {
li[currentIndex].addEventListener('click', function(e) {
console.log(currentIndex)
})
})(i)
}
The reason this code works as intended is because IIFE creates a new scope at each iteration, and we write the value “i” in currentIndex.27. What is the Function.prototype.apply method used for?
Apply is used to bind a specific object to the this value of the called function.const details = {
message: 'Hello World!'
}
function getMessage() {
return this.message
}
getMessage.apply(details)
This method is similar to Function.prototype.call. The only difference is that in apply, the arguments are passed as an array.const person = {
name: 'Marko Polo'
}
function greeting(greetingMessage) {
return `${greetingMessage} ${this.name}`
}
greeting.apply(person, ['Hello'])
28. What is the function.prototype.call method used for?
Call is used to bind a specific object to the value of this function being called.const details = {
message: 'Hello World!'
};
function getMessage() {
return this.message;
}
getMessage.call(details);
This method is similar to Function.prototype.apply. The difference is that in call arguments are passed separated by commas.const person = {
name: 'Marko Polo'
};
function greeting(greetingMessage) {
return `${greetingMessage} ${this.name}`;
}
greeting.call(person, 'Hello');
29. What is the difference between call and apply methods?
The difference between call and apply is how we pass arguments in the called function. In apply, the arguments are passed as an array, in call, separated by commas.const obj1 = {
result: 0
}
const obj2 = {
result: 0
}
function reduceAdd() {
let result = 0
for (let i = 0, len = arguments.length; i < len; i++) {
result += arguments[i]
}
this.result = result
}
reduceAdd.apply(obj1, [1, 2, 3, 4, 5])
reduceAdd.call(obj2, 1, 2, 3, 4, 5)
30. What is the function.prototype.bind method used for?
Bind returns a new function whose this value is the object specified as the first parameter. Unlike bind, call and apply immediately call the function.import React from 'react'
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
value: ''
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(e) {
}
render() {
return ( < >
<
input type = {
this.props.type
}
value = {
this.state.value
}
onChange = {
this.handleChange
}
/> </ >
)
}
}
31. What is functional programming and what features of JS allow us to talk about it as a functional programming language?
Functional programming is a declarative programming concept or pattern (pattern) of how applications are built, how functions containing expressions that calculate values without changing the arguments that are passed to them are used.The Array object contains the map, filter, and reduce methods, which are the most famous functions in the world of functional programming because of their usefulness and also because they do not modify the array, which makes these functions “clean”. JS also has a closure and higher-order functions that are characteristics of a functional programming language.The map method returns a new array with callback results for each element of the array:const words = ['Functional', 'Procedural', 'Object-Oriented']
const wordsLength = words.map(word => word.length)
The filter method creates a new array with all elements that satisfy the condition specified in the callback:const data = {
{
name: 'Mark',
isRegistered: true
} {
name: 'Mary',
isRegistered: false
} {
name: 'Mae',
isRegistered: true
}
}
const registeredUsers = data.filter(user => user.isRegistered)
The reduce method performs a callback once for each element of the array, with the exception of voids, taking four arguments: the initial value (or the value from the previous callback), the value of the current element, the current index, and the iterated array:const strs = ['I', ' ', 'am', ' ', 'Iron', ' ', 'Man']
const result = strs.reduce((acc, currentStr) => acc + str, '')
32. What are Higher Order Functions?
A higher-order function is a function that returns another function or accepts another function as an argument.function higherOrderFunction(param, callback) {
return callback(param)
}
33. Why are functions in JS called First-class Objects?
Functions are called first-class objects because they are processed just like any other value in JS. They can be assigned to variables, be a property of an object (method), an element of an array, an argument to another function, the value returned by the function. The only difference between a function and any other value in JS is that the function can be executed or called.34. How would you implement the Array.prototype.map method?
function map(arr, mapCallback) {
if (!Array.isArray(arr) || !arr.length || typeof mapCallback !== 'function') {
return []
} else {
let result = []
for (let i = 0, len = arr.length; i < len; i++) {
result.push(mapCallback(arr[i], i, arr))
}
return result
}
}
The map method creates a new array with the result of calling the specified function for each element of the array.35. How would you implement the Array.prototype.filter method?
function filter(arr, filterCallback) {
if (!Array.isArray(arr) || !arr.length || typeof filterCallback !== 'function') {
return []
} else {
let result = []
for (let i = 0, len = arr.length; i < len; i++) {
if (filterCallback(arr[i], i, arr)) {
result.push(arr[i])
}
}
return result
}
}
The filter method creates a new array with all the elements that passed the test specified in the function being passed.36. How would you implement the Array.prototype.reduce method?
function reduce(arr, reduceCallbak, initialValue) {
if (!Array.isArray(arr) || !arr.length || typeof filterCallback !== 'function') {
return []
} else {
let hasInitialValue = initialValue !== undefined
let value = hasInitialValue ? initialValue : arr[0]
for (let i = hasInitialValue ? 0 : 1, len = arr.length; i < len; i++) {
value = reduceCallback(value, arr[i], i, arr)
}
return value
}
}
The reduce method applies the reducer function to each element of the array (from left to right), returning one resulting value.37. What is an arguments object?
Arguments is a collection of arguments passed to a function. This is an array-like object, it has the length property, we can access a specific value using arguments [i], but it does not have the forEach, reduce, filter, and map methods. It allows you to find out the number of function parameters.You can convert arguments to an array using Array.prototype.slice:Array.prototype.slice.call(arguments)
Remember: in arrow functions, the arguments object does not work.function one() {
return arguments
}
const two = function() {
return arguments
}
const three = function three({
return arguments
})
const four = () => arguments
four() // arguments is not defined
Calling the four function results in a ReferenceError: arguments is not defined error. This problem can be solved using the rest statement:const four = (...args) => args
This will automatically put all the parameters in an array.38. How to create an object that does not have a prototype?
This can be done using Object.create:const o1 = {}
console.log(o1.toString)
const o2 = Object.create(null)
console.log(o2.toString)
39. Why in the presented code does the variable b become global when the function is called?
function myFunc(){
let a = b = 0
}
myFunc()
This happens because the assignment operator ("=") has right-handed associativity, i.e. assigns values from right to left. Therefore, the code takes the following form:function myFunc(){
let a = (b = 0)
}
myFunc()
First, the value 0 is assigned to the variable "b", which is not declared. The JS engine makes it global. The value (0) returned by b = 0 is then assigned to the local variable “a”.This problem can be solved by first declaring local variables and then assigning values to them:function myFunc(){
let a, b
a = b = 0
}
myFunc()
40. What is ECMAScript?
ECMAScript is a specification, a standard scripting programming language, it is the basis of JS, so any changes to ECMAScript are reflected in JS.The latest version of the ECMA-262 specification can be viewed here .41. What new things did ES6 or ECMAScript2015 bring to JS?
- Arrow Functions
- Classes
- Template Strings.
- Enhanced Object literals
- Destructuring (Object Destructuring).
- Promises (Promises).
- Generators
- Modules
- Symbol.
- Proxies
- Sets.
- The default options.
- Rest and spread operators.
- Block scope (keywords “let” and “const”).
42. What is the difference between the keywords “var”, “let” and “const”?
Variables declared using the var keyword are global. This means that they are accessible from anywhere in the code:function giveMeX(showX){
if(showX){
var x = 5
}
return x
}
console.log(giveMeX(false))
console.log(giveMeX(true))
The result of the first console.log will be undefined, the second - 5. We have access to the variable “x” because of its emergence into the global scope. The code from the example above is interpreted as follows:function giveMeX(showX){
var x
if(showX){
x = 5
}
return x
}
The result of the first console.log is undefined, because declared variables that are not assigned a value are undefined by default.Variables declared using the keywords "let" and "const" have a block scope. This means that they are only available inside the block ({}):function giveMeX(showX){
if(showX){
let x = 5
}
return x
}
function giveMeY(showY){
if(showY){
let y = 5
}
return y
}
Calling these functions with the false parameter will result in a ReferenceError error, because the variables "x" and "y" are not accessible outside the block and their values are not returned (do not pop up).The difference between “let” and “const” is that in the first case we can change the value of the variable, and in the second - no (constant). At the same time, we can change the value of the property of an object declared using const, but not the property itself (variable).43. What are arrow functions (Arrow Functions)?
Arrow function is a relatively new way to create functions in JS. Arrow functions are created faster and have more readable syntax than functional expressions. In arrow functions, the word "function" is omitted:
var getCurrentDate = function(){
return new Date()
}
const getCurrentDate = () => new Date()
In a functional expression, we use the return keyword to return a value. In the arrow function, we do not do this, since arrow functions implicitly return values, provided that we return a single expression or value:
function greet(name){
return 'Hello ' + name + '!'
}
const greet = (name) => `Hello ${name}`
const greet2 = name = > `Hello ${name}`
We can also pass parameters to arrow functions. If we pass one parameter, we don’t have to wrap it in parentheses:const getArgs = () => arguments
const getArgs2 = (...rest) => rest
Arrow functions do not have access to the arguments object. Therefore, calling the first function will result in an error. To get the parameters passed to the function, we can use the rest operator.const data = {
result: 0
nums: [1,2,3,4,5]
computeResult(){
const addAll = () => {
return this.nums.reduce((total, cur) => total + cur, 0)
}
this.result = addAll()
}
}
44. What are classes?
Classes are a relatively new way of writing constructor functions in JS. This is syntactic sugar for constructor functions. Classes are based on the same prototypes and prototype inheritance:
function Person(firstName, lastName, age, address){
this.firstName = firstName
this.lastName = lastName
this.age = age
this.address = address
}
Person.self = function(){
return this
}
Person.prototype.toString = function(){
return '[object Person]'
}
Person.prototype.getFullName = function(){
return this.firstName + ' ' + this.lastName
}
class Person{
constructor(firstName, lastName, age, address){
this.firstName = firstName
this.lastName = lastName
this.age = age
this.address = address
}
static self(){
return this
}
toString(){
return '[object Person]'
}
getFullName(){
return `${this.firstName} ${this.lastName}`
}
}
Method overrides and inheritance from another class:
Employee.prototype = Object.create(Person.prototype)
function Employee(firstName, lastName, age, address, jobTitle, yearStarted){
Person.call(this, firstName, lastName, age, address)
this.jobTitle = jobTitle
this.yearStarted = yearStarted
}
Employee.prototype.describe = function(){
return `I am ${this.getFullName()} and I have a position of #{this.jobTitle} and I started at ${this.yearStarted}}`
}
Employee.prototype.toString = function(){
return '[object Employee]'
}
class Employee extends Person{
constructor(firstName, lastName, age, address, jobTitle, yearStarted){
super(firstName, lastName, age, address)
this.jobTitle = jobTitle
this.yearStarted = yearStarted
}
describe(){
return `I am ${this.getFullName()} and I have a position of #{this.jobTitle} and I started at ${this.yearStarted}}`
}
toString(){
return '[object Employee]'
}
}
How to learn about the use of prototypes?class Something{ }
function AnotherSomething(){ }
const as = new AnotherSomething()
const s = new Something()
console.log(typeof Something)
console.log(typeof AnotherSomething)
console.log(as.toString())
console.log(a.toString())
console.log(as.toString === Object.prototype.toString)
console.log(a.toString === Object.prototype.toString)
45. What are Template Literals?
Template literals are a relatively new way to create strings in JS. Template literals are created using double backticks (``):
var greet = 'Hi I\'m Mark'
let greet = `Hi I'm Mark`
In template literals, we do not need to escape single quotes.
var lastWords = '\n'
+ ' I \n'
+ ' am \n'
+ 'Iron Man \n'
let lastWords = `
I
am
Iron Man
`
In ES6, we do not need to use the escape sequence "\ n" to feed the line.
function greet(name){
return 'Hello ' + name + '!'
}
function greet(name){
return `Hello ${name}!`
}
In ES6, we don’t need to use string concatenation to combine text with a variable: we can use the expression $ {expr} to get the value of the variable.46. What is Object Destructuring?
Destructuring is a relatively new way of obtaining (retrieving) the values of an object or array.Let's say we have an object like this:const employee = {
firstName: 'Marko',
lastName: 'Polo',
position: 'Software Developer',
yearHired: 2017
}
Previously, to create the properties of an object, we created variables for each property. It was very boring and very annoying:var firstName = employee.firstName
var lastName = employee.lastName
var position = employee.position
var yearHired = employee.yearHired
Using destructuring makes the code cleaner and takes less time. The destructuring syntax is as follows: we enclose the object properties that we want to receive in curly brackets ({}), and if we are talking about an array, in square brackets ([]):let { firstName, lastName, position, yearHired } = employee
To change the variable name, use "propertyName: newName":let { firstName: fName, lastName: lName, position, yearHired } = employee
To assign default values to variables, use "propertyName = 'defaultValue'":let { firstName = 'Mark', lastName: lName, position, yearHired } = employee
47. What are Modules?
Modules allow you to combine (use) code from different files and save us from having to keep all the code in one large file. Before modules appeared in JS, there were two popular module systems for supporting code:- CommonJS - Nodejs
- AMD (AsyncronousModuleDefinition) - Browsers
The syntax of the modules is very simple: we use import to import functionality or values from another file or files, and export to export.Export functionality to another file (named export):
exports.isNull = function(val){
return val === null
}
exports.isUndefined = function(val){
return val === undefined
}
exports.isNullOrUndefined = function(val){
return exports.isNull(val) || exports.isUndefined(val)
}
export function isNull(val){
return val === null;
}
export function isUndefined(val) {
return val === undefined;
}
export function isNullOrUndefined(val) {
return isNull(val) || isUndefined(val);
}
Import functionality into another file:
const helpers = require('./helpers.js')
const isNull = helpers.isNull
const isUndefined = helpers.isUndefined
const isNullOrUndefined = helpers.isNullOrUndefined
const { isNull, isUndefined, isNullOrUndefined } = require('./helpers.js')
import * as helpers from './helpers.js'
import { isNull, isUndefined, isNullOrUndefined as isValid} from './helpers.js'
Default Export:
class Helpers {
static isNull(val){
return val === null
}
static isUndefined(val){
return val === undefined
}
static isNullOrUndefined(val){
return this.isNull(val) || this.isUndefined(val)
}
}
module.exports = Helpers
class Helpers {
static isNull(val){
return val === null
}
static isUndefined(val){
return val === undefined
}
static isNullOrUndefined(val){
return this.isNull(val) || this.isUndefined(val)
}
}
export default Helpers
Import:
const Helpers = require('./helpers.js')
console.log(Helpers.isNull(null))
import Helpers from './helpers.js'
console.log(Helpers.isNull(null))
This is the basic use of modules. I did not go into details, because my post is already too large.48. What is a Set object?
The Set object allows you to store unique values, primitives, and object references. Once again: only unique values can be added to Set. It checks the values stored in it using the SameZeroValue algorithm.A Set instance is created using the Set constructor. We can also pass it some values when creating:const set1 = new Set()
const set2 = new Set(['a','b','c','d','d','e'])
We can add values to Set using the add method. Since the add method is returnable, we can use a chain of calls:set2.add('f')
set2.add('g').add('h').add('i').add('j').add('k').add('k')
We can delete values from Set using the delete method:set2.delete('k')
set2.delete('z')
We can check for a property in Set using the has method:set2.has('a')
set2.has('z')
To get the length of Set, use the size method:set2.size
The clear method clears Set:set2.clear()
We can use Set to remove duplicate values in an array:const nums = [1,2,3,4,5,6,6,7,8,8,5]
const uniqNums = [...new Set(nums)]
49. What is a Callback Function?
The callback function is a function whose call is postponed for the future (occurs under certain conditions, for example, when an event occurs).const btnAdd = document.getElementById('btnAdd')
btnAdd.addEventListener('click', function clickCallback(e)){
}
In the example, we are waiting for a “click” event on an element with the identifier “btnAdd”. By click, the clickCallback function is called. The callback function adds some functionality to the data or event. The reduce, filter, and map methods are passed a callback function as the second argument. A good analogy to callback is the following situation: you call someone, he does not answer, you leave him a message and wait for him to call back. A call or message is an event or data, and a callback is the expectation (anticipation) of a return call.50. What are Promises?
Promises are one way of working with asynchronous code in JS. They return the result of an asynchronous operation. Promises were invented to solve the problem of the so-called hell of callback functions.fs.readFile('somefile.txt', function(e, data){
if(e){
console.log(e)
}
console.log(data)
})
The problems with this approach begin when we need to add another asynchronous operation to the first (inside the first), then another, etc. As a result, we get a messy and unreadable code:fs.readFile('somefile.txt', function(e,data){
fs.readFile('directory', function(e, files){
fs.mkdir('directory', function(e){
})
})
})
And here is what it looks like with promises:promReadFile('file/path')
.then(data => {
return promReaddir('directory')
})
.then(data => {
return promMkdir('directory')
})
.catch(e => {
console.error(e)
})
Promise has four conditions:- Waiting is the initial state of a promise. The result of the promise is unknown because the operation is not completed.
- Done - Asynchronous operation completed, there is a result.
- Rejected - asynchronous operation failed, there is a reason.
- Completed - completed or rejected.
The Promise constructor accepts resolve and reject as parameters. In resolve, the result of the operation is recorded, in reject, the reason for the failure of the operation. The result can be processed in the .then method, the error can be processed in the .catch method. The .then method also returns a promise, so we can use a chain consisting of several .then.const myPromiseAsync = (...args) => {
return new Promise((resolve, reject) => {
doSomeAsync(...args, (error, data) => {
if(error){
reject(error)
} else{
resolve(data)
}
})
})
}
myPromiseAsync()
.then(result => {
console.log(result)
})
.catch(reason => {
console.error(reason)
})
We can create a helper function to convert an asynchronous operation from callback to a promise. It will work like util from Node.js (“promisification”):const toPromise = (asyncFuncWithCallback) => {
return (...args) => {
return new Promise((res, rej) => {
asyncFuncWithCallback(...args, (e, result) => {
return e ? rej(e) : res(result)
})
})
}
}
const promiseReadFile = toPromise(fs.readFile)
promiseReadFile('file/path')
.then((data) => {
console.log(data)
})
.catch(e => console.error(e))
You can read more about promises here and here .51. What is async / await?
Async / await is a relatively new way to write asynchronous (non-blocking) code in JS. They are wrapped in a promise. It makes code more readable and clean than promises and callback functions. However, to use async / await, you need to know the promises well.
function callApi(){
return fetch('url/to/api/endpoint')
.then(resp => resp.json())
.then(data => {
}).catch(err => {
})
}
async function callApi(){
try{
const resp = await fetch('url/to/api/endpoint')
const data = await res.json()
} catch(e){
}
}
Remember: using the async keyword before a function forces it to return a promise:const giveMeOne = async () = 1
giveMeOne()
.then((num) => {
console.log(num)
})
The await keyword can only be used inside an asynchronous function. Using await inside another function will result in an error. Await waits for the expression to finish on the right to return its value before executing the next line of code.const giveMeOne = async() => 1
function getOne(){
try{
const num = await giveMeOne()
console.log(num)
} catch(e){
console.log(e)
}
}
async function getTwo(){
try{
const num1 = await giveMeOne()
const nm2 = await giveMeOne()
return num1 + num2
} catch(e){
console.log(e)
}
}
await getTwo()
Read more about async / await here and here .52. What is the difference between a spread operator and a rest operator?
The spread and rest statements have the same syntax ("..."). The difference lies in the fact that with the help of spread we transfer or spread the data of the array to other data, and with the help of rest we get all the parameters of the function and put them into the array (or we extract some of the parameters).function add(a, b){
return a + b
}
const nums = [5, 6]
const sum = add(...nums)
console.log(sum)
In this example, we use spread when calling the add function with the nums array data. The value of the variable “a” will be 5, b = 6, sum = 11.function add(...rest){
return rest.reduce((total, current) => total + current)
}
console.log(add(1, 2))
console.log(add(1, 2, 3, 4, 5))
Here we call the add function with any number of arguments. Add returns the sum of these arguments.const [first, ...others] = [1, 2, 3, 4, 5]
console.log(first)
console.log(others)
In this example, we use rest to put any number of parameters except the first one into the others array.53. What are the Default Parameters?
This is a relatively new way of defining default variable values.
function add(a,b){
a = a || 0
b = b || 0
return a + b
}
function add(a = 0, b = 0){
return a + b
}
add(1)
You can use destructuring:function getFirst([first, ...rest] = [0, 1]){
return first
}
getFirst()
getFirst([10,20,30])
function getArr({ nums } = { nums: [1,2,3,4] }){
return nums
}
getArr
getArr({nums:[5,4,3,2,1]})
We can even use the default parameters declared in the same place:function doSomethingWithValue(value = 'Hello World', callback = () => { console.log(value) }){
callback()
}
doSomethingWithValue()
54. What is an object wrapper (Wrapper Objects)?
The primitives string, number, and boolean have properties and methods, despite the fact that they are not objects:let name = 'marko'
console.log(typeof name)
console.log(name.toUpperCase())
Name is a string (primitive type) that has no properties and methods, but when we call the toUpperCase () method, this leads not to an error, but to “MARKO”.The reason for this behavior is that name is temporarily converted to an object. Each primitive, except null and undefined, has a wrapper object. Such objects are String, Number, Boolean, Symbol, and BigInt. In our case, the code takes the following form:console.log(new String(name).toUpperCase())
A temporary object is discarded upon completion of work with a property or method.55. What is the difference between Implicit and Explicit Coercion?
Implicit conversion is a way of casting a value to another type without our knowledge (participation).Suppose we have the following:console.log(1 + '6')
console.log(false + true)
console.log(6 * '2')
The result of the first console.log will be 16. In other languages, this would lead to an error, but in JS 1 it is converted to a string and concatenated (attached) from 6. We did nothing, the conversion occurred automatically.The result of the second console.log will be 1. False was converted to 0, true to 1. 0 + 1 = 1.The result of the third console.log will be 12. Line 2 was converted to a number before multiplying by 6.Explicit conversion implies our participation in casting the value to another type:console.log(1 + parseInt('6'))
In this example, we use parseInt to cast string 6 to a number, then add up the two numbers and get 7.56. What is NaN? How to check if the value is NaN?
NaN or Not A Number (not a number) is the value obtained as a result of performing a numerical operation on a non-numerical value:let a
console.log(parseInt('abc'))
console.log(parseInt(null))
console.log(parseInt(undefined))
console.log(parseInt(++a))
console.log(parseInt({} * 10))
console.log(parseInt('abc' - 2))
console.log(parseInt(0 / 0))
console.log(parseInt('10a' * 10))
JS has a built-in isNaN method that allows you to check if the value is NaN, but it behaves quite strangely:console.log(isNaN())
console.log(isNaN(undefined))
console.log(isNaN({}))
console.log(isNaN(String('a')))
console.log(isNaN(() => { }))
The result of all console.log is true, despite the fact that none of the values is NaN.ES6 recommends using the Number.isNaN method to check if the value is NaN. We can also write an auxiliary function to solve the problem of “NaN inequality for itself”:function checkIsNan(value){
return value !== value
}
57. How to check if a value is an array?
To do this, use the Array.isArray method:console.log(Array.isArray(5))
console.log(Array.isArray(''))
console.log(Array.isArray())
console.log(Array.isArray(null))
console.log(Array.isArray( {length: 5 }))
console.log(Array.isArray([]))
If the environment in which you work does not support this method, you can use the following polyfile:function isArray(value){
return Object.prototype.toString.call(value) === '[object Array]'
}
58. How to check that a number is even, without using modulo division or division with remainder (operator "%")?
To solve this problem, you can use the operator "&" (binary and). The & operator compares operands as binary values.function isEven(num){
if(num & 1){
return false
} else{
return true
}
}
0 in the binary notation is 0001 - this is 0012 - 0103 - 0114 - 1005 - 1016 - 1107 - 111, etc.
Console.log (5 & 1) will return 1. First, the & operator converts both numbers to binary values, 5 turns into 101, 1 turns into 001. Then a bitwise comparison is made:
Compare 1 and 0, we get 0.Compare 0 and 0 , we get 0.Compare 1 and 1, we get 1.Convert the binary value to an integer, we get 1.If this information seems too complicated for you, we can solve the problem using the recursive function:function isEven(num){
if(num < 0 || num === 1) return false
if(num == 0) return true
return isEven(num - 2)
}
59. How to determine the presence of a property in an object?
There are three ways to do this.The first way is to use the in operator:const o = {
'prop': 'bwahahah',
'prop2': 'hweasa'
}
console.log('prop' in o)
console.log('prop1' in o)
The second is to use the hasOwnProperty method:console.log(o.hasOwnProperty('prop2'))
console.log(o.hasOwnProperty('prop1'))
The third is the index notation of the array:console.log(o['prop'])
console.log(o['prop1'])
60. What is AJAX?
AJAX or Asyncronous JavaScript and XML is a set of interconnected technologies that allow you to work with data in asynchronous mode. This means that we can send data to the server and receive data from it without reloading the web page.AJAX uses the following technologies:HTML - web page structure.CSS - web page styles.JavaScript - page behavior and work with the DOM.XMLHttpRequest API - sending and receiving data from the server.PHP, Python, Nodejs - some kind of server language.61. How to create an object in JS?
Object literal:const o = {
name: 'Mark',
greeting(){
return `Hi, I'm ${this.name}`
}
}
o.greeting
Constructor function:function Person(name){
this.name = name
}
Person.prototype.greeting = function(){
return `Hi, I'm ${this.name}`
}
const mark = new Person('Mark')
mark.greeting()
Object.create Method:const n = {
greeting(){
return `Hi, I'm ${this.name}`
}
}
const o = Object.create(n)
o.name = 'Mark'
console.log(o.greeting)
62. What is the difference between the methods Object.freeze and Object.seal?
The difference is that when using the Object.freeze method, we cannot change or edit the properties of the object, and when using Object.seal we have such an opportunity.63. What is the difference between the in operator and the hasOwnProperty method?
The difference is that the "in" operator checks for the presence of a property not only in the object itself, but also in its prototypes, and the hasOwnProperty method - only in the object.console.log('prop' in o)
console.log('toString' in o)
console.log(o.hasOwnProperty('prop'))
console.log(o.hasOwnProperty('toString'))
64. What techniques of working with asynchronous code in JS do you know?
- Callbacks
- Promises (Promises).
- Async / await.
- Libraries like async.js, blueprint, q, co.
65. What is the difference between a normal function and a functional expression?
Let's say we have the following:hoistedFunc()
notHoistedFunc()
function hoistedFunc(){
console.log('I am hoisted')
}
var notHoistedFunc = function(){
console.log('I will not be hoisted!')
}
A call to notHoistedFunc will result in an error, but a call to hoistedFunc does not, because hoistedFunc “pops up”, rises to the global scope, but notHoistedFunc does not.66. How to call a function in JS?
In JS, there are 4 ways to call a function. The call defines the value of this or the "owner" of the function.Call as a function. If a function is called as a method, constructor, or using the apply or call methods, then it is called as a function. The owner of such a function is the window object:function add(a,b){
console.log(this)
return a + b
}
add(1,5)
const o = {
method(callback){
callback()
}
}
o.method(function(){
console.log(this)
})
Call as a method. When a function is a property of an object, we call it a method. When a method is called, the this object becomes the object of this method:const details = {
name: 'Marko',
getName(){
return this.name
}
}
details.getName()
Call as constructor. When a function is called using the “new” keyword, we call that function a constructor. This creates an empty object, which is the value of this:function Employee(name, position, yearHired){
this.name = name
this.position = position
this.yearHired = yearHired
}
const emp = new Employee('Marko Polo', 'Software Development', 2017)
A call using the apply or call methods. We use these methods when we want to explicitly determine the value of this or the owner of a function:const obj1 = {
result: 0
}
const obj2 = {
result: 0
}
function reduceAdd(){
let result = 0
for(let i = 0, len = arguments.length; i < len; i++){
result += arguments[i]
}
this.result = result
}
reduceAdd.apply(obj1, [1,2,3,4,5])
reduceAdd.call(obj2, 1,2,3,4,5)
67. What is memorization or memoization?
Memoization is the technique of creating a function that can remember previously calculated results or values. The advantage of memoization is that we avoid re-executing a function with the same arguments. The disadvantage is that we are forced to allocate additional memory to save the results.68. How would you implement the auxiliary function of memorization?
function memoize(fn){
const cache = {}
return function(param){
if(cache[param]){
console.log('cached')
return cache[param]
} else{
let result = fn(param)
cache[param] = result
console.log('not cached')
return result
}
}
}
const toUpper = (str = '') => str.toUpperCase()
const toUpperMemoized = memoize(toUpper)
toUpperMemoized('abcdef')
toUpperMemoized('abcdef')
We implemented the memoization function with one argument. Let's make it "multi-argument":const slice = Array.prototype.slice
function memoize(fn){
const cache = {}
return (...args) => {
const params = slice.call(args)
console.log(params)
if(cache[params]){
console.log('cached')
return cache[params]
} else{
let result = fn(...args)
cache[params] = result
console.log('not cached')
return result
}
}
}
const makeFullName = (fName, lName) => `${fName} ${lName}`
const reduceAdd = (numbers, startValue = 0) => numbers.reduce((total, cur) => total + cur, startValue)
const memoizedFullName = memoize(makeFullName)
const memoizeReduceAdd = memoize(reduceAdd)
memoizedFullName('Marko', 'Polo')
memoizedFullName('Marko', 'Polo')
memoizeReduceAdd([1,2,3,4],5)
memoizeReduceAdd([1,2,3,4],5)
69. Why typeof null returns object? How to check if a value is null?
typeof null == 'object' will always return true for historical reasons. There was a proposal to fix this error by changing typeof null = 'object' to typeof null = 'null', but it was rejected in the interest of maintaining backward compatibility (such a change would entail a large number of errors).To check whether the value is null, you can use the strict equality operator (===):function isNull(value){
return value === null
}
70. What is the “new” keyword used for?
The keyword “new” is used in constructor functions to create a new object (a new instance of the class).Let's say we have a code like this:function Employee(name, position, yearHired){
this.name = name
this.position = position
this.yearHired = yearHired
}
const emp = new Employee('Marko Polo', 'Software Development', 2017)
The keyword "new" does 4 things:- Creates an empty object.
- Binds the this value to it.
- A function inherits from functionName.prototype.
- Returns this unless otherwise specified.