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.
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
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.
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 .
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 trueReason-
/^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.
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
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 0Reason- the catch is
(a +++ a)
is equivalent to (a++ + a)
And,
(a + + + a)
is equivalent to (a + a)
function foo() {
console.log(i)
for (var i = 0; i < 3; i++) {
console.log(i)
}
}
foo()
Answer
undefined 0 1 2Reason- In general,
var
can be hoisted before its initialization, hence got undefined
in first console. Futher, for
loop is normal
function a() {
console.log(1)
return {
a: function() {
console.log(2)
return a()
}
}
}
a().a()
Answer
1 2 1Reason- 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
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
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
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
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
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
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
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.
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.
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 })()
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
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
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 = 1console.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
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
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
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) // 1Foo.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
const func1 = () => console.log(1)
func1()
func2()
function func2() {
console.log(2)
}
func3()
var func3 = function func4() {
console.log(3)
}
Answer
1 2 Error
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.
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
const num = +((~~!+[])+(~~!+[])+[]+(~~!+[]))
console.log(num)
Answer
+((~~!+[])+(~~!+[])+[]+(~~!+[])) +( 1 + 1 + [] + 1 ) +( 2 + [] + 1) +( '2' + '' + '1' ) +('21') = 21
let a = 1
const b = ++a
const c = a++
console.log(a)
console.log(b)
console.log(c)
Answer
3 2 2
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')) // falseconsole.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
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
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
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)
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'
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
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
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
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
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
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