Skip to content

Instantly share code, notes, and snippets.

@soruly
Created April 1, 2021 06:58
Show Gist options
  • Save soruly/e27668ee8da7192f69c421124979bd21 to your computer and use it in GitHub Desktop.
Save soruly/e27668ee8da7192f69c421124979bd21 to your computer and use it in GitHub Desktop.
Javascript Practice

Javascript Practice

Why?

Exercise 1: if(true)

Circle the statement that will execute:
a)	if (false)        { foo(); } else { bar(); }
b)	if (true)         { foo(); } else { bar(); }
c)	if ("false")      { foo(); } else { bar(); }
d)	if (1)            { foo(); } else { bar(); }
e)	if (0)            { foo(); } else { bar(); }
f)	if (-0)           { foo(); } else { bar(); }
g)	if (Infinity)     { foo(); } else { bar(); }
h)	if ("1")          { foo(); } else { bar(); }
i)	if (null)         { foo(); } else { bar(); }
j)	if ("null")       { foo(); } else { bar(); }
k)	if ([null])       { foo(); } else { bar(); }
l)	if (undefined)    { foo(); } else { bar(); }
m)	if ("undefined")  { foo(); } else { bar(); }
n)	if ([1])          { foo(); } else { bar(); }
o)	if ("0")          { foo(); } else { bar(); }
p)	if ([true])       { foo(); } else { bar(); }
q)	if ("true")       { foo(); } else { bar(); }
r)	if (NaN)          { foo(); } else { bar(); }
s)	if (["0"])        { foo(); } else { bar(); }
t)	if ({})           { foo(); } else { bar(); }
u)	if ("")           { foo(); } else { bar(); }
v)	if ([])           { foo(); } else { bar(); }
w)	if ([""])         { foo(); } else { bar(); }

Exercise 1 solution

console.table([
  false,
  null,
  undefined,
  NaN,
  0,
  -0,
  "",
  true,
  1,
  -1,
  Infinity,
  "true",
  "false",
  "null",
  "undefined",
  "NaN",
  "0",
  "1",
  "-1",
  "[]",
  "{}",
  {},
  [],
  [0],
  [1],
  [-1],
  [true],
  [false],
  [NaN],
  [null],
  [undefined],
  ["true"],
  ["false"],
  ["null"],
  ["undefined"],
  ["0"],
  ["1"],
  ["-1"],
  [""],
  [[]],
  [{}],
].map(obj => [obj, Boolean(obj)]));

Exercise 1 discussion

  • Why sometimes use isTrue() sometimes does not? trust? confidence?
  • Should we come up with a consistent way to check existence of values?
  • Should we use lazy evaluation shorthand when possible?
if (!isNullOrUndef(event) && !isNullOrUndef(validEvents[event]) && (!waitForInit || (waitForInit && this._initCompleted))) {}
if (event && !isNullOrUndef(validEvents[event]) && (!waitForInit || (waitForInit && this._initCompleted))) {}
  • Should we omit the use of isTrue() ?
if (isTrue(match) && !this._isPreviousBetInit))
if (match && !this._isPreviousBetInit))
  • Do we need isTrue() if we have types?

Exercise 2: if (foo >= 0)

Circle the statement that will execute:
1.	if (1 >= 0)           { foo(); } else { bar(); }
2.	if (0 >= 0)           { foo(); } else { bar(); }
3.	if (true >= 0)        { foo(); } else { bar(); }
4.	if (false >= 0)       { foo(); } else { bar(); }
5.	if (null >= 0)        { foo(); } else { bar(); }
6.	if (undefined >= 0)   { foo(); } else { bar(); }
7.	if (NaN >= 0)         { foo(); } else { bar(); }
8.	if (Infinity >= 0)    { foo(); } else { bar(); }
9.	if ("" >= 0)          { foo(); } else { bar(); }
10.	if ("true" >= 0)      { foo(); } else { bar(); }
11.	if ("false" >= 0)     { foo(); } else { bar(); }
12.	if ("null" >= 0)      { foo(); } else { bar(); }
13.	if ("undefined" >= 0) { foo(); } else { bar(); }
14.	if ("0" >= 0)         { foo(); } else { bar(); }
15.	if ("1" >= 0)         { foo(); } else { bar(); }
16.	if ("[]" >= 0)        { foo(); } else { bar(); }
17.	if ("{}" >= 0)        { foo(); } else { bar(); }
18.	if ({} >= 0)          { foo(); } else { bar(); }
19.	if ([] >= 0)          { foo(); } else { bar(); }
20.	if ([0] >= 0)         { foo(); } else { bar(); }
21.	if ([1] >= 0)         { foo(); } else { bar(); }
22.	if ([true] >= 0)      { foo(); } else { bar(); }
23.	if ([false] >= 0)     { foo(); } else { bar(); }
24.	if ([NaN] >= 0)       { foo(); } else { bar(); }
25.	if ([null] >= 0)      { foo(); } else { bar(); }
26.	if ([undefined] >= 0) { foo(); } else { bar(); }
27.	if (["true"] >= 0)    { foo(); } else { bar(); }
28.	if (["false"] >= 0)   { foo(); } else { bar(); }
29.	if (["null"] >= 0)    { foo(); } else { bar(); }
30.	if (["0"] >= 0)       { foo(); } else { bar(); }
31.	if (["1"] >= 0)       { foo(); } else { bar(); }
32.	if ([""] >= 0)        { foo(); } else { bar(); }
33.	if ([[]] >= 0)        { foo(); } else { bar(); }
34.	if ([{}] >= 0)        { foo(); } else { bar(); }
35.	if ([[""]] >= 0)      { foo(); } else { bar(); }

Exercise 2 solution

console.table([
  1,
  1,
  0,
  true,
  false,
  null,
  undefined,
  NaN,
  Infinity,
  "",
  "true",
  "false",
  "null",
  "undefined",
  "0",
  "1",
  "[]",
  "{}",
  {},
  [],
  [0],
  [1],
  [true],
  [false],
  [NaN],
  [null],
  [undefined],
  ["true"],
  ["false"],
  ["null"],
  ["0"],
  ["1"],
  [""],
  [[]],
  [{}],
  [[""]]
].map(obj => [obj, Number(obj), obj >= 0]));

Exercise 2 discussion

  • How do you know what kind of type conversion would happen?
  • Even we enforce ourselves to use === instead of ==, we cannot avoid implicit type casting
  • Implicit type casting is hard to remember, too many special, weird cases
  • How can you be sure of the behavior if the type of variable is unknown?
  • Should we use operators like >= ?

Exercise 3: 1+1

typeof (1)
typeof ("1")
typeof (1+1)
typeof ("1"+"1")
typeof (1+"1")
typeof ("1"+1)
typeof (1+true)
typeof ("1"+true)
typeof (true+1)
typeof (true+"1")
typeof (1+null)
typeof ("1"+null)
typeof (null+1)
typeof (null+"1")
typeof (1+undefined)
typeof ("1"+undefined)
typeof (undefined+1)
typeof (undefined+"1")
typeof (1+NaN)
typeof ("1"+NaN)
typeof (NaN+1)
typeof (NaN+"1")
typeof (1+"")
typeof (""+1)
typeof (1+[])
typeof ([]+1)
typeof (Symbol() + 1)

Exercise 3 solution

console.table([
  "---",
  1,
  "1",
  1 + 1,
  "1" + "1",
  1 + "1",
  "1" + 1,
  1 + true,
  "1" + true,
  true + 1,
  true + "1",
  1 + null,
  "1" + null,
  null + 1,
  null + "1",
  1 + undefined,
  "1" + undefined,
  undefined + 1,
  undefined + "1",
  1 + NaN,
  "1" + NaN,
  NaN + 1,
  NaN + "1",
  1  +  "",
  ""  +  1,
  1 + [],
  [] + 1,
  ].map(obj => [obj, typeof obj]));

Exercise 3 discussion

  • NaN is number type
  • after any + operation, it can only be number / string type
  • when any side of the expression is string type, cast anything to string
  • i.e. before es6 template literal, foobar+"" was a common way to cast things to string type
  • For primitive types, when neither side of the expression is string type, cast anything to number
  • i.e. 1 + null => 1 + Number(null) => 1 + 0 => 1
  • Symbol() is an exceptional case which throw errors
  • + operations on non-primitive types would be discussed in upcoming exercises

Exercise 4: Revision

Circle the statement that will execute:
1.	if (1 >= 0)               { foo(); } else { bar(); }
2.	if (true >= 0)            { foo(); } else { bar(); }
3.	if (false >= 0)           { foo(); } else { bar(); }
4.	if (null >= 0)            { foo(); } else { bar(); }
5.	if (undefined >= 0)       { foo(); } else { bar(); }
6.	if (NaN >= 0)             { foo(); } else { bar(); }
7.	if ("" >= 0)              { foo(); } else { bar(); }
8.	if ("null" >= 0)          { foo(); } else { bar(); }
9.	if ("1" >= 0)             { foo(); } else { bar(); }
10.	if ({} >= 0)              { foo(); } else { bar(); }
11.	if ([] >= 0)              { foo(); } else { bar(); }
12.	if (null)                 { foo(); } else { bar(); }
13.	if ("")                   { foo(); } else { bar(); }
14.	if ([])                   { foo(); } else { bar(); }
15.	if ({})                   { foo(); } else { bar(); }
16.	if (NaN)                  { foo(); } else { bar(); }
17.	if ("0")                  { foo(); } else { bar(); }
18.	if (1 + "1" === 2)        { foo(); } else { bar(); }
19.	if ("1" + 1 === "11")     { foo(); } else { bar(); }
20.	if (null + 1 === 1)       { foo(); } else { bar(); }
21.	if (typeof NaN === "NaN") { foo(); } else { bar(); }

Exercise 4 solution

console.table([
1,
1 >= 0,
true >= 0,
false >= 0,
null >= 0,
undefined >= 0,
NaN >= 0,
"" >= 0,
"null" >= 0,
"1" >= 0,
{} >= 0,
[] >= 0,
null,
"",
[],
{},
NaN,
"0",
1 + "1" === 2,
"1" + 1 === "11",
null + 1 === 1,
typeof NaN === "NaN"
].map(obj => Boolean(obj)));

Exercise 5: Revision

Circle the statement that will execute:
1.	if (true)         { foo(); } else { bar(); }
2.	if (false)        { foo(); } else { bar(); }
3.	if (0)            { foo(); } else { bar(); }
4.	if (1)            { foo(); } else { bar(); }
5.	if (null)         { foo(); } else { bar(); }
6.	if (undefined)    { foo(); } else { bar(); }
7.	if (Infinity)     { foo(); } else { bar(); }
8.	if (NaN)          { foo(); } else { bar(); }
9.	if ("")           { foo(); } else { bar(); }
10.	if ([])           { foo(); } else { bar(); }
11.	if ({})           { foo(); } else { bar(); }
12.	if ("true")       { foo(); } else { bar(); }
13.	if ("false")      { foo(); } else { bar(); }
14.	if ("0")          { foo(); } else { bar(); }
15.	if ("1")          { foo(); } else { bar(); }
16.	if ("null")       { foo(); } else { bar(); }
17.	if ("undefined")  { foo(); } else { bar(); }
18.	if ([1])          { foo(); } else { bar(); }
19.	if ([null])       { foo(); } else { bar(); }
20.	if (["0"])        { foo(); } else { bar(); }
21.	if ([""])         { foo(); } else { bar(); }

Exercise 5 solution

console.table([
1,
true,
false,
0,
1,
null,
undefined,
Infinity,
NaN,
"",
[],
{},
"true",
"false",
"0",
"1",
"null",
"undefined",
[1],
[null],
["0"],
[""],
].map(obj => Boolean(obj)));

Exercise 6: Revision

Circle the statement that will execute:
1.	if (true)         { foo(); } else { bar(); }
2.	if (false)        { foo(); } else { bar(); }
3.	if (0)            { foo(); } else { bar(); }
4.	if (null)         { foo(); } else { bar(); }
5.	if (undefined)    { foo(); } else { bar(); }
6.	if (NaN)          { foo(); } else { bar(); }
7.	if ("")           { foo(); } else { bar(); }
8.	if ([])           { foo(); } else { bar(); }
9.	if ({})           { foo(); } else { bar(); }
10.	if (-1)           { foo(); } else { bar(); }
11.	if ("false")      { foo(); } else { bar(); }
12.	if ("0")          { foo(); } else { bar(); }
13.	if ("null")       { foo(); } else { bar(); }
14.	if ("undefined")  { foo(); } else { bar(); }
15.	if ([null])       { foo(); } else { bar(); }
16.	if (["0"])        { foo(); } else { bar(); }
17.	if ([""])         { foo(); } else { bar(); }

Exercise 6 solution

console.table([
1,
true,
false,
0,
null,
undefined,
NaN,
"",
[],
{},
-1,
"false",
"0",
"null",
"undefined",
[null],
["0"],
[""],
].map(obj => Boolean(obj)));

Exercise 7: Revision

Same as exercise 6

Exercise 8: NaN

Circle the statement that will execute:
1.	if (NaN)                        { foo(); } else { bar(); }
2.	if (NaN === NaN)                { foo(); } else { bar(); }
3.	if (isNaN(NaN))                 { foo(); } else { bar(); }
4.	if (Number.NaN)                 { foo(); } else { bar(); }
5.	if (Number.NaN === Number.NaN)  { foo(); } else { bar(); }
6.	if (Number.isNaN(Number.NaN))   { foo(); } else { bar(); }
7.	if (isNaN(Number.NaN))          { foo(); } else { bar(); }
8.	if (Number.isNaN(NaN))          { foo(); } else { bar(); }
9.	if (Number("1"))                { foo(); } else { bar(); }
10.	if (isNaN("1"))                 { foo(); } else { bar(); }
11.	if (Number.isNaN("1"))          { foo(); } else { bar(); }
12.	if (Number("foo"))              { foo(); } else { bar(); }
13.	if (isNaN("foo"))               { foo(); } else { bar(); }
14.	if (Number.isNaN("foo"))        { foo(); } else { bar(); }
15.	if (Number.isNaN(Number("foo")) { foo(); } else { bar(); }

Exercise 8 solution

console.table([
[0,0],
["NaN", NaN],
["NaN === NaN", NaN === NaN],
["isNaN(NaN)", isNaN(NaN)],

["Number.NaN", Number.NaN],
["Number.NaN === Number.NaN", Number.NaN === Number.NaN],
["Number.isNaN(Number.NaN)", Number.isNaN(Number.NaN)],

["isNaN(Number.NaN)", isNaN(Number.NaN)],
["Number.isNaN(NaN)", Number.isNaN(NaN)],

[`Number("1")`, Number("1")],
[`isNaN("1")`, isNaN("1")],
[`Number.isNaN("1")`, Number.isNaN("1")],

[`Number("foo")`, Number("foo")],
[`isNaN("foo")`, isNaN("foo")],
[`Number.isNaN("foo")`, Number.isNaN("foo")],

[`Number.isNaN(Number("foo"))`, Number.isNaN(Number("foo"))]
]);

See Explanation in MDN

Exercise 9: Revision

Circle the statement that will execute:
1.	if (true)                  { foo(); } else { bar(); }
2.	if ("false")               { foo(); } else { bar(); }
3.	if ("0")                   { foo(); } else { bar(); }
4.	if ("0" >= 0)              { foo(); } else { bar(); }
5.	if ("0" + 1 === 1)         { foo(); } else { bar(); }
6.	if ("")                    { foo(); } else { bar(); }
7.	if ([])                    { foo(); } else { bar(); }
8.	if ({})                    { foo(); } else { bar(); }
9.	if (-1)                    { foo(); } else { bar(); }
10.	if (false >= 0)            { foo(); } else { bar(); }
11.	if (undefined >= 0)        { foo(); } else { bar(); }
12.	if (null >= 0)             { foo(); } else { bar(); }
13.	if (1 + "1" === 2)         { foo(); } else { bar(); }
14.	if (null + 1 === "null1")  { foo(); } else { bar(); }
15.	if (NaN)                   { foo(); } else { bar(); }
16.	if (NaN !== NaN)           { foo(); } else { bar(); }
17.	if (typeof NaN === "NaN")  { foo(); } else { bar(); }

Exercise 9 solution

console.table([
true,
"false",
"0",
"0" >= 0,
"0" + 1 === 1,
"",
[],
{},
-1,
false >= 0,
undefined >= 0,
null >= 0,
1 + "1" === 2,
null + 1 === "null1",
NaN,
NaN !== NaN,
typeof NaN === "NaN",
].map(obj => Boolean(obj)));

Exercise 10: Short-circuit evaluation

Circle the statement that will execute (if any):
1.	if (true)                       { foo(); } else { bar(); }
2.	if (true && false)              { foo(); } else { bar(); }
3.	if (true || false)              { foo(); } else { bar(); }
4.	if (null || "0")                { foo(); } else { bar(); }
5.	if ("" && [])                   { foo(); } else { bar(); }
6.	if (undefined || -1)            { foo(); } else { bar(); }
7.	if (NaN || {})                  { foo(); } else { bar(); }
8.	if ([] && {})                   { foo(); } else { bar(); }
9.	if (false >= 0 || "")           { foo(); } else { bar(); }
10.	if (baz())                      {}
11.	if (baz() && false)             {}
12.	if (false && baz())             {} 
13.	if (baz() || "")                {}
14.	if ("" || baz())                {}
15.	if (baz() && [])                {}
16.	if ([] && baz())                {}

Exercise 10 solution

const q = [
  Boolean(true) ? "foo" : "bar",
  Boolean(true) ? "foo" : "bar",
  Boolean(true && false) ? "foo" : "bar",
  Boolean(true || false) ? "foo" : "bar",
  Boolean(null || "0") ? "foo" : "bar",
  Boolean("" && []) ? "foo" : "bar",
  Boolean(undefined || -1) ? "foo" : "bar",
  Boolean(NaN || {}) ? "foo" : "bar",
  Boolean([] && {}) ? "foo" : "bar",
  Boolean(false >= 0 || "") ? "foo" : "bar",
  "baz() does not execute",
  "baz() does not execute",
  "baz() does not execute",
  "baz() does not execute",
  "baz() does not execute",
  "baz() does not execute",
  "baz() does not execute"
];
const baz = (i) => {q[i] = "baz executed"};
baz(10);
baz(11) && false;
false && baz(12);
baz(13) || "";
"" || baz(14);
baz(15) && [];
[] && baz(16);
console.table(q);

Exercise 11: Standard built-in objects

Which ECMAScript Version support such function?

The first two has been done for you:

Built-in Objects Methods ES 5.1 ES2015 ES2016 ES2017 ES2018 ES2019 ES2020 ESNEXT
"".trimLeft / "".trimRight
[].indexOf
[].forEach
"".split / [].join
[].filter / [].map / [].reduce
[].slice / [].splice
[].concat
[].flat
[].flatMap
[].includes
"".includes
"".padStart / "".padEnd
"".trim
"".trimStart / "".trimEnd
"".match
"".matchAll
"".replace
"".replaceAll
"".startsWith / "".endsWith
Object.assign
Object.keys
Object.values
Array.isArray
Promise.all
Promise.catch
Promise.finally
Promise.allSettled

Exercise 11 solution

Built-in Objects Methods ES 5.1 ES2015 ES2016 ES2017 ES2018 ES2019 ES2020 ESNEXT
"".trimLeft / "".trimRight
[].indexOf
[].forEach
"".split / [].join
[].filter / [].map / [].reduce
[].slice / [].splice
[].concat
[].flat
[].flatMap
[].includes
"".includes
"".padStart / "".padEnd
"".trim
"".trimStart / "".trimEnd
"".match
"".matchAll
"".replace
"".replaceAll
"".startsWith / "".endsWith
Object.assign
Object.keys
Object.values
Array.isArray
Promise.all
Promise.catch
Promise.finally
Promise.allSettled

No need to recite which function is supported in which ECMAScript version.

Unless you are 100% certain that function is supported in all browsers, you should check if it requires a polyfill.

https://node.green/

https://kangax.github.io/compat-table/es5/

Exercise 12: Syntax

Which ECMAScript Version support such syntax?

The first two has been done for you:

Syntax ES 5.1 ES2015 ES2016 ES2017 ES2018
var a = 1;
let a = 1;
const a = 1;
function(a) {}
function(a = 1) {}
function(...b) {}
function([a, b, c]) {}
function([a, ...bc]) {}
function* generator(){ yield 1; }
async function a() { await b; }
async function* generator(){ yield 1; }
() => {}
`${0}123`
[0, ...[1, 2, 3]]
[0, ..."123"]
{a: 1, ...bc}
{ [a]: 1 }
{ a }
{ a() { return 1 }}
{ [a]() { return 1 }}
var [a, b, c] = [1, 2, 3];
var [a, b, c] = "123"
var {a, b, c} = {a: 1, b: 2, c: 3}
var [a ...bc] = [1, 2, 3];
var {a, ...bc} = {a: 1, b: 2, c: 3}
class A {}
2 ** 3
for(var i=0; i<3; i++) {}
for(var item in [1, 2, 3]) {}
for(var item in "123") {}
for (var item of [1, 2, 3]) {}
for (var item of "123") {}
for await(var item of [1, 2, 3]) {}

Exercise 12 solution

Syntax ES 5.1 ES2015 ES2016 ES2017 ES2018
var a = 1;
let a = 1;
const a = 1;
function(a) {}
function(a = 1) {}
function(...b) {}
function([a, b, c]) {}
function([a, ...bc]) {}
function* generator(){ yield 1; }
async function a() { await b; }
async function* generator(){ yield 1; }
() => {}
`${0}123`
[0, ...[1, 2, 3]]
[0, ..."123"]
{a: 1, ...bc}
{ [a]: 1 }
{ a }
{ a() { return 1 }}
{ [a]() { return 1 }}
var [a, b, c] = [1, 2, 3];
var [a, b, c] = "123"
var {a, b, c} = {a: 1, b: 2, c: 3}
var [a ...bc] = [1, 2, 3];
var {a, ...bc} = {a: 1, b: 2, c: 3}
class A {}
2 ** 3
for(var i=0; i<3; i++) {}
for(var item in [1, 2, 3]) {}
for(var item in "123") {}
for (var item of [1, 2, 3]) {}
for (var item of "123") {}
for await(var item of [1, 2, 3]) {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment