This paper selected more than 20 has a certain confusion OF JS questions, the main investigation is the type of judgment, scope, this point, prototype, event cycle and other knowledge points, each question is equipped with the author detailed idiot analysis, biased to beginners, please feel free to boss.

Question 1

let a = 1
function b(a) {
  a = 2
  console.log(a)
}
b(a)
console.log(a)
Copy the code
Click to see the answer

2, 1

Click to see the parsing

Firstly basic data types are passed by value, so b function, the parameters of the b receives a value of 1, parameter a is equal to the function of internal variables, when the scope and the upper scope of variables, the same name can’t access to the upper variables, so no matter how to modify a function, doesn’t affect the upper, so the function of internal printing a is 2, I still print 1 on the outside.

Second question

function a (b = c, c = 1) {
  console.log(b, c)
}
a()
Copy the code
Click to see the answer

An error

Click to see the parsing

Setting default values for multiple arguments to a function is essentially the same as defining variables in order, so there is a temporary dead zone problem, where previously defined variables cannot refer to later undefined variables, and later ones can access earlier ones.

The third question

let a = b = 10; (function(){ 
  let a = b = 20}) ()console.log(a)
console.log(b)
Copy the code
Click to see the answer

10 and 20

Click to see the parsing

Even perform operations such as from right to left, the equivalent of b = 10, let a = b, b obviously couldn’t direct assignment statement, so will implicitly created as a global variable, function is the same, no statement, b to b direct assignment, because of the scope chain, will be one layer to find upwards, the change to the global b, So the global b is changed to 20, and the function a is a local variable because it’s redeclared, so it doesn’t affect the global a, so a is still 10.

Number 4

var a = {n:1}
var b = a
a.x = a = {n:2}
console.log(a.x)
console.log(b.x)
Copy the code
Click to see the answer

Undefined, 2} {n,

Click to see the parsing

Forgive the author not only, this problem the author did a wrong.

Well, according to most of the Internet, because. {n: 1, x: undefined} = {n: 1, x: undefined} = {n: 1, x: undefined} = {n: 1, x: undefined} ({n: 1, x: undefined}). X = b.x = a = {n: 2}. ({n: 1, x: undefined}).

5

var arr = [0.1.2]
arr[10] = 10
console.log(arr.filter(function (x) {
  return x === undefined
}))
Copy the code
Click to see the answer

[]

Click to see the parsing

This problem is simpler, arr [10] = 10, then 3 to 9 position index is undefined, arr [3] and other printed also really is undefined, but, actually involves ECMAScript version here different corresponding method behavior problems, All previous traversal methods in ES6 skipped the unassigned part of the array, the empty space, but the new for of method in ES6 does not.

Number 6

var name = 'World'; (function () {
  if (typeof name === 'undefined') {
    var name = "Jack"
    console.info('Goodbye ' + name)
  } else {
    console.info('Hello ' + name)
  }
})()
Copy the code
Click to see the answer

Goodbye Jack

Click to see the parsing

Var () {if () {if () {if () {if () {if () {if () {if () {if () {if () {if (); Finally, because all unassigned variables are declared undefined, the first branch of if satisfies the condition.

Question 7

console.log(1 + NaN)
console.log("1" + 3)
console.log(1 + undefined)
console.log(1 + null)
console.log(1 + {})
console.log(1 + [])
console.log([] + {})

Copy the code
Click to see the answer

NaN, 13, NaN, 1, 1[object object], 1, [object object]

Click to see the parsing

This question examines the behavior of the + sign:

1. If one of the operands is a string, convert the other operand to a string to perform concatenation

2. If one of the operands is an object, then call the object’s valueOf method to convert it to the original value. If there is no method or it is still a non-original value, then call the toString method

3. In any other case, both operands are converted to numbers for addition

8 the topic

var a={},
    b={key:'b'},
    c={key:'c'}
a[b]=123
a[c]=456
console.log(a[b])
Copy the code
Click to see the answer

456

Click to see the parsing

Name and obj[‘name’]. The square brackets can be strings, numbers, variables, etc., but the final result is a string. In the case of b and C above, they are both objects, so the toString() method is called to convert them to strings. The result is [object Obejct], so a[b]=a[c]=a[‘[object object]’].

Question 9

var out = 25
var inner = {
  out: 20.func: function () {
    var out = 30
    return this.out
  }
};
console.log((inner.func, inner.func)())
console.log(inner.func())
console.log((inner.func)())
console.log((inner.func = inner.func)())
Copy the code
Click to see the answer

25, 20, 20, 25

Click to see the parsing

This is the answer to the question:

1. The comma operator returns the last value in the expression, in this case the function of inner

2. This is obviously a method call on an object, so this refers to that object

3. It looks a little confusing with parentheses, but in fact (inner. Func) and inner. Func are exactly equal, so they are still called as methods on the object

4. Assignment expressions are similar to comma expressions in that they return the value itself, so they are also relative to calling a function globally

Question 10

let {a,b,c} = { c:3.b:2.a:1 }
console.log(a, b, c)
Copy the code
Click to see the answer

One, two, three

Click to see the parsing

This question is to examine the variable destructuring assignment problem, array destructuring assignment is corresponding to the position, but the object as long as the variable and the property of the same name, the order is arbitrary.

Question 11

console.log(Object.assign([1.2.3], [4.5]))
Copy the code
Click to see the answer

[4, 5, 3]

Click to see the parsing

Do you never assign an array? The assign method works with arrays, but treats the array as an object. For example, we treat the target array as an object with attributes 0, 1, 2, so the values of the 0 and 1 properties of the source array override the values of the target object.

Number 12

var x=1
switch(x++)
{
  case 0: ++x
  case 1: ++x
  case 2: ++x
}
console.log(x)
Copy the code
Click to see the answer

4

Click to see the parsing

The increment operator does not occur until after the statement is evaluated, so x will still match the case branch with the value 1. In this case, x++ will still match the branch with the value 1. In this case, x++ will become 2. Because there is no break statement, it will go to the branch after the current case, so ++x again, and finally 4.

13 questions

console.log(typeof undefined= =typeof NULL)
console.log(typeof function () {} = =typeof class {})
Copy the code
Click to see the answer

True, true,

Click to see the parsing

The js keyword is case sensitive, so this is a normal variable, and there is no declaration. Typeof uses an undeclared variable without error, and returns ‘undefined’. Typeof also uses ‘undefined’ for undefined, so the two are equal

2. Typeof returns ‘function’ when using a function, class is just syntax sugar added in ES6, it’s still essentially a function, so the two are equal

Question 14

var count = 0
console.log(typeof count === "number")
console.log(!!typeof count === "number")
Copy the code
Click to see the answer

True, false,

Click to see the parsing

Typeof returns ‘number’ for numeric types.

2. What is the priority of operator? The priority of “===” is higher than that of congruent ===, so execute first!! Typeof count, result true, then execute true === ‘number’, result false of course, you can click here to see the list of priorities: click on me.

Question 15

"use strict"
a = 1
var a = 2
console.log(window.a)
console.log(a)
Copy the code
Click to see the answer

2, 2,

Click to see the parsing

The var declaration will elevate the variable to the top of the current scope, so a=1 will not cause an error. The var declaration in the global scope will cause the variable to become a property of the window. Both of these are independent of strict mode.

Number 16

var i = 1
function b() {
  console.log(i)
}
function a() {
  var i = 2
  b()
}
a()
Copy the code
Click to see the answer

1

Click to see the parsing

This problem is to investigate the issues of scope, the scope is actually a set of variables to find the rules, each function when executed will create an execution context, which would be associated with a variable object, its scope, it keeps the function can access all variables, when executed in the context of other code will create a scope chain, If an identifier is not found in the current scope, along the outer scope will continue to search, until the top of the global scope, because the js is lexical scope, in the coding phase scope have identified, in other words, is established in the function definition, rather than executed, so a function is defined in the global scope, Although called from within b, it can only access the global scope, not the scope of b.

Question 17

var obj = {
  name: 'abc'.fn: () = > {
    console.log(this.name)
  }
};
obj.name = 'bcd'
obj.fn()
Copy the code
Click to see the answer

undefined

Click to see the parsing

The context of the arrow function is not bound to this, so the “this” in it depends on the “this” in the outer scope. In this case, the outer scope of the function is global, so “this” refers to window. There is no name attribute in the window object. So undefined.

18 the topic

const obj = {
  a: {
    a: 1}};const obj1 = {
  a: {
    b: 1}};console.log(Object.assign(obj, obj1))
Copy the code
Click to see the answer

{a: {b: 1}}

Click to see the parsing

This is easy, because the assign method performs a shallow copy, so the a property of the source object directly overwrites the A property of the target object.

Article 19 the topic

console.log(a)
var a = 1
var getNum = function() {
  a = 2
}
function getNum() {
  a = 3
}
console.log(a)
getNum()
console.log(a)
Copy the code
Click to see the answer

Undefined, 1, 2

Click to see the parsing

First, because of the variable promotion function declared by var, the variable a is promoted to the top and is not assigned, so the first thing printed is undefined.

Then a function declaration and function expression, the difference between a function declaration can have promote role, before they can put the function code execution ascension to the top, generating function definition at the execution context, so the second getNum will be the first to ascend to the top, and then the var statement getNum ascension, but because getNum function has been declared, Var getNum = fun… var getNum = fun… GetNum is assigned to a function, and the following function declaration is skipped. Finally, before getNum is executed, a is printed as 1. After getNum is executed, a is changed to 2, so the final 2 is printed.

Question 20

var scope = 'global scope'
function a(){
  function b(){ 
    console.log(scope)
  }
  return b
  var scope = 'local scope'
}
a()()
Copy the code
Click to see the answer

undefined

Click to see the parsing

This examination or variables to promote and scope of the problem, although the var statement was behind the return statement, but it will be promoted to a function on top of the scope, then because the scope is set in the function definition, has nothing to do with the position, so the upper scope of b is a function, the scope is not found in b’s own scope, Looking up found the scope variable that was automatically promoted and not assigned, so the undefined is printed.

Question 21

function fn (){ 
  console.log(this)}var arr = [fn]
arr[0] ()Copy the code
Click to see the answer

Prints out the ARR array itself

Click to see the parsing

The function is called as a method on an object to which this refers, and the array is obviously an object, but we’re all used to objects referring to properties: obj.fn, but actually obj[‘fn’] references are fine.

Question 22

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

var b
function b(){}
console.log(b)

function b(){}
var b
console.log(b)
Copy the code
Click to see the answer

1. B function itself, B function itself

Click to see the parsing

The function declaration and the var declaration are both promoted, but the function is promoted first, so if the variable has the same name as the function, the variable promotion is ignored.

1. After the promotion, the execution of the assignment code, a is assigned to 1, because the function has been declared to promote, so skip, finally print a is 1.

2. Similar to the first question, only b has no assignment operation, so the execution of these two lines is equivalent to no operation, b of course is a function.

3. Print out b as a function, but the order of promotion is changed.

Question 23

function Foo() {
  getName = function () { console.log(1)}return this
}
Foo.getName = function () { console.log(2) }
Foo.prototype.getName = function () { console.log(3)}var getName = function () { console.log(4)}function getName() { console.log(5)}// Please write the following output:
Foo.getName()
getName()
Foo().getName()
getName()
new Foo.getName()
new Foo().getName()
new new Foo().getName()
Copy the code
Click to see the answer

One, one, two, three, three

Click to see the parsing

Var getName=… var getName=… var getName=… GetName is assigned to a new function that prints 4.

1. Execute the static method of function Foo and print 2.

2. Run getName. Currently getName is the function that prints 4.

3. Execute Foo, change the global getName, assign it to the function that prints 1, and return this, which refers to window, and print 1 because getName has been changed.

4. Because getName has not been reassigned, it still prints 1.

5. The new operator is used to call functions, so new foo.getName () is equivalent to new (foo.getName)(), so new is the static method getName of Foo, printing 2.

6. Because the dot operator (.) “Has the same priority as new, so it’s executed from left to right, equivalent to (new Foo()).getName(). A new call to Foo returns a newly created object, and then executes the object’s getName method. The object itself doesn’t have the method, so it looks up from the prototype object of Foo. There it is, so print out 3.

7. As in the previous problem, the dot operator (.) So new new Foo().getName() is equivalent to new ((new Foo()).getName)(). That’s what’s in parenthesy. so what you end up with is a method on the stereotype of Foo, whether it’s called directly, Whether it’s a new call, it’s going to execute that method, so it’s going to print out 3.

Question 24

const person = {
	address: {
		country:"china".city:"hangzhou"
	},
	say: function () {
		console.log(`it's The ${this.name}, from The ${this.address.country}`)},setCountry:function (country) {
		this.address.country=country
	}
}

const p1 = Object.create(person)
const p2 = Object.create(person)

p1.name = "Matthew"
p1.setCountry("American")

p2.name = "Bob"
p2.setCountry("England")

p1.say()
p2.say()
Copy the code
Click to see the answer

it’s Matthew, from England

it’s Bob, from England

Click to see the parsing

The object. create method creates an Object and points its __proto__ attribute to the Object passed in, so p1 and P2 have the same Object as their protoobjects, then add a name attribute to P1, and then call p1’s setCountry method. P1 itself does not have this method, so it goes down the stereotype chain, and it finds this method on its stereotype, which is the person object. Executing this method will set the value passed in to the country property of the address object. P1 itself does not have an address property, but unlike the name property, The address attribute is found on the stereotype object, and since it is a reference value, the country attribute will be successfully modified. The same is true for P2, and since there is a reference value in the stereotype, it will be shared across all instances. Therefore, both P1 and P2 refer to the same address object. Will be reflected in all instances, so p2 changes will override P1 changes, and the final value of country will be England.

Question 25

setTimeout(function() {
  console.log(1)},0)
new Promise(function(resolve) {
  console.log(2)
  for( var i=0 ; i<10000 ; i++ ) {
    i == 9999 && resolve()
  }
  console.log(3)
}).then(function() {
  console.log(4)})console.log(5)
Copy the code
Click to see the answer

2, 3, 5, 4, 1

Click to see the parsing

This question is obviously looking at the knowledge point of the event cycle.

Js is a single thread of language, but in order to perform some asynchronous tasks don’t block code, and avoid waste of resources, during the period of waiting there js event loop, the mechanism of single thread refers to the implementation of js threads, known as the main thread, and some other thread, timer thread, such as network request the main thread at runtime execution stack, Stack the code if asynchronous API calls will add events to the event queue, as long as the asynchronous task are the results will put the corresponding callback, task queue 】 【 when performing stack after the execution of code to read the tasks in the task queue, in the main thread, when performing the stack is empty and will go to check, so on, This is called the event loop.

Asynchronous tasks are divided into macro tasks (e.g., setTimeout, setInterval) and microtasks (e.g., Promise), which are placed in different queues. When the execution stack is empty, the microtask queue is checked first, and if there are any microtasks, they are executed all at once. Then go to the macro task queue to check, if there is a task to the main thread to execute, after the execution will check the micro task queue, so loop.

Let’s go back to this one. First, the whole code starts executing as a macro task. If we encounter setTimeout, the corresponding callback will enter the macro task queue. So then the callback will be put to detail task queue, and then print out 3, the final print out 5, here the execution of the current stack is empty, so check the task queue, discovered that a task, then taken out on the main thread, 4, print out the final inspection of macro task queue, put the timer callback main thread execution, print 1.

Question 26

console.log('1');

setTimeout(function() {
  console.log('2');
  process.nextTick(function() {
    console.log('3');
  });
  new Promise(function(resolve) {
    console.log('4');
    resolve();
  }).then(function() {
    console.log('5');
  });
}); 

process.nextTick(function() {
  console.log('6');
});

new Promise(function(resolve) {
  console.log('7');
  resolve();
}).then(function() {
  console.log('8');
});

setTimeout(function() {
  console.log('9');
  process.nextTick(function() {
    console.log('10');
  }) 
  new Promise(function(resolve) {
    console.log('11');
    resolve();
  }).then(function() {
    console.log('12')}); })Copy the code
Click to see the answer

1, 7, 6, 8, 2, 4, 9, 11, 3, 10, 5, 12

Click to see the parsing

The event loop concept exists in node. However, the macro task in NodeJS is divided into several different phases. The two timers are in the timers phase. SetImmediate is in the check phase, the socket is in the close callbacks phase, and all the other macro tasks are in the poll phase, except that once you get to one of the phases mentioned above, you do all the tasks in that phase, which is different from a browser. The browser executes one macro task at a time, and then checks the microtask queue. But nodeJS executes all the tasks at once. In what phase do process.nextTick and microtasks execute? But process.nextTick takes precedence over microtasks, and a picture is worth a thousand words:

The setTimeout callback is thrown into the Timers queue, the nextTick callback is thrown into the nextTick queue, the Promise callback is the synchronization code, and the 7 is printed out. Then the callback is thrown into the microtask queue. Then another setTimeout callback is thrown into the timers queue, at which point the current node ends. Check the nextTick and microtask queues. The nextTick queue has a task and prints out 6, and the microtask queue has a task and prints out 8. There are no tasks in the check queue or close Callbacks queue. In the timers phase, there are two tasks. Run the first one, print out 2, throw the nextTick into the nextTick queue, execute the Promise and print out 4, then throw the callback into the microtask queue. Next, the nextTick is thrown into the nextTick queue. The promise is executed to print out 11. Then the callback is thrown into the microtask queue. Find two more tasks, execute them in sequence, print out 3 and 10, and then check the microtask queue, also two tasks, execute them in sequence, print out 5 and 12, and by this point the queues are all clear.