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.
Contents
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
❓ 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 .