Skip to content

Latest commit

 

History

History
1007 lines (893 loc) · 22.3 KB

bfe_javascript_quizzes.md

File metadata and controls

1007 lines (893 loc) · 22.3 KB

1. Promise Executor (#2)

new Promise((resolve, reject) => {
  resolve(1)
  resolve(2)
  reject('error')
}).then((value) => {
  console.log(value)
}, (error) => {
  console.log('error')
})
Answer

1
Reason- When a promise gets settled (resolved or rejected) additional calls to resolve() or reject() will not have any effect.


2. Equal III (#79)

console.log(2.0 == "2" == new Boolean(true) == "1")
Answer

true
Reason- Since '==' attempts to convert and compare operands that are of different types and comparisons happen from Left to Right.

2 == 2 == true == '1'
true == true == '1'
true == '1'
1 == 1
true


3. undefined (#69)

function foo(a, b, undefined, undefined) {
  console.log('BFE.dev')
}
console.log(foo.length)
Answer

4
Reason- A Function object's length property indicates how many arguments the function expects, i.e. the number of formal parameters. Hence it logs 4.
Also, We have just called the foo.length not invoked the foo. So, 'BFE.dev' will not be logged.


4. let (#89)

let a = 1;
(function() {
  let foo = () => a
  let a = 2;
  console.log(foo())
}())
Answer

2
Reason- foo will simply return value of a defined at that point. Since foo is invoked after a is assigned with 2 and locally a's value is 2. Hence, 2 is logged out .


5. RegExp.prototype.test (#40)

console.log(/^4\d\d$/.test('404'))
console.log(/^4\d\d$/.test(404))
console.log(/^4\d\d$/.test(['404']))
console.log(/^4\d\d$/.test([404]))
Answer

true
true
true
true
Reason- /^4\d\d$/ says Start with 4, followed by a digit and end with a digit
Also, test() expects a string as input, against which to match the regular expression. So, if the input is not a string it simply converts the input to a string and then matches with regex.


6. Implicit Coercion (#46)

const foo = [0]
if (foo) {
  console.log(foo == true)
} else {
  console.log(foo == false)
}
Answer

false
Reason- Since if takes boolean values so foo will converted to true (as array is truthy value)
Now come to if block. Here both values is converted into Number (due to ==). so 1 == 0 ==> false


7. Precedence (#34)

let a = 1;  console.log(a +++ a)
let b = 1;  console.log(b + + + b)
let c = 1; console.log(c --- c)
let d = 1; console.log(d - - - d)
Answer

3
2
1
0
Reason- the catch is (a +++ a) is equivalent to (a++ + a)
And, (a + + + a) is equivalent to (a + a)


8. Var (#39)

function foo() {
  console.log(i)
  for (var i = 0; i < 3; i++) {
    console.log(i)
  }
}
foo()
Answer

undefined
0
1
2
Reason- In general, var can be hoisted before its initialization, hence got undefined in first console. Futher, for loop is normal


9. Function call (#44)

function a() {
  console.log(1)
  return {
    a: function() {
      console.log(2)
      return a()
    }
  }
}
a().a()
Answer

1
2
1
Reason- First outer a() is called and printed 1 and returned object with another func a.
Calling a().a() invoked the returned Object method a() and that printed 2 and returned a() that printed 1


10. Operator Precedence (#13)

console.log(0 == 1 == 2)
console.log(2 == 1 == 0)
console.log(0 < 1 < 2)
console.log(1 < 2 < 3)
console.log(2 > 1 > 0)
console.log(3 > 2 > 1)
Answer

false   // (0 == 1)--- (false == 2)--- (0 == 2)--- false  
true    // (2 == 1)--- (false == 0)--- (0 == 0)--- true  
true    // (0 < 1)--- (true < 2)--- (1 < 2)--- true 
true    // (1 < 2)--- (true < 3)--- (1 < 3)--- true
true    // (2 > 1)--- (true > 0)--- (1 > 0)--- true 
false   // (3 > 2)--- (true > 1)--- (1 > 1)--- false 


11. in (#63)

const obj = {
  foo: 'bar'
}
console.log('foo' in obj)
console.log(['foo'] in obj)
Answer
console.log('foo' in obj);  // true
console.log(['foo'] in obj) // true - ['foo'] coerced to string

12. Prototype 2 (#53)

function F() {
  this.foo = 'bar'
}
const f = new F()
console.log(f.prototype)
Answer

undefined
Reason- Only constructor functions have .prototype. So when a new object (f in our case) is created, it gets its internal [ [Prototype] ] which cannot be directly accessed. Hence result is undefined


13. Two-way Generator (#71)

function* gen() {
  yield 2 * (yield 100)
}
const generator = gen()
console.log(generator.next().value)
console.log(generator.next(1).value)
console.log(generator.next(1).value)
Answer
generator.next().value   // 100: inner yield resolved first
generator.next(1).value  // 2: replaces (yield 100) with 1 & perfomed 2 * 1
generator.next(1).value  // undefined: gen status is done at this point

14. Push unshift (#37)

const arr = [1,2]
arr.push(3,4)
arr.unshift(5,6)
console.log(arr)
Answer

[5,6,1,2,3,4]
Reason- push() adds 1 or more elements to the end & unshift() adds 1 or more elements to the beginning of an array


15. Override Setter (#59)

class A {
  val = 1
  get foo() {
    return this.val
  }
}
class B {
  val = 2
  set foo(val) {
    this.val = val
  }
}
const a = new A()
const b = new B()
console.log(a.foo)
console.log(b.foo)
b.foo = 3
console.log(b.val)
console.log(b.foo)
Answer
1
undefined
3
undefined

Missing getter means we can never get the value of the prop even if we have a set for it


16. Array Length (#72)

class MyArray extends Array {
  get length() {
    return 3
  }
}
const arr1 = new MyArray(10); console.log(arr1.length)
const arr2 = new Array(10); console.log(arr2.length)
Answer
10
10

Subclasses (MyArray) cannot override parent class (Array) properties. This is by design.


17. setTimeout III (#86)

let func = () => {
  console.log(1)
}
setTimeout(() => {
  func = () => {
    console.log(2)
  }
}, 0)
setTimeout(func, 100)
Answer
setTimeout(func, 100)  // 1 after 100ms

func is changed inside the first setimeout but since this is part of the callback it will not execute until the first setTimeout is invoked.


18. Hosting VI (#45)

var foo = 1;
(function () {
  console.log(foo);
  foo = 2;
  console.log(window.foo);
  console.log(foo);
  var foo = 3;
  console.log(foo);
  console.log(window.foo)
})()
Answer
(function () {
  // var foo;              // var declaration can be hoisted
  console.log(foo);        // undefined- as foo is unintialized till now
  foo = 2;
  console.log(window.foo); // 1- outer foo
  console.log(foo);        // 2- local foo
  var foo = 3;
  console.log(foo);        // 3- local foo
  console.log(window.foo)  // 1- outer foo
})()

19. Typed Array Length (#74)

class MyArray extends Uint8Array {
  get length() {
    return 3
  }
}
const arr1 = new MyArray(10)
console.log(arr1.length)

const arr2 = new Uint8Array(10)
console.log(arr2.length)
Answer

Here, we are extending from Uint8Array typed array that uses ArrayBuffer and in this case Subclass constructors may over-ride it to change the constructor assignment

console.log(arr1.length)  // 3
console.log(arr2.length)  // 10

20. comma (#66)

var obj = {
  a: "BFE",
  b: "dev",
  func: (function foo(){ return this.a; }, function bar(){ return this.b; })
}
console.log(obj.func())
Answer 'dev'

comma operator evaluates from left to right and returns the last(right most) operand


21. non-writable (#57)

const a = {}
Object.defineProperty(a, 'foo1', {
  value: 1
})
const b = Object.create(a)
b.foo2 = 1

console.log(b.foo1)
console.log(b.foo2)

b.foo1 = 2
b.foo2 = 2

console.log(b.foo1)
console.log(b.foo2)
Answer

Object.defineProperty() takes 3 parameters: the target object, name of the property and descriptor. The writable descriptor describes if the value associated with the property can be changed with an assignment operator. Defaults to false.

const b = Object.create(a)
b.foo2 = 1

console.log(b.foo1) // 1 console.log(b.foo2) // 1

b.foo1 = 2 // fails because it is non-writable property b.foo2 = 2

console.log(b.foo1) // 1 console.log(b.foo2) // 2


22. Promise executor II (#18)

const p1 = Promise.resolve(1)
const p2 = new Promise((resolve) => resolve(p1))
const p3 = Promise.resolve(p1)
const p4 = p2.then(() => new Promise((resolve) => resolve(p3)))
const p5 = p4.then(() => p4)

console.log(p1 == p2)
console.log(p1 == p3)
console.log(p3 == p4)
console.log(p4 == p5)
Answer

Promise.resolve() returns a Promise object that is resolved with a given value. If the value is a promise, that promise is returned; otherwise, the returned promise will be fulfilled with the value.

const p1 = Promise.resolve(1)                                     // Object=> Promise { 1 }
const p2 = new Promise((resolve) => resolve(p1))                  // Object => Promise {  }
const p3 = Promise.resolve(p1)                                    // Object => pointing to same object that p1 is pointing i.e. Promise { 1 }
const p4 = p2.then(() => new Promise((resolve) => resolve(p3)))   // Object => Promise {  }
const p5 = p4.then(() => p4)                                      // Object => Promise {  }

console.log(p1 == p2) // false-- both are pointing to different object console.log(p1 == p3) // true -- both point to same object console.log(p3 == p4) // false-- both are pointing to different object console.log(p4 == p5) // false-- both are pointing to different object


23. Math (#31)

console.log(1 / 0)
console.log(0 / 0)
console.log(-1 / 0)
console.log(1 / 0 * 0)
console.log(1 / 0 * 1)
console.log(1 / 0 * -1)
console.log(1 / 0 * 1 + 1 / 0 * 1)
console.log(1 / 0 * 1 - 1 / 0 * 1)
console.log(1 / 0 * 1 * (1 / 0 * 1))
console.log(1 / 0 * 1 / (1 / 0 * 1))
console.log(0 / Infinity)
console.log(0 * Infinity)
Answer
(1 / 0)         // Infinity
(0 / 0)         // NaN
(-1 / 0)        // -Infinity
(1 / 0 * 0)     // NaN = Infinity * 0
(1 / 0 * 1)     // Infinity = Infinity * 1
(1 / 0 * -1)    // -Infinity = Infinity * -1
(1 / 0 * 1 + 1 / 0 * 1)     // Infinity = (Infinity * 1) + (Infinity * 1) 
(1 / 0 * 1 - 1 / 0 * 1)     // NaN = (Infinity * 1) - (Infinity * 1)
(1 / 0 * 1 * (1 / 0 * 1))   // Infinity = Infinity * 1 * (Infinity * 1)
(1 / 0 * 1 / (1 / 0 * 1))   // NaN = Infinity * 1 / (Infinity * 1)
(0 / Infinity)    // 0
(0 * Infinity)    // NaN

24. Prototype (#48)

function Foo() { }
Foo.prototype.bar = 1
const a = new Foo()
console.log(a.bar)

Foo.prototype.bar = 2
const b = new Foo()
console.log(a.bar)
console.log(b.bar)

Foo.prototype = {bar: 3}
const c = new Foo()
console.log(a.bar)
console.log(b.bar)
console.log(c.bar)
Answer
function Foo() { }
Foo.prototype.bar = 1
const a = new Foo()
console.log(a.bar)       // 1  

Foo.prototype.bar = 2 // Value of bar in Foo.prototype is updated

const b = new Foo() console.log(a.bar) // 2 console.log(b.bar) // 2

Foo.prototype = {bar: 3} // Foo.prototype starts pointing to a completly new object const c = new Foo()

// proto property of a and b is still pointing to the object which was pointed by previous prototype of Foo. Thus a.bar & b.bar will print 2. console.log(a.bar) // 2 console.log(b.bar) // 2 console.log(c.bar) // 3


25. Hoisting II (#28)

const func1 = () => console.log(1)
func1()

func2()
function func2() {
  console.log(2)
}

func3()
var func3 = function func4() {
  console.log(3)
}
Answer
1
2
Error  

26. this II (#33)

const obj = {
  a: 1,
  b() {
    return this.a
  }
}
console.log(obj.b())
console.log((true ? obj.b : a)())
console.log((true, obj.b)())
console.log((3, obj['b'])())
console.log((obj.b)())
console.log((obj.c = obj.b)())
Answer
obj.b()               // 1 -- return reference
(true ? obj.b : a)()  // undefined  -- ternary operator returns value, which does not carry the info allowing to set this.
(true, obj.b)()       // undefined  -- comma operator returns value, which does not carry the info allowing to set this.
(3, obj['b'])()       // undefined  -- comma operator returns value, which does not carry the info allowing to set this.
(obj.b)()             // 1  -- returns reference
(obj.c = obj.b)()     // undefined  -- assignment operator returns value, which does not carry the info allowing to set this.


27. Largest Array index (#91)

const arr = []
arr[(2 ** 32) - 2] = 1
arr[(2 ** 32) - 1] = 2
console.log(arr.at(-1))
Answer

Check out about Array.at() and highest possible index is (2^32 - 2). Therefore, arr[(2 ** 32) - 1] = 2 can't be accessed due to exceeding array max length

console.log(arr.at(-1))  // 1

28. Meaningless Calculation (#75)

const num = +((~~!+[])+(~~!+[])+[]+(~~!+[]))
console.log(num)
Answer
+((~~!+[])+(~~!+[])+[]+(~~!+[]))
+( 1 + 1 + [] + 1 )
+( 2 + [] + 1)
+( '2' + '' + '1' ) 
+('21') = 21

29. Increment Operator (#7)

let a = 1
const b = ++a
const c = a++

console.log(a)
console.log(b)
console.log(c)
Answer
3
2
2

30. Equality & Sameness (#24)

console.log(0 == '0')
console.log(0 === '0')
console.log(Object.is(0, '0'))

console.log(0 == 0)
console.log(0 === 0)
console.log(Object.is(0, 0))

console.log(0 == -0)
console.log(0 === -0)
console.log(Object.is(0, -0))

console.log(NaN == NaN)
console.log(NaN === NaN)
console.log(Object.is(NaN, NaN))

console.log(0 == false)
console.log(0 === false)
console.log(Object.is(0, false))
Answer

Check out about Object.is() and NaN compares unequal to any other value, including itself

console.log(0 == '0')          // true
console.log(0 === '0')         // false
console.log(Object.is(0, '0')) // false

console.log(0 == 0) // true console.log(0 === 0) // true console.log(Object.is(0, 0)) // true

console.log(0 == -0) // true console.log(0 === -0) // true console.log(Object.is(0, -0)) // false

console.log(NaN == NaN) // false console.log(NaN === NaN) // false console.log(Object.is(NaN, NaN)) // true

console.log(0 == false) // true console.log(0 === false) // false console.log(Object.is(0, false)) // false


31. Block Scope (#5)

for (var i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 0)
}
for (let i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 0)
}
Answer
for (var i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 0)   // 5 5 5 5 5
}
for (let i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 0)   // 0 1 2 3 4
}

If we have any closures created in the loop, let variables will be bound to the value from only that iteration of the loop, whereas var variables will be the current value of the variable, which at that point of the settimeout it is 5


32. Equal II (#30)

console.log([1] == 1)
console.log([1] == '1')
console.log(['1'] == '1')
console.log(['1'] == 1)
console.log([1] == ['1'])
console.log(new Boolean(true) == 1)
console.log(new Boolean(true) == new Boolean(true))
console.log(Boolean(true) == '1')
console.log(Boolean(false) == [0])
console.log(new Boolean(true) == '1')
console.log(new Boolean(false) == [0])
console.log(null == undefined)
Answer
([1] == 1)              // true-- (1 == 1)
([1] == '1')            // true-- (1 == 1)
(['1'] == '1')          // true-- (1 == 1)
(['1'] == 1)            // true-- (1 == 1)
([1] == ['1'])            // false-- 2 different arrays
(new Boolean(true) == 1)  // true-- (1 == 1)
(new Boolean(true) == new Boolean(true))   // false-- 2 different objects 
(Boolean(true) == '1')       // true-- (true == '1')--(1 == 1)
(Boolean(false) == [0])      // true-- (false == [0])--(0 == 0)
(new Boolean(true) == '1')   // true-- (true == '1')--(1 == 1)
(new Boolean(false) == [0])  // false-- 2 different objects
(null == undefined)          // true

33. true or false (#26)

console.log([] == 0)
console.log([] == false)
console.log(!![])
console.log([1] == 1)
console.log(!![1])
console.log(Boolean([]))
console.log(Boolean(new Boolean([])))
console.log(Boolean(new Boolean(false)))
Answer

When types mismatch then JavaScript tries to coerce the right-side value to match the type of the left-side

([] == 0)        // true-- (0 == 0)
([] == false)    // true-- (0 == 0)
(!![])           // true-- (!!true)
([1] == 1)       // true-- (1 == 1)
(!![1])          // true-- (!!true)
(Boolean([]))    // true
(Boolean(new Boolean([])))      // true-- Boolean(any object)
(Boolean(new Boolean(false)))   // true-- Boolean(any object)

34. Comparison (#96)

console.log(10 > 9)
console.log(10 > '9')
console.log('10' > 9)
console.log('10' > '9')
Answer
(10 > 9)        // true
(10 > '9')      // true
('10' > 9)      // true
('10' > '9')    // false; get compared lexicographically and '1' < '9' so '10' < '9'

35. Inherit Getter Setter (#58)

let val = 0

class A {
  set foo(_val){ val = _val }
  get foo(){ return val }
}

class B extends A { }

class C extends A {
  get foo(){ return val}
}

const b = new B()
console.log(b.foo)
b.foo = 1
console.log(b.foo)

const c = new C()
console.log(c.foo)
c.foo = 2
console.log(c.foo)
console.log(b.foo)
Answer
console.log(b.foo)    // 0
b.foo = 1             // global variable 'val' got updated
console.log(b.foo)    // 1 
const c = new C() console.log(c.foo) // 1 c.foo = 2 // no effect as there is no setter in class C console.log(c.foo) // 1 console.log(b.foo) // 1

36. 'this' (#97)

const obj = {
  prefix: 'BFE',
  list: ['1', '2', '3'],
  log() {
    this.list.forEach(function (item) {
      console.log(this.prefix + item);
    });
  },
};
obj.log();
Answer
'undefined1'
'undefined2'
'undefined3'

this inside forEach callback func will refer to window as it's not the obj invoking callback. Hence this.prefix will be undefined


37. min max (#22)

console.log(Math.min())
console.log(Math.max())
console.log(Math.min(1))
console.log(Math.max(1,2))
console.log(Math.min([1,2,3]))
Answer
Infinity
-Infinity
1
2
NaN

38. Function Name (#65)

var foo = function bar(){ 
  return 'BFE'; 
};

console.log(foo());
console.log(bar());
Answer
console.log(foo());  // 'BFE'
console.log(bar());  // Error as named exp only available in func body

39. Hoisting III (#29)

var a = 1
function func() {
  a = 2
  console.log(a)
  var a
}
func()
console.log(a)

if (!('b' in window)) {
  var b = 1
}
console.log(b)
Answer
2
1
undefined

40. Function (#70)

function foo(){ console.log(1) }
var foo = 2
function foo(){ console.log(3) }
foo()
Answer

Hoisting Order of Precedence: variable assigment > function declaration > variable declaration

function foo(){ console.log(1) } // declaration will be hoisted & foo = function
var foo = 2                      // variable will be hoisted & function get replaced by foo = 2 due to above rule
function foo(){ console.log(3) } // no effect due to above rule
foo()                            // Error-- invoking a number isn't possible