Concepts Flashcards

1
Q

What is v8

A

translates JS into C++

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

what is libuv?

A

deals with concurrency and accessing the file system in the C++ side

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What is a thread?

A

process = task thread= to do lists for that tasks event look= to lists for thread

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

event loop three checks

A
  1. set time out, set interval, set immediate
  2. any pending OS tasks
  3. any pending long running operations
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

How does the Libuv Thread pool work?

A

Pool of threads can take in some tasks to eventually passed to the core

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Can we use the threadpool for javascript code or can only nodeJS functions use it?

A

We can use custom JS that uses the thread pool

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What functions in node std library use the threadpool?

A

All ‘fs’ module functions. Some crypto stuff. Depends on OS (windows vs unix based)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

How does this threadpool stuff fit into the event loop?

A

Tasks running in the readpool are the ‘pendingOperations’ in our code example.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Make a code scratch of how the event loop works

A

// node myFile.js

const pendingTimers= []
const pendingOSTasks = []
const pendingOperations = []
// New timers, tasks, operations are recorded from myFile running
myFile.runContents( )
function shouldContinue( ) {
// Check one: Any pending setTimeout, setInterval, setImmediate?
// Check two: Any pending OS tasks? (Like server listening to port)
// Check three: Any pending long running operations? (Like fs module)

return pendingTimers.length || pendingOSTasks.length || pendingOperations.length

}

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

What functions in node std library use the OS’s async features?

A

Almost everything around networking for all OS’s. Some other stuff is OS specific

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How does this OS async stuff fit into the event loop

A

Tasks using the underlying OS are reflected in our ‘pendingOSTasks’ array.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What is a potential pitfall with using typeof bar === “object” to determine if bar is an object? How can this pitfall be avoided?

A

Although typeof bar === “object” is a reliable way of checking if bar is an object, the surprising gotcha in JavaScript is that null is also considered an object!

Therefore, the following code will, to the surprise of most developers, log true (not false) to the console:

var bar = null; console.log(typeof bar === “object”); // logs true!

As long as one is aware of this, the problem can easily be avoided by also checking if bar is null:

console.log((bar !== null) && (typeof bar === “object”)); // logs false

To be entirely thorough in our answer, there are two other things worth noting:

First, the above solution will return false if bar is a function. In most cases, this is the desired behavior, but in situations where you want to also return true for functions, you could amend the above solution to be:

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

What will the code below output to the console and why?

https://i.gyazo.com/fdb84541356f0b3a668989069d282569.png

A

But in fact, var a = b = 3; is actually shorthand for:

b = 3; var a = b;

As a result (if you are not using strict mode), the output of the code snippet would be:

a defined? false b defined? true

But how can b be defined outside of the scope of the enclosing function? Well, since the statement var a = b = 3; is shorthand for the statements b = 3; and var a = b;, b ends up being a global variable (since it is not preceded by the var keyword) and is therefore still in scope even outside of the enclosing function.

Note that, in strict mode (i.e., with use strict), the statement var a = b = 3; will generate a runtime error of ReferenceError: b is not defined, thereby avoiding any headfakes/bugs that might othewise result. (Yet another prime example of why you should use use strict as a matter of course in your code!)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What will the code below output to the console and why?

https://i.gyazo.com/fdb84541356f0b3a668989069d282569.png

A

The above code will output the following to the console:

outer func: this.foo = bar outer func: self.foo = bar inner func: this.foo = undefined inner func: self.foo = bar

In the outer function, both this and self refer to myObject and therefore both can properly reference and access foo.

In the inner function, though, this no longer refers to myObject. As a result, this.foo is undefined in the inner function, whereas the reference to the local variable self remains in scope and is accessible there.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What is the significance of, and reason for, wrapping the entire content of a JavaScript source file in a function block?

https://i.gyazo.com/e58887b2fb5d99a3bc53be8c74a0ffa7.png

A

This is an increasingly common practice, employed by many popular JavaScript libraries (jQuery, Node.js, etc.). This technique creates a closure around the entire contents of the file which, perhaps most importantly, creates a private namespace and thereby helps avoid potential name clashes between different JavaScript modules and libraries.

Another feature of this technique is to allow for an easily referenceable (presumably shorter) alias for a global variable. This is often used, for example, in jQuery plugins. jQuery allows you to disable the $ reference to the jQuery namespace, using jQuery.noConflict(). If this has been done, your code can still use $ employing this closure technique, as follows:

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Consider the two functions below. Will they both return the same thing? Why or why not?

A

Surprisingly, these two functions will not return the same thing. Rather:

console.log(“foo1 returns:”); console.log(foo1()); console.log(“foo2 returns:”); console.log(foo2());

will yield:

foo1 returns: Object {bar: “hello”} foo2 returns: undefined

Not only is this surprising, but what makes this particularly gnarly is that foo2() returns undefined without any error being thrown.

The reason for this has to do with the fact that semicolons are technically optional in JavaScript (although omitting them is generally really bad form). As a result, when the line containing the return statement (with nothing else on the line) is encountered in foo2(), a semicolon is automatically inserted immediately after the return statement.

No error is thrown since the remainder of the code is perfectly valid, even though it doesn’t ever get invoked or do anything (it is simply an unused code block that defines a property bar which is equal to the string “hello”).

This behavior also argues for following the convention of placing an opening curly brace at the end of a line in JavaScript, rather than on the beginning of a new line. As shown here, this becomes more than just a stylistic preference in JavaScript.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

What is NaN? What is its type? How can you reliably test if a value is equal to NaN?

A

The NaN property represents a value that is “not a number”. This special value results from an operation that could not be performed either because one of the operands was non-numeric (e.g., “abc” / 4), or because the result of the operation is non-numeric.

While this seems straightforward enough, there are a couple of somewhat surprising characteristics of NaN that can result in hair-pulling bugs if one is not aware of them.

For one thing, although NaN means “not a number”, its type is, believe it or not, Number:

console.log(typeof NaN === “number”); // logs “true”

Additionally, NaN compared to anything – even itself! – is false:

console.log(NaN === NaN); // logs “false”

A semi-reliable way to test whether a number is equal to NaN is with the built-in function isNaN(), but even using isNaN() is an imperfect solution.

A better solution would either be to use value !== value, which would only produce true if the value is equal to NaN. Also, ES6 offers a new Number.isNaN() function, which is a different and more reliable than the old global isNaN() function.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

What will the code below output? Explain your answer.

A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Discuss possible ways to write a function isInteger(x) that determines if x is an integer.

A
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

In what order will the numbers 1-4 be logged to the console when the code below is executed? Why?

A

The values will be logged in the following order:

1

4

3

2

Let’s first explain the parts of this that are presumably more obvious:

1 and 4 are displayed first since they are logged by simple calls to console.log() without any delay

2 is displayed after 3 because 2 is being logged after a delay of 1000 msecs (i.e., 1 second) whereas 3 is being logged after a delay of 0 msecs.

OK, fine. But if 3 is being logged after a delay of 0 msecs, doesn’t that mean that it is being logged right away? And, if so, shouldn’t it be logged before 4, since 4 is being logged by a later line of code?

The answer has to do with properly understanding JavaScript events and timing.

The browser has an event loop which checks the event queue and processes pending events. For example, if an event happens in the background (e.g., a script onload event) while the browser is busy (e.g., processing an onclick), the event gets appended to the queue. When the onclick handler is complete, the queue is checked and the event is then handled (e.g., the onload script is executed).

Similarly, setTimeout() also puts execution of its referenced function into the event queue if the browser is busy.

When a value of zero is passed as the second argument to setTimeout(), it attempts to execute the specified function “as soon as possible”. Specifically, execution of the function is placed on the event queue to occur on the next timer tick. Note, though, that this is not immediate; the function is not executed until the next tick. That’s why in the above example, the call to console.log(4) occurs before the call to console.log(3) (since the call to console.log(3) is invoked via setTimeout, so it is slightly delayed).

21
Q

Write a simple function (less than 160 characters) that returns a boolean indicating whether or not a string is a palindrome.

A
22
Q

Discuss possible ways to write a function isInteger(x) that determines if x is an integer.

A
23
Q

Write a sum method which will work properly when invoked using either syntax below.

A
24
Q

Consider the following code snippet:

A

Next

25
Q

What will the code below output to the console and why?

var arr1 = "john".split('');
var arr2 = arr1.reverse();
var arr3 = "jones".split('');
arr2.push(arr3);
console.log("array 1: length=" + arr1.length + " last=" + arr1.slice(-1));
console.log("array 2: length=" + arr2.length + " last=" + arr2.slice(-1));
A

The above code will output the following to the console:

"122"
"32"
"02"
"112"
"NaN2"
NaN

Here’s why…

The fundamental issue here is that JavaScript (ECMAScript) is a loosely typed language and it performs automatic type conversion on values to accommodate the operation being performed. Let’s see how this plays out with each of the above examples.

Example 1: 1 + "2" + "2" Outputs: "122" Explanation: The first operation to be performed in 1 + "2". Since one of the operands ("2") is a string, JavaScript assumes it needs to perform string concatenation and therefore converts the type of 1 to "1", 1 + "2" yields "12". Then, "12" + "2" yields "122".

Example 2: 1 + +"2" + "2" Outputs: "32" Explanation: Based on order of operations, the first operation to be performed is +"2" (the extra + before the first "2" is treated as a unary operator). Thus, JavaScript converts the type of "2" to numeric and then applies the unary + sign to it (i.e., treats it as a positive number). As a result, the next operation is now 1 + 2 which of course yields 3. But then, we have an operation between a number and a string (i.e., 3 and "2"), so once again JavaScript converts the type of the numeric value to a string and performs string concatenation, yielding "32".

Example 3: 1 + -"1" + "2" Outputs: "02" Explanation: The explanation here is identical to the prior example, except the unary operator is - rather than +. So "1" becomes 1, which then becomes -1 when the - is applied, which is then added to 1 yielding 0, which is then converted to a string and concatenated with the final "2" operand, yielding "02".

Example 4: +"1" + "1" + "2" Outputs: "112" Explanation: Although the first "1" operand is typecast to a numeric value based on the unary + operator that precedes it, it is then immediately converted back to a string when it is concatenated with the second "1" operand, which is then concatenated with the final "2" operand, yielding the string "112".

Example 5: "A" - "B" + "2" Outputs: "NaN2" Explanation: Since the - operator can not be applied to strings, and since neither "A" nor "B" can be converted to numeric values, "A" - "B" yields NaN which is then concatenated with the string "2" to yield “NaN2”.

Example 6: "A" - "B" + 2 Outputs: NaN Explanation: As exlained in the previous example, "A" - "B" yields NaN. But any operator applied to NaN with any other numeric operand will still yield NaN.

26
Q

The following recursive code will cause a stack overflow if the array list is too large. How can you fix this and still retain the recursive pattern?

var list = readHugeList();

var nextListItem = function() {
var item = list.pop();
~~~

if (item) {
    // process the list item...
    nextListItem();
} }; ~~~
A

The potential stack overflow can be avoided by modifying the nextListItem function as follows:

var list = readHugeList();

var nextListItem = function() {
var item = list.pop();
~~~

if (item) {
    // process the list item...
    setTimeout( nextListItem, 0);
} }; ~~~

The stack overflow is eliminated because the event loop handles the recursion, not the call stack. When nextListItem runs, if item is not null, the timeout function (nextListItem) is pushed to the event queue and the function exits, thereby leaving the call stack clear. When the event queue runs its timed-out event, the next item is processed and a timer is set to again invoke nextListItem. Accordingly, the method is processed from start to finish without a direct recursive call, so the call stack remains clear, regardless of the number of iterations.

27
Q

What is a “closure” in JavaScript? Provide an example.

A

A closure is an inner function that has access to the variables in the outer (enclosing) function’s scope chain. The closure has access to variables in three scopes; specifically: (1) variable in its own scope, (2) variables in the enclosing function’s scope, and (3) global variables.

Here is an example:

var globalVar = "xyz";

(function outerFunc(outerArg) {
var outerVar = ‘a’;
~~~

    (function innerFunc(innerArg) {
    var innerVar = 'b';
console.log(
    "outerArg = " + outerArg + "\n" +
    "innerArg = " + innerArg + "\n" +
    "outerVar = " + outerVar + "\n" +
    "innerVar = " + innerVar + "\n" +
    "globalVar = " + globalVar);

})(456); })(123); ~~~

In the above example, variables from innerFunc, outerFunc, and the global namespace are all in scope in the innerFunc. The above code will therefore produce the following output:

outerArg = 123
innerArg = 456
outerVar = a
innerVar = b
globalVar = xyz
28
Q

What will be the output of the following code:

for (var i = 0; i < 5; i++) {
	setTimeout(function() { console.log(i); }, i * 1000 );
}

Explain your answer. How could the use of closures help here?

A

The code sample shown will not display the values 0, 1, 2, 3, and 4 as might be expected; rather, it will display 5, 5, 5, 5, and 5.

The reason for this is that each function executed within the loop will be executed after the entire loop has completed and all will therefore reference the last value stored in i, which was 5.

Closures can be used to prevent this problem by creating a unique scope for each iteration, storing each unique value of the variable within its scope, as follows:

for (var i = 0; i < 5; i++) {
    (function(x) {
        setTimeout(function() { console.log(x); }, x * 1000 );
    })(i);
}

This will produce the presumably desired result of logging 0, 1, 2, 3, and 4 to the console.

In an ES2015 context, you can simply use let instead of var in the original code:

for (let i = 0; i < 5; i++) {
	setTimeout(function() { console.log(i); }, i * 1000 );
}
29
Q

What would the following lines of code output to the console?

console.log("0 || 1 = "+(0 || 1));
console.log("1 || 2 = "+(1 || 2));
console.log("0 && 1 = "+(0 && 1));
console.log("1 && 2 = "+(1 && 2));

Explain your answer.

A

The code will output:

true
false

In JavaScript, there are two sets of equality operators. The triple-equal operator === behaves like any traditional equality operator would: evaluates to true if the two expressions on either of its sides have the same type and the same value. The double-equal operator, however, tries to coerce the values before comparing them. It is therefore generally good practice to use the === rather than ==. The same holds true for !== vs !=.

30
Q

What is the output out of the following code? Explain your answer.

var a={},
    b={key:'b'},
    c={key:'c'};

a[b]=123;
a[c]=456;

console.log(a[b]);
A

The output of this code will be 456 (not 123).

The reason for this is as follows: When setting an object property, JavaScript will implicitly stringify the parameter value. In this case, since b and c are both objects, they will both be converted to "[object Object]". As a result, a[b] anda[c] are both equivalent to a["[object Object]"] and can be used interchangeably. Therefore, setting or referencing a[c] is precisely the same as setting or referencing a[b].

31
Q

What will the following code output to the console:

console.log((function f(n){return ((n > 1) ? n * f(n-1) : n)})(10));

Explain your answer.

A

The code will output the value of 10 factorial (i.e., 10!, or 3,628,800).

Here’s why:

The named function f() calls itself recursively, until it gets down to calling f(1) which simply returns 1. Here, therefore, is what this does:

f(1): returns n, which is 1
f(2): returns 2 * f(1), which is 2
f(3): returns 3 * f(2), which is 6
f(4): returns 4 * f(3), which is 24
f(5): returns 5 * f(4), which is 120
f(6): returns 6 * f(5), which is 720
f(7): returns 7 * f(6), which is 5040
f(8): returns 8 * f(7), which is 40320
f(9): returns 9 * f(8), which is 362880
f(10): returns 10 * f(9), which is 3628800
32
Q

What will the following code output to the console and why:

var hero = {
    _name: 'John Doe',
    getSecretIdentity: function (){
        return this._name;
    }
};

var stoleSecretIdentity = hero.getSecretIdentity;

console.log(stoleSecretIdentity());
console.log(hero.getSecretIdentity());

What is the issue with this code and how can it be fixed.

A

The code will output:

undefined
John Doe

The first console.log prints undefined because we are extracting the method from the hero object, so stoleSecretIdentity() is being invoked in the global context (i.e., the window object) where the _name property does not exist.

One way to fix the stoleSecretIdentity() function is as follows:

var stoleSecretIdentity = hero.getSecretIdentity.bind(hero);
33
Q

Create a function that, given a DOM Element on the page, will visit the element itself and all of its descendents (not just its immediate children). For each element visited, the function should pass that element to a provided callback function.

The arguments to the function should be:

  • a DOM element
  • a callback function (that takes a DOM element as its argument)
A

Visiting all elements in a tree (DOM) is a classic Depth-First-Search algorithm application. Here’s an example solution:

function Traverse(p_element,p_callback) {
   p_callback(p_element);
   var list = p_element.children;
   for (var i = 0; i < list.length; i++) {
       Traverse(list[i],p_callback); // recursive call
   }
}
34
Q

Testing your this knowledge in JavaScript: What is the output of the following code?

var length = 10;
function fn() {
	console.log(this.length);
}

var obj = {
  length: 5,
  method: function(fn) {
    fn();
    arguments[0]();
  }
};

obj.method(fn, 1);
A

Output:

10
2

Why isn’t it 10 and 5?

In the first place, as fn is passed as a parameter to the function method, the scope (this) of the function fn is window. var length = 10; is declared at the window level. It also can be accessed as window.length or length or this.length (when this === window.)

method is bound to Object obj, and obj.method is called with parameters fn and 1. Though method is accepting only one parameter, while invoking it has passed two parameters; the first is a function callback and other is just a number.

When fn() is called inside method, which was passed the function as a parameter at the global level, this.length will have access to var length = 10 (declared globally) not length = 5 as defined in Object obj.

Now, we know that we can access any number of arguments in a JavaScript function using the arguments[] array.

Hence arguments[0]() is nothing but calling fn(). Inside fn now, the scope of this function becomes the arguments array, and logging the length of arguments[] will return 2.

Hence the output will be as above.

35
Q

Consider the following code. What will the output be, and why?

(function () {
    try {
        throw new Error();
    } catch (x) {
        var x = 1, y = 2;
        console.log(x);
    }
    console.log(x);
    console.log(y);
})();
A
1
undefined
2

var statements are hoisted (without their value initialization) to the top of the global or function scope it belongs to, even when it’s inside a with or catch block. However, the error’s identifier is only visible inside the catch block. It is equivalent to:

(function () {
    var x, y; // outer and hoisted
    try {
        throw new Error();
    } catch (x /* inner */) {
        x = 1; // inner x, not the outer one
        y = 2; // there is only one y, which is in the outer scope
        console.log(x /* inner */);
    }
    console.log(x);
    console.log(y);
})();
36
Q

What will be the output of this code?

var x = 21;
var girl = function () {
    console.log(x);
    var x = 20;
};
girl ();
A

Neither 21, nor 20, the result is undefined

It’s because JavaScript initialization is not hoisted.

(Why doesn’t it show the global value of 21? The reason is that when the function is executed, it checks that there’s a local x variable present but doesn’t yet declare it, so it won’t look for global one.)

37
Q

How do you clone an object?

A
var obj = {a: 1 ,b: 2}
var objclone = Object.assign({},obj);

Now the value of objclone is {a: 1 ,b: 2} but points to a different object than obj.

Note the potential pitfall, though: Object.assign() will just do a shallow copy, not a deep copy. This means that nested objects aren’t copied. They still refer to the same nested objects as the original:

let obj = {
    a: 1,
    b: 2,
    c: {
        age: 30
    }
};

var objclone = Object.assign({},obj);
console.log(‘objclone: ‘, objclone);
~~~

obj.c.age = 45;
console.log(‘After Change - obj: ‘, obj); // 45 - This also changes
console.log(‘After Change - objclone: ‘, objclone); // 45
~~~

38
Q
for (let i = 0; i < 5; i++) {
  setTimeout(function() { console.log(i); }, i * 1000 );
}

What will this code print?

A

It will print 0 1 2 3 4, because we use let instead of var here. The variable i is only seen in the for loop’s block scope.

39
Q

What do the following lines output, and why?

console.log(1 < 2 < 3);
console.log(3 > 2 > 1);
A

The first statement returns true which is as expected.

The second returns false because of how the engine works regarding operator associativity for < and >. It compares left to right, so 3 > 2 > 1 JavaScript translates to true > 1. true has value 1, so it then compares 1 > 1, which is false.

40
Q

How do you add an element at the begining of an array? How do you add one at the end?

A
var myArray = ['a', 'b', 'c', 'd'];
myArray.push('end');
myArray.unshift('start');
console.log(myArray); // ["start", "a", "b", "c", "d", "end"]

With ES6, one can use the spread operator:

myArray = ['start', ...myArray];
myArray = [...myArray, 'end'];

Or, in short:

myArray = ['start', ...myArray, 'end'];
41
Q

Imagine you have this code:

var a = [1, 2, 3];

a) Will this result in a crash?

a[10] = 99;

b) What will this output?

console.log(a[6]);
A

a) It will not crash. The JavaScript engine will make array slots 3 through 9 be “empty slots.”
b) Here, a[6] will output undefined, but the slot still remains empty rather than filled with undefined. This may be an important nuance in some cases. For example, when using map(), empty slots will remain empty in map()’s output, but undefined slots will be remapped using the function passed to it:

var b = [undefined];
b[2] = 1;
console.log(b); // (3) [undefined, empty × 1, 1]
console.log(b.map(e => 7)); // (3) [7, empty × 1, 7]
42
Q

What is the value of typeof undefined == typeof NULL?

A

The expression will be evaluated to true, since NULL will be treated as any other undefined variable.

Note: JavaScript is case-sensitive and here we are using NULL instead of null.

43
Q

What would following code return?

console.log(typeof typeof 1);
A

string

typeof 1 will return "number" and typeof "number" will return string.

44
Q

What will the following code output and why?

var b = 1;
function outer(){
   	var b = 2
    function inner(){
        b++;
        var b = 3;
        console.log(b)
    }
    inner();
}
outer();
A

Output to the console will be “3”.

There are three closures in the example, each with it’s own var b declaration. When a variable is invoked closures will be checked in order from local to global until an instance is found. Since the inner closure has a b variable of its own, that is what will be output.

Furthermore, due to hoisting the code in inner will be interpreted as follows:

function inner () {
    var b; // b is undefined
    b++; // b is NaN
    b = 3; // b is 3
    console.log(b); // output "3"
}
45
Q
A
46
Q
A
47
Q
A
48
Q
A