6 unexpected JavaScript problems

As a front-end development engineer, JavaScript is our main development language. Its syntax is relatively simple, and the ecosystem is also very complete, and its influence in the community is growing.

In the process of our use, we often encounter various strange problems, which make us often puzzled.

Inspired by wtfjs , this article organizes 6 more common and interesting questions.

1. Strange try..catch

❓ Questions

What will the following code return when executed? 2 or 3 ?

 (() => {
  try {
    return 2;
  } finally {
    return 3;
  }
})();

💡Answer

The answer is 3 , why is that? This is because in the try...catch...finally statement, the finally clause is executed regardless of whether an exception is thrown. Also, if an exception is thrown, the statements in the finally clause will execute even without catch clause to handle the exception.

📚Reference

2. [] and null are both objects

❓ Questions

What is the result returned by the following 3 lines of code?

 typeof [];
typeof null;

null instanceof Object;

💡Answer

The result returned is this:

 typeof []; // -> 'object'
typeof null; // -> 'object'

null instanceof Object; // false

typeof operator returns a string, and must conform to Table 37: The return value of the typeof operator . It returns the string 'object' — for null , normal, standard-specific, and non-standard-specific objects that do not implement [[Call]] 0507f47952593932c3a37e2f35b2aef2—.

 console.log(typeof 42);
// expected output: "number"

console.log(typeof '前端自习课');
// expected output: "string"

console.log(typeof true);
// expected output: "boolean"

console.log(typeof undeclaredVariable);
// expected output: "undefined"

However, you can use the toString method to check the type of the object.

 Object.prototype.toString.call([]);
// -> '[object Array]'

Object.prototype.toString.call(new Date());
// -> '[object Date]'

Object.prototype.toString.call(null);
// -> '[object Null]'

📚Reference

3. The arrow function returns undefined

❓ Questions

Why does the function f2 return undefined 448903fb688779d35391f0828855aec7— after execution?

 let f1 = () => '前端自习课';
f1(); // -> '前端自习课'

let f2 = () => {};
f2(); // -> undefined

💡Answer

Our first impression should be to return {} , but it returns undefined , the essential reason is that the arrow function returns {} is part of the arrow function syntax , we can see that by writing a test case:

 let f2 = () => {
    return '前端自习课'
};
f2(); // -> '前端自习课'

Therefore, the above f2 function returns undefined , of course, if you need to return a {} object is also possible, just use parentheses to wrap the return value:

 let f2 = () => ({});
f2(); // -> {}

4. Can you also use backticks to execute functions?

❓ Questions

In addition to the following ways to call functions, is there any other way?

 function f(...args) {
  return args;
}

f(1, 2, 3); // -> [ 1, 2, 3 ]

Of course, we can use backticks to call:

 f`Hello string ${'前端自习课'}, Hello boolean ${false}, Hello array ${[1, 2, 3]}`;
/*
[
    ["Hello string ",  ", Hello boolean ", ", Hello array ", ""],
    "前端自习课",
    false,
    [1, 2, 3]
]
*/

💡Answer

This looks amazing, but it actually uses template strings . This is an advanced form of template string, which is a tagged template string.

In the above sample code: f The function is the label of the template literal, and the label can use the function to parse the template string. The first parameter of the label function contains an array of string values. The remaining parameters are related to the expression.

📚Reference

5. Are there tags in JavaScript too?

❓ Questions

Is there a problem with the following way of writing?

 foo: {
  console.log("Hello");
  break foo;
  console.log("前端自习课");
}

💡Answer

The answer is no problem, it will return a string of Hello . Because foo is recognized as a tag, then execute the following console.log("Hello") and then execute break foo to interrupt execution.

We often use labeled statements with break / continue statements to end or continue a loop:

 let str = '';

loop1:
for (let i = 0; i < 5; i++) {
  if (i === 1) {
    continue loop1;
  }
  str = str + i;
}

console.log(str);
// expected output: "0234"

📚Reference

6. {}{} is undefined

❓ Questions

We can test the following code in the console. A structure like this returns the value from the last defined object.

 {}{}; // -> undefined
{}{}{}; // -> undefined
{}{}{}{}; // -> undefined
{foo: 'bar'}{}; // -> 'bar'
{}{foo: 'bar'}; // -> 'bar'
{}{foo: 'bar'}{}; // -> 'bar'
{a: 'b'}{c:' d'}{}; // -> 'd'
{a: 'b', c: 'd'}{}; // > SyntaxError: Unexpected token ':'
({}{}); // > SyntaxError: Unexpected token '{'

💡Answer

When parsing to {} returns undefined, and when parsing {foo: ‘bar’}{}, the expression {foo: ‘bar’} returns ‘bar’.

Here {} has two meanings: it means an object , or it means a code block .

For example, () => {} in {} represents a code block . So we have to add parentheses: () => ({}) to make it return an object correctly.

Therefore, we now use {foo: 'bar'} as a code block , which can be written in the terminal as follows:

 if (true) {
  foo: "bar";
} // -> 'bar'

Aha, same result! So the curly braces in {foo: 'bar'}{} represent code blocks .