Front end interview handwritten output questions

Posted by MaxD on Wed, 02 Mar 2022 17:12:06 +0100

preface:

The output of the code is a common topic in the interview. A piece of code may involve a lot of knowledge points, which examines the applicant's basic ability. In the front-end interview, the common code output problems mainly involve the following knowledge points: asynchronous programming, event loop, this pointing, scope, variable promotion, closure, prototype, inheritance, etc. these knowledge points often do not appear alone, but contain multiple knowledge points in the same piece of code. Therefore, the author roughly divides these problems into four categories for discussion. Here, we will not systematically explain the basic knowledge, but describe the knowledge points of each topic and the implementation process of the code in the form of interview examples. If you know these examples, most of the code output problems in the front-end interview can be easily solved.

Note: all examples in this article are collected from Niuke network, network, etc. in case of infringement, please contact to delete!

1, Asynchronous & event loop

1. Code output result

const promise = new Promise((resolve, reject) => {
  console.log(1);
  console.log(2);
});
promise.then(() => {
  console.log(3);
});
console.log(4);

The output results are as follows:

1 
2 
4

promise.then is a micro task, which will not be executed until all macro tasks are executed. At the same time, the internal state of promise needs to be changed. Because there is no change here, it is always in the pending state, so 3 is not output.

2. Code output results

const promise1 = new Promise((resolve, reject) => {
  console.log('promise1')
  resolve('resolve1')
})
const promise2 = promise1.then(res => {
  console.log(res)
})
console.log('1', promise1);
console.log('2', promise2);

The output results are as follows:

promise1
1 Promise{<resolved>: resolve1}
2 Promise{<pending>}
resolve1

It should be noted that if you print promise1 directly, its status value and parameters will be printed.

The code execution process is as follows:

  1. script is a macro task that executes these codes in order;
  2. First, enter Promise, execute the code in the constructor and print Promise 1;
  3. Encounter the resolve function, change the state of promise1 to resolved, and save the result;
  4. Meet promise 1 Then this micro task and put it into the micro task queue;
  5. Promise 2 is a new promise in pending status;
  6. Execute synchronization code 1 and print out the status of promise1 as resolved;
  7. Execute synchronization code 2 and print out that the status of promise 2 is pending;
  8. After the macro task is executed, find the micro task queue and find promise 1 Then execute the micro task with the status of resolved.

3. Code output results

const promise = new Promise((resolve, reject) => {
  console.log(1);
  setTimeout(() => {
    console.log("timerStart");
    resolve("success");
    console.log("timerEnd");
  }, 0);
  console.log(2);
});
promise.then((res) => {
  console.log(res);
});
console.log(4);

The output results are as follows:

1
2
4
timerStart
timerEnd
success

The code execution process is as follows:

  • First, if you encounter Promise constructor, you will execute the contents and print 1;
  • Encounter the timer steTimeout, which is a macro task and put it into the macro task queue;
  • Continue to execute downward and print out 2;
  • Since Promise is still pending at this time, Promise Then do not execute first;
  • Continue to perform the following synchronization tasks and print out 4;
  • At this time, there are no tasks in the micro task queue. Continue to execute the next round of macro tasks and execute steTimeout;
  • First, execute timerStart, and then encounter resolve. Change the state of promise to resolved, save the results, and replace the previous promise Then push the micro task queue, and then execute timerEnd;
  • After executing the macro task, go to the micro task promise Then, print the result of resolve.

4. Code output results

Promise.resolve().then(() => {
  console.log('promise1');
  const timer2 = setTimeout(() => {
    console.log('timer2')
  }, 0)
});
const timer1 = setTimeout(() => {
  console.log('timer1')
  Promise.resolve().then(() => {
    console.log('promise2')
  })
}, 0)
console.log('start');

The output results are as follows:

start
promise1
timer1
promise2
timer2

The code execution process is as follows:

  1. First, promise resolve(). Then is a micro task. Join the micro task queue
  2. Execute timer1, which is a macro task and join the macro task queue
  3. Continue to execute the following synchronization code and print out start
  4. In this way, the first round of macro task is completed and micro task promise is started resolve(). Then, print out promise1
  5. When timer2 is encountered, it is a macro task. Add it to the macro task queue. At this time, there are two tasks in the macro task queue, namely timer1 and timer2;
  6. In this way, the first round of micro task is completed, and the second round of macro task is started. First, execute timer timer1 and print timer1;
  7. Promise encountered resolve(). Then, which is a micro task, join the micro task queue
  8. Start executing the tasks in the micro task queue and print promise2;
  9. Finally, execute the macro task timer2 timer and print out timer2;

5. Code output results

const promise = new Promise((resolve, reject) => {
    resolve('success1');
    reject('error');
    resolve('success2');
});
promise.then((res) => {
    console.log('then:', res);
}).catch((err) => {
    console.log('catch:', err);
})

The output results are as follows:

then: success1

This topic examines that Promise's state will not change after it changes. The start state changes from pending to resolve, indicating that it has changed to completed state. The following two states will not be executed, and the following catch will not catch errors.

6. Code output results

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)

The output results are as follows:

1
Promise {<fulfilled>: undefined}

Promise. If the parameter of the resolve method is an original value or an object without the then method, promise The resolve method returns a new promise object with the status of resolved, promise The parameters of the resolve method will be passed to the callback function at the same time.

The parameter accepted by the then method is a function. If a function is not passed, it will actually interpret it as then(null), which will cause the result of the previous Promise to be passed to the following.

7. Code output results

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  }, 1000)
})
const promise2 = promise1.then(() => {
  throw new Error('error!!!')
})
console.log('promise1', promise1)
console.log('promise2', promise2)
setTimeout(() => {
  console.log('promise1', promise1)
  console.log('promise2', promise2)
}, 2000)

The output results are as follows:

promise1 Promise {<pending>}
promise2 Promise {<pending>}

Uncaught (in promise) Error: error!!!
promise1 Promise {<fulfilled>: "success"}
promise2 Promise {<rejected>: Error: error!!}

8. Code output results

Promise.resolve(1)
  .then(res => {
    console.log(res);
    return 2;
  })
  .catch(err => {
    return 3;
  })
  .then(res => {
    console.log(res);
  });

The output results are as follows:

1   
2

Promise can be called in a chain, because every call then , or catch # will return a new promise to realize the chain call. It is not like the chain call of general tasks to return this.

The reason why the above output results print out 1 and 2 in turn is that after resolve(1), the first then method is followed, and it is not in the catch. Therefore, res in the second then actually gets the return value of the first then. And return 2 will be packaged as resolve(2) and printed out by the last then.

9. Code output results

Promise.resolve().then(() => {
  return new Error('error!!!')
}).then(res => {
  console.log("then: ", res)
}).catch(err => {
  console.log("catch: ", err)
})

The output results are as follows:

"then: " "Error: error!!!"

Any non promise value returned will be wrapped into a promise object, so the return new Error('error!!! ') here is also wrapped into a return promise Resolve (new error ('error!!! '), so it will be caught by then instead of catch.

10. Code output results

const promise = Promise.resolve().then(() => {
  return promise;
})
promise.catch(console.err)

The output results are as follows:

Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>

This is actually a pit then or The value returned by catch # cannot be promise itself, otherwise it will cause an endless loop.

11. Code output results

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)

The output results are as follows:

1

Seeing this topic, many then actually only need to remember one principle: Then or The parameter of catch , is expected to be a function. If a non function is passed in, value transparent transmission will occur.

Neither the first then nor the second then is a function. One is a number and the other is an object. Therefore, transparent transmission occurs. The value of resolve(1) is directly transmitted to the last then and 1 is printed directly.

12. Code output results

Promise.reject('err!!!')
  .then((res) => {
    console.log('success', res)
  }, (err) => {
    console.log('error', err)
  }).catch(err => {
    console.log('catch', err)
  })

The output results are as follows:

error err!!!

We know that Two parameters in the then function:

  • The first parameter is the function used to handle Promise success
  • The second is the function that handles the failure

Promise The value of resolve ('1 ') will enter the successful function, promise The value of reject ('2 ') will enter the failed function.

In this problem, the error is directly captured by the second parameter of then, so it will not be captured by catch. The output result is: error err!!! '

However, if it is like this:

Promise.resolve()
  .then(function success (res) {
    throw new Error('error!!!')
  }, function fail1 (err) {
    console.log('fail1', err)
  }).catch(function fail2 (err) {
    console.log('fail2', err)
  })

If an error is thrown in the first parameter of then, he will not be inactivated by the second parameter, but caught by the following catch.

13. Code output results

Promise.resolve('1')
  .then(res => {
    console.log(res)
  })
  .finally(() => {
    console.log('finally')
  })
Promise.resolve('2')
  .finally(() => {
    console.log('finally2')
  	return 'I am finally2 Returned value'
  })
  .then(res => {
    console.log('finally2 hinder then function', res)
  })

The output results are as follows:

1
finally2
finally
finally2 hinder then Function 2

. finally() is rarely used. Just remember the following points:

  • The. finally() method executes regardless of the final state of the Promise object
  • The callback function of the. finally() method does not accept any parameters, that is, you are In the finally() function, it is impossible to know whether the final state of Promise is resolved or rejected
  • It will eventually return the default value of the last Promise object, but if an exception is thrown, it will return the Promise object of the exception.
  • finally is essentially a special case of then method

Error capture for. finally():

Promise.resolve('1')
  .finally(() => {
    console.log('finally1')
    throw new Error('I am finally Exception thrown in')
  })
  .then(res => {
    console.log('finally hinder then function', res)
  })
  .catch(err => {
    console.log('Capture error', err)
  })

The output result is:

'finally1'
'Capture error' Error: I am finally Exception thrown in

14. Code output results

function runAsync (x) {
    const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000))
    return p
}

Promise.all([runAsync(1), runAsync(2), runAsync(3)]).then(res => console.log(res))

The output results are as follows:

1
2
3
[1, 2, 3]

First, a Promise is defined to asynchronously execute the function runAsync, which passes in a value of x, and then prints out the x after an interval of one second.

Then use promise All to execute this function. When executing, you see that 1, 2, 3 and array [1, 2, 3] are output one second later. The three functions are executed synchronously and all results are returned in a callback function. And the result is consistent with the execution order of the function.

15. Code output results

function runAsync (x) {
  const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000))
  return p
}
function runReject (x) {
  const p = new Promise((res, rej) => setTimeout(() => rej(`Error: ${x}`, console.log(x)), 1000 * x))
  return p
}
Promise.all([runAsync(1), runReject(4), runAsync(3), runReject(2)])
       .then(res => console.log(res))
       .catch(err => console.log(err))

The output results are as follows:

// Output after 1s
1
3
// Output after 2s
2
Error: 2
// Output after 4s
4

You can see. catch caught the first error. The first error in this topic is the result of runReject(2). If there is no exception in the asynchronous operation group In the first callback function parameter of then(). Will be The second callback function of then().

16. Code output results

function runAsync (x) {
  const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000))
  return p
}
Promise.race([runAsync(1), runAsync(2), runAsync(3)])
  .then(res => console.log('result: ', res))
  .catch(err => console.log(err))

The output results are as follows:

1
'result: ' 1
2
3

Then will only capture the first successful method. Although other functions will continue to execute, they are not captured by then.

17. Code output results

function runAsync(x) {
  const p = new Promise(r =>
    setTimeout(() => r(x, console.log(x)), 1000)
  );
  return p;
}
function runReject(x) {
  const p = new Promise((res, rej) =>
    setTimeout(() => rej(`Error: ${x}`, console.log(x)), 1000 * x)
  );
  return p;
}
Promise.race([runReject(0), runAsync(1), runAsync(2), runAsync(3)])
  .then(res => console.log("result: ", res))
  .catch(err => console.log(err));

The output results are as follows:

0
Error: 0
1
2
3

You can see that after catch catches the first error, the following code is not executed, but it will not be caught again.

Note: if there are asynchronous tasks that will throw exceptions in the array passed in by all and race, only the first error thrown will be caught, and it will be caught by the second parameter of then or the following catch; But it will not affect the execution of other asynchronous tasks in the array.

18. Code output results

async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
}
async function async2() {
  console.log("async2");
}
async1();
console.log('start')

The output results are as follows:

async1 start
async2
start
async1 end

The code execution process is as follows:

  1. First execute the synchronization code async1 start in the function, and then encounter await, which will block the execution of the code behind async1. Therefore, first execute the synchronization code async2 in async2, and then jump out of async1;
  2. After jumping out of async1 function, execute the synchronization code start;
  3. After a round of macro tasks are all executed, execute async1 end after await.

It can be understood here that the statement after await is equivalent to being placed in new Promise, and the statements on the next line and after are equivalent to being placed in promise Then.

19. Code output results

async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
  setTimeout(() => {
    console.log('timer1')
  }, 0)
}
async function async2() {
  setTimeout(() => {
    console.log('timer2')
  }, 0)
  console.log("async2");
}
async1();
setTimeout(() => {
  console.log('timer3')
}, 0)
console.log("start")

The output results are as follows:

async1 start
async2
start
async1 end
timer2
timer3
timer1

The code execution process is as follows:

  1. First, enter async1 and print out async1 start;
  2. After that, you encounter async2, enter async2, encounter timer timer2, join the macro task queue, and then print async2;
  3. Because async2 blocks the execution of the following code, execute the following timer timer3, add it to the macro task queue, and then print start;
  4. Then execute the code behind async2, print out async1 end, encounter timer timer1, and add it to the macro task queue;
  5. Finally, there are three tasks in the macro task queue, in the order of timer2, timer3 and timer1. There are no micro tasks, so all macro tasks are directly executed according to the principle of first in first out.

20. Code output results

async function async1 () {
  console.log('async1 start');
  await new Promise(resolve => {
    console.log('promise1')
  })
  console.log('async1 success');
  return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')

The output results are as follows:

script start
async1 start
promise1
script end

It should be noted here that Promise after await has no return value in async1, that is, its state is always pending, so the contents after await will not be executed, including those after async1 then.

21. Code output results

async function async1 () {
  console.log('async1 start');
  await new Promise(resolve => {
    console.log('promise1')
    resolve('promise1 resolve')
  }).then(res => console.log(res))
  console.log('async1 success');
  return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')

Here is the transformation of the above question and the addition of resolve.

The output results are as follows:

script start
async1 start
promise1
script end
promise1 resolve
async1 success
async1 end

22. Code output results

async function async1() {
  console.log("async1 start");
  await async2();
  console.log("async1 end");
}

async function async2() {
  console.log("async2");
}

console.log("script start");

setTimeout(function() {
  console.log("setTimeout");
}, 0);

async1();

new Promise(resolve => {
  console.log("promise1");
  resolve();
}).then(function() {
  console.log("promise2");
});
console.log('script end')

The output results are as follows:

script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout

The code execution process is as follows:

  1. async1 and async2 functions are defined at the beginning, but they are not executed. The code in script is executed, so script start is printed;
  2. Encounter timer Settimeout, which is a macro task, and add it to the macro task queue;
  3. After that, execute the function async1, and first print out async1 start;
  4. In case of await, execute async2, print out async2, block the execution of the following code, and add the following code to the micro task queue;
  5. Then jump out of async1 and async2, encounter Promise, and print out Promise 1;
  6. When resolve is encountered, add it to the micro task queue, and then execute the following script code to print out script end;
  7. Then it's time to execute the micro task queue. First print async1 end, and then print promise2;
  8. After executing the micro task queue, start to execute the timer in the macro task queue and print out setTimeout.

23. Code output results

async function async1 () {
  await async2();
  console.log('async1');
  return 'async1 success'
}
async function async2 () {
  return new Promise((resolve, reject) => {
    console.log('async2')
    reject('error')
  })
}
async1().then(res => console.log(res))

The output results are as follows:

async2
Uncaught (in promise) error

You can see that if an error is thrown in the async function, the error result will be terminated and the execution will not continue downward.

If you want the code behind the error and deficiency to execute, you can use catch to catch:

async function async1 () {
  await Promise.reject('error!!!').catch(e => console.log(e))
  console.log('async1');
  return Promise.resolve('async1 success')
}
async1().then(res => console.log(res))
console.log('script start')

The output result is:

script start
error!!!
async1
async1 success

24. Code output results

const first = () => (new Promise((resolve, reject) => {
    console.log(3);
    let p = new Promise((resolve, reject) => {
        console.log(7);
        setTimeout(() => {
            console.log(5);
            resolve(6);
            console.log(p)
        }, 0)
        resolve(1);
    });
    resolve(2);
    p.then((arg) => {
        console.log(arg);
    });
}));
first().then((arg) => {
    console.log(arg);
});
console.log(4);

The output results are as follows:

3
7
4
1
2
5
Promise{<resolved>: 1}

The code execution process is as follows:

  1. First enter Promise and print out 3, then enter Promise below and print out 7;
  2. When a timer is encountered, it is added to the macro task queue;
  3. Execute resolve in Promise # p, the status changes to resolved, and the return value is 1;
  4. Execute resolve in Promise first, the status changes to resolved, and the return value is 2;
  5. Encounter p.then, add it to the micro task queue, and encounter first() Then, add it to the task queue;
  6. Execute the external code and print out 4;
  7. In this way, the first round of macro tasks will be executed, and the tasks in the micro task queue will be executed. 1 and 2 will be printed successively;
  8. In this way, the micro task is completed and the next round of macro task is started. There is a timer in the macro task queue. Execute it and print 5. Since the execution has changed to the resolved state, resolve(6) will not be executed again;
  9. Finally, console Log (P) print promise {< resolved >: 1};

25. Code output results

const async1 = async () => {
  console.log('async1');
  setTimeout(() => {
    console.log('timer1')
  }, 2000)
  await new Promise(resolve => {
    console.log('promise1')
  })
  console.log('async1 end')
  return 'async1 success'
} 
console.log('script start');
async1().then(res => console.log(res));
console.log('script end');
Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .catch(4)
  .then(res => console.log(res))
setTimeout(() => {
  console.log('timer2')
}, 1000)

The output results are as follows:

script start
async1
promise1
script end
1
timer2
timer1

The code execution process is as follows:

  1. First, execute the timing belt and print out script start;
  2. When timer timer1 is encountered, add it to the macro task queue;
  3. Then execute Promise and print out Promise 1. Since Promise has no return value, the following code will not be executed;
  4. Then execute the synchronization code and print out script end;
  5. Continue to execute Promise below Then and catch expects the parameter to be a function, where a number is passed in, so value penetration will occur. Pass the value of resolve(1) to the last then and print 1 directly;
  6. The timer will be printed out in the order of two seconds after the micro timer. However, it will be printed out in the order of two seconds after the micro timer.

26. Code output results

const p1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve('resolve3');
    console.log('timer1')
  }, 0)
  resolve('resovle1');
  resolve('resolve2');
}).then(res => {
  console.log(res)  // resolve1
  setTimeout(() => {
    console.log(p1)
  }, 1000)
}).finally(res => {
  console.log('finally', res)
})

The results are as follows:

resolve1
finally  undefined
timer1
Promise{<resolved>: undefined}

It should be noted that p1 printed by the last timer is actually Finally, we know the return value If no error is thrown, the return value of finally will be the return value of the previous Promise by default Finally, the last Promise was But this one then() does not return a value, so the Promise value printed by p1 will be undefined. If a return 1 is added to the bottom of the timer, the value will become 1.

27. Code output results

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')
    })
})

The output results are as follows:

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

(1) The process analysis of the first round of event cycle is as follows:

  • The whole script enters the main thread as the first macro task and encounters console Log, output 1.
  • When setTimeout is encountered, its callback function is distributed to the macro task Event Queue. Temporarily record as setTimeout1.
  • Encountered process Nexttick(), whose callback function is distributed to the micro task Event Queue. Record as process1.
  • If Promise is encountered, new Promise is executed directly and output 7. Then is distributed to the micro task Event Queue. Write then1.
  • setTimeout is encountered again, and its callback function is distributed to the macro task Event Queue, which is recorded as setTimeout2.
Macro task Event QueueMicro task Event Queue
setTimeout1process1
setTimeout2then1

The above table shows the situation of each Event Queue at the end of the first round of event cycle macro task. At this time, 1 and 7 have been output. N1 and N1 found two micro tasks:

  • Execute process1 and output 6.
  • Execute then1 and output 8.

The first round of event cycle officially ends, and the result of this round is output 1, 7, 6 and 8.

(2) The second round of time cycle starts from * * setTimeout1 * * macro task:

  • Output 2 first. Next, I encountered process Nexttick(), which is also distributed to the micro task Event Queue and marked as process2.
  • new Promise immediately executes output 4, and then is also distributed to the micro task Event Queue, marked as then2.
Macro task Event QueueMicro task Event Queue
setTimeout2process2
 then2

At the end of the second round of event cycle macro task, it is found that two micro tasks process2 and then2 can be executed:

  • Output 3.
  • Output 5.

The second round of event cycle ends, and the second round outputs 2, 4, 3 and 5.

(3) The third round of event loop starts. At this time, only setTimeout2 is left. Execute.

  • Direct output 9.
  • Set process Nexttick() is distributed to the micro task Event Queue. Record as process3.
  • Execute new Promise directly and output 11.
  • Distribute then to the micro task Event Queue and record it as then3.
Macro task Event QueueMicro task Event Queue
 process3
 then3

The third round of event loop macro task execution ends, and two micro tasks process3 and then3 are executed:

  • Output 10.
  • Output 12.

The third round of event cycle ends, and the third round outputs 9, 11, 10 and 12.

The whole code has three event cycles, and the complete output is 1, 7, 6, 8, 2, 4, 3, 5, 9, 11, 10 and 12.

28. Code output results

console.log(1)

setTimeout(() => {
  console.log(2)
})

new Promise(resolve =>  {
  console.log(3)
  resolve(4)
}).then(d => console.log(d))

setTimeout(() => {
  console.log(5)
  new Promise(resolve =>  {
    resolve(6)
  }).then(d => console.log(d))
})

setTimeout(() => {
  console.log(7)
})

console.log(8)

The output results are as follows:

1
3
8
4
2
5
6
7

The code execution process is as follows:

  1. First, execute the script code and print out 1;
  2. When the first timer is encountered, it is added to the macro task queue;
  3. When you encounter Promise, execute the code, print out 3, and when you encounter resolve, add it to the micro task queue;
  4. When the second timer is encountered, it is added to the macro task queue;
  5. When the third timer is encountered, it is added to the macro task queue;
  6. Continue to execute the script code, print out 8, and the first round of execution ends;
  7. Execute the micro task queue and print the resolve result of the first Promise: 4;
  8. Start executing macro task queue, execute the first timer and print out 2;
  9. At this time, there is no micro task. Continue to execute the second timer in the macro task. Print 5 first. If you encounter Promise, print 6 first. If you encounter resolve, add it to the micro task queue;
  10. Execute the micro task queue and print out 6;
  11. Execute the last timer in the macro task queue and print out 7.

29. Code output results

console.log(1);
    
setTimeout(() => {
  console.log(2);
  Promise.resolve().then(() => {
    console.log(3)
  });
});

new Promise((resolve, reject) => {
  console.log(4)
  resolve(5)
}).then((data) => {
  console.log(data);
})

setTimeout(() => {
  console.log(6);
})

console.log(7);

The code output results are as follows:

1
4
7
5
2
3
6

The code execution process is as follows:

  1. First, execute the scrip t code and print out 1;
  2. Encounter the first timer setTimeout and add it to the macro task queue;
  3. In case of Promise, execute the synchronization code inside, print out 4, and in case of resolve, add it to the micro task queue;
  4. Encounter the second timer setTimeout and add it to the red task queue;
  5. Execute the script code and print out 7. So far, the first round of execution is completed;
  6. Specify the code in the micro task queue and print the result of resolve: 5;
  7. Execute the first timer setTimeout in the macro task, print out 2 first, and then encounter {promise resolve(). Then (), add it to the micro task queue;
  8. After executing the macro task, start to execute the micro task queue and print out 3;
  9. Continue to execute the second timer in the macro task queue and print out 6.

30. Code output results

Promise.resolve().then(() => {
    console.log('1');
    throw 'Error';
}).then(() => {
    console.log('2');
}).catch(() => {
    console.log('3');
    throw 'Error';
}).then(() => {
    console.log('4');
}).catch(() => {
    console.log('5');
}).then(() => {
    console.log('6');
});

The results are as follows:

1 
3 
5 
6

In this topic, we need to know that in both thne and catch, as long as throw throws an error, it will be caught by catch. If there is no throw error, it will continue to execute the following then.

31. Code output results

setTimeout(function () {
  console.log(1);
}, 100);

new Promise(function (resolve) {
  console.log(2);
  resolve();
  console.log(3);
}).then(function () {
  console.log(4);
  new Promise((resove, reject) => {
    console.log(5);
    setTimeout(() =>  {
      console.log(6);
    }, 10);
  })
});
console.log(7);
console.log(8);

The output result is:

2
3
7
8
4
5
6
1

The code execution process is as follows:

  1. First, the timer is encountered and added to the macro task queue;
  2. When you encounter Promise, first execute the synchronization code inside and print out 2. When you encounter resolve, add it to the micro task queue, execute the following synchronization code and print out 3;
  3. Continue to execute the code in the script, print out 7 and 8, and the first round of code execution is completed;
  4. To execute the code in the micro task queue, first print out 4. If Promise is encountered, execute the synchronization code and print out 5. If timer is encountered, add it to the macro task queue. At this time, there are two timers in the macro task queue;
  5. Execute the code in the macro task queue. Here we need to note that the time of the first timer is 100ms and the time of the second timer is 10ms, so execute the second timer first and print 6;
  6. At this time, the micro task queue is empty. Continue to execute the macro task queue and print 1.

After finishing this topic, we need to pay special attention to that the time of each timer is not 0 for all timers.

2, this

1. Code output result

function foo() {
  console.log( this.a );
}

function doFoo() {
  foo();
}

var obj = {
  a: 1,
  doFoo: doFoo
};

var a = 2; 
obj.doFoo()

Output result: 2

In Javascript, this points to the current object when the function is executed. When executing foo, the execution environment is the doFoo function, and the execution environment is global. Therefore, this in foo points to window, so 2 will be printed.

2. Code output results

var a = 10
var obj = {
  a: 20,
  say: () => {
    console.log(this.a)
  }
}
obj.say() 

var anotherObj = { a: 30 } 
obj.say.apply(anotherObj) 

Output result: 10

We know that the arrow function does not bind this. Its this comes from the context of its parent, so the value of a in the global will be printed first. Later, although the say method points to another object, it still cannot change the characteristics of the arrow function. Its this still points to the global, so it will still output 10.

However, if it is an ordinary function, it will have completely different results:

var a = 10  
var obj = {  
  a: 20,  
  say(){
    console.log(this.a)  
  }  
}  
obj.say()   
var anotherObj={a:30}   
obj.say.apply(anotherObj)

Output result: 20 30

At this time, this in the say method will point to the object where it is located and output the value of a.

3. Code output results

function a() {
  console.log(this);
}
a.call(null);

Print results: window object

According to ECMAScript262 specification: if the object caller passed in by the first parameter is null or undefined, the call method will take the global object (window object on the browser) as the value of this. Therefore, whether null or undefined is passed in, this is the global object window. Therefore, on the browser, the answer is to output the window object.

Note that in strict mode, null is null and undefined is undefined:

'use strict';

function a() {
    console.log(this);
}
a.call(null); // null
a.call(undefined); // undefined

4. Code output results

var obj = { 
  name : 'cuggz', 
  fun : function(){ 
    console.log(this.name); 
  } 
} 
obj.fun()     // cuggz
new obj.fun() // undefined

When using the new constructor, this refers to the global environment window.

6. Code output results

var obj = {
   say: function() {
     var f1 = () =>  {
       console.log("1111", this);
     }
     f1();
   },
   pro: {
     getPro:() =>  {
        console.log(this);
     }
   }
}
var o = obj.say;
o();
obj.say();
obj.pro.getPro();

Output result:

1111 window object
1111 obj object
window object

Resolution:

  1. o(), o is executed globally, while f1 is an arrow function. It is not bound to this. Its this points to its parent's this, and its parent say method's this points to the global scope, so it will print out window;
  2. obj.say(), this of say points to whoever calls say, so this points to obj object at this time;
  3. obj.pro.getPro(), we know that the arrow function does not bind this, getPro is in Pro, and the object does not form a separate scope, so this of the arrow function points to the global scope window.

7. Code output results

var myObject = {
    foo: "bar",
    func: function() {
        var self = this;
        console.log(this.foo);  
        console.log(self.foo);  
        (function() {
            console.log(this.foo);  
            console.log(self.foo);  
        }());
    }
};
myObject.func();

Output result: bar undefined bar

Resolution:

  1. First, func is called by myObject, and this points to myObject. Because var self = this; So self points to myObject.
  2. This immediate anonymous function expression is called by window, and this points to window. The scope of the anonymous function to execute immediately is myObject In the scope of func, the self variable cannot be found in this scope. Look up the self variable along the scope chain and find the self pointing to the myObject object.

8. Code output problem

window.number = 2;
var obj = {
 number: 3,
 db1: (function(){
   console.log(this);
   this.number *= 4;
   return function(){
     console.log(this);
     this.number *= 5;
   }
 })()
}
var db1 = obj.db1;
db1();
obj.db1();
console.log(obj.number);     // 15
console.log(window.number);  // 40

This topic looks a little messy, but it is actually pointed by this:

  1. When db1() is executed, this points to the global scope, so window Number * 4 = 8, and then execute the anonymous function, so window number * 5 = 40;
  2. Execute obj db1(); When, this points to the obj object and executes anonymous functions, so obj numer * 5 = 15.

9. Code output results

var length = 10;
function fn() {
    console.log(this.length);
}
 
var obj = {
  length: 5,
  method: function(fn) {
    fn();
    arguments[0]();
  }
};
 
obj.method(fn, 1);

Output result: 10 2

Resolution:

  1. Execute fn() for the first time. this points to the window object and outputs 10.
  2. Execute arguments for the second time 0 , which is equivalent to the method called by arguments. this points to arguments, and two parameters are passed here. Therefore, the length of output arguments is 2.

10. Code output results

var a = 1;
function printA(){
  console.log(this.a);
}
var obj={
  a:2,
  foo:printA,
  bar:function(){
    printA();
  }
}

obj.foo(); // 2
obj.bar(); // 1
var foo = obj.foo;
foo(); // 1

Output result: 2 1 1

Resolution:

  1. obj.foo(), this of foo points to obj object, so a will output 2;
  2. obj.bar(), printA is executed in the bar method, so this of printA points to window, so 1 will be output;
  3. foo(), foo is executed in the global object, so its this points to window, so it will output 1;

11. Code output results

var x = 3;
var y = 4;
var obj = {
    x: 1,
    y: 6,
    getX: function() {
        var x = 5;
        return function() {
            return this.x;
        }();
    },
    getY: function() {
        var y = 7;
        return this.y;
    }
}
console.log(obj.getX()) // 3
console.log(obj.getY()) // 6

Output result: 3 6

Resolution:

  1. We know that this of the anonymous function points to the global object, so this points to window and will print 3;
  2. getY is called by obj, so its this points to the obj object, and 6 will be printed.

12. Code output results

 var a = 10; 
 var obt = { 
   a: 20, 
   fn: function(){ 
     var a = 30; 
     console.log(this.a)
   } 
 }
 obt.fn();  // 20
 obt.fn.call(); // 10
 (obt.fn)(); // 20

Output result: 20 10 20

Resolution:

  1.  obt.fn(), fn is called by obt, so its this points to the obt object and 20 will be printed;
  2.  obt.fn.call(), where the call parameter is not written, which means null. We know that if the call parameter is undefined or null, this will point to the global object this, so 10 will be printed;
  3. (obt.fn)(), parentheses are added to the expression, and the function of parentheses is to change the operation order of the expression, but whether parentheses are added or not has no effect; Equivalent to # obt FN (), so 20 will be printed;

13. Code output results

function a(xx){
  this.x = xx;
  return this
};
var x = a(5);
var y = a(6);

console.log(x.x)  // undefined
console.log(y.x)  // 6

Output result: undefined 6

Resolution:

  1. The key is var x = a(5). Function a is called in the global scope, so this inside the function points to the window object** So this X = 5 is equivalent to: window x = 5. ** Then return this, that is, the value of the X variable in var x = a(5) is window, where x overrides the value of X inside the function. Then execute console Log (x.x), that is, console Log (window. X), but there is no X attribute in the window object, so undefined will be output.
  2. When pointing to y.x, X in the global variable will be assigned 6, so 6 will be printed.

14. Code output results

function foo(something){
    this.a = something
}

var obj1 = {
    foo: foo
}

var obj2 = {}

obj1.foo(2); 
console.log(obj1.a); // 2

obj1.foo.call(obj2, 3);
console.log(obj2.a); // 3

var bar = new obj1.foo(4)
console.log(obj1.a); // 2
console.log(bar.a); // 4

Output result: 2 3 2 4

Resolution:

  1. First execute obj 1 foo(2); The a attribute will be added to obj with a value of 2. Then execute obj 1 a. A is called by right obj1, so this points to obj and prints 2;
  2. Execute obj 1 foo. When calling (obj2, 3), this of foo will point to obj2, which is the same as the above, so 3 will be printed;
  3. obj1.a will print out 2;
  4. Finally, check the priority of this binding. new binding has higher priority than implicit binding, so 4 will be output.

15. Code output results

function foo(something){
    this.a = something
}

var obj1 = {}

var bar = foo.bind(obj1);
bar(2);
console.log(obj1.a); // 2

var baz = new bar(3);
console.log(obj1.a); // 2
console.log(baz.a); // 3

Output result: 2 2 3

This topic is similar to the above topics. It mainly focuses on the priority of this binding. Just remember the following conclusion: the priority of this binding: new binding > explicit binding > implicit binding > default binding.

3, Scope & variable promotion & closure

1. Code output result

(function(){
   var x = y = 1;
})();
var z;

console.log(y); // 1
console.log(z); // undefined
console.log(x); // Uncaught ReferenceError: x is not defined

The key of this code is: var x = y = 1; In fact, it is executed from right to left. First, y = 1 is executed. Because y does not use var declaration, it is a global variable. Then, the second step is to assign y to X. say that a global variable is assigned to a local variable. Finally, X is a local variable and y is a global variable, so printing x is an error.

2. Code output results

var a, b
(function () {
   console.log(a);
   console.log(b);
   var a = (b = 3);
   console.log(a);
   console.log(b);   
})()
console.log(a);
console.log(b);

Output result:

undefined 
undefined 
3 
3 
undefined 
3

This topic is similar to the knowledge points investigated in the above topic. b is assigned as 3, b is a global variable at this time, and 3 is assigned to a, a is a local variable, so at the last printing, a is still undefined.

3. Code output results

var friendName = 'World';
(function() {
  if (typeof friendName === 'undefined') {
    var friendName = 'Jack';
    console.log('Goodbye ' + friendName);
  } else {
    console.log('Hello ' + friendName);
  }
})();

Output result: Goodbye Jack

We know that in JavaScript, both Function and var will be promoted (variable promotion), so the above code is equivalent to:

var name = 'World!';
(function () {
    var name;
    if (typeof name === 'undefined') {
        name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();

In this way, the answer is clear at a glance.

4. Code output results

function fn1(){
  console.log('fn1')
}
var fn2
 
fn1()
fn2()
 
fn2 = function() {
  console.log('fn2')
}
 
fn2()

Output result:

fn1
Uncaught TypeError: fn2 is not a function
fn2

Here we are also examining the variable promotion. The key lies in the first fn2(). At this time, fn2 is still an undefined variable, so an error will be reported. fn2 is not a function.

5. Code output results

function a() {
    var temp = 10;
    function b() {
        console.log(temp); // 10
    }
    b();
}
a();

function a() {
    var temp = 10;
    b();
}
function b() {
    console.log(temp); // Uncaught ReferenceError: temp is not defined
}
a();

In the above two sections of code, the first section can be output normally, which should be no problem. The key lies in the second section of code, which will report an error Uncaught ReferenceError: temp is not defined. At this time, the value of temp is undefined when the b method is executed.

6. Code output results

 var a=3;
 function c(){
    alert(a);
 }
 (function(){
  var a=4;
  c();
 })();

The scope chain of variables in js is related to the environment at the time of definition and has nothing to do with the execution time. The execution environment will only change this, passed parameters, global variables, etc

7. Code output problem

function fun(n, o) {
  console.log(o)
  return {
    fun: function(m){
      return fun(m, n);
    }
  };
}
var a = fun(0);  a.fun(1);  a.fun(2);  a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1);  c.fun(2);  c.fun(3);

Output result:

undefined  0  0  0
undefined  0  1  2
undefined  0  1  1

For the object returned by the method called fun, it is about a closure. We know that when calling a function, the number of arguments passed in is less than that specified in the function declaration, and the remaining formal parameters will be set to undefined value. So, console log(o); Undefined will be output. A is the object returned by fun(0). In other words, the value of parameter n in function fun is 0, and the returned object needs a parameter n, but the scope of this object does not have n, so it continues to look for N in the scope of the upper level along the scope, and finally finds n in function fun, and the value of n is 0. Knowing this, other operations are very simple, and so on.

8. Code output results

f = function() {return true;};   
g = function() {return false;};   
(function() {   
   if (g() && [] == ![]) {   
      f = function f() {return false;};   
      function g() {return true;}   
   }   
})();   
console.log(f());

Output result: false

Here we first define two variables f and g. we know that variables can be re assigned. An anonymous self executing function is followed by calling function g() in the if condition. Because the function g is redefined in the anonymous function, it covers the variable g defined externally, so the internal function g method is called here, and it is returned to true. The first condition passes and enters the second condition.

The second condition is [] = =! [], look first! [] in JavaScript, when used for Boolean operations, for example, here, the non empty reference of the object is regarded as true, and the null reference is regarded as false. Since this is not a null, but an array without elements, [] is regarded as true, and! The result of [] is false. When a Boolean value participates in the conditional operation, true will be regarded as 1 and false will be regarded as 0. Now the condition becomes [] = = 0. When an object participates in the condition comparison, it will be evaluated. The evaluation result is that the array becomes a string, the result of [] is' ', and' 'will be treated as 0. Therefore, the condition holds.

Both conditions are true, so the code in the condition will be executed. F does not use var in the definition, so it is a global variable. Therefore, the external variable f will be accessed through the closure and re assigned. Now the return value of executing the F function has become false. G will not have this problem. Here is g defined in a function, which will not affect the external g function. So the final result is false.

4, Prototype & Inheritance

1. Code output result

function Person(name) {
    this.name = name
}
var p2 = new Person('king');
console.log(p2.__proto__) //Person.prototype
console.log(p2.__proto__.__proto__) //Object.prototype
console.log(p2.__proto__.__proto__.__proto__) // null
console.log(p2.__proto__.__proto__.__proto__.__proto__)//null is not followed by an error
console.log(p2.__proto__.__proto__.__proto__.__proto__.__proto__)//null is not followed by an error
console.log(p2.constructor)//Person
console.log(p2.prototype)//undefined p2 is an instance and has no prototype attribute
console.log(Person.constructor)//Function is an empty function
console.log(Person.prototype)//Print out person All the methods and properties in the prototype object
console.log(Person.prototype.constructor)//Person
console.log(Person.prototype.__proto__)// Object.prototype
console.log(Person.__proto__) //Function.prototype
console.log(Function.prototype.__proto__)//Object.prototype
console.log(Function.__proto__)//Function.prototype
console.log(Object.__proto__)//Function.prototype
console.log(Object.prototype.__proto__)//null

This topic examines the prototype and the basis of the prototype chain. Just remember.

2. Code output results

// a
function Foo () {
 getName = function () {
   console.log(1);
 }
 return this;
}
// b
Foo.getName = function () {
 console.log(2);
}
// c
Foo.prototype.getName = function () {
 console.log(3);
}
// d
var getName = function () {
 console.log(4);
}
// e
function getName () {
 console.log(5);
}

Foo.getName();           // 2
getName();               // 4
Foo().getName();         // 1
getName();               // 1 
new Foo.getName();       // 2
new Foo().getName();     // 3
new new Foo().getName(); // 3

Output result: 2 4 1 1 2 3 3

Resolution:

  1. Foo.getName(), foo is a function object, and all objects can have attributes. The getName attribute of foo defined at b is a function, output 2;
  2. getName(), look at places d and e here. d is the function expression and E is the function declaration. The difference between the two is that the variable is raised, and the 5 of the function declaration will be overwritten by the 4 of the later function expression;
  3. ** Foo().getName(), * * here we need to look at part a. in foo, re assign the global getName to console Log (1), execute foo() to return this, which points to window, foo() getName() is window getName(), output 1;
  4. getName(), in 3 above, the global getName has been re assigned, so 1 is still output here;
  5. new Foo.getName(), which is equivalent to Foo.getName(), execute Foo.getName() first Getname(), output 2, and then new an instance;
  6. new Foo().getName(), which is equivalent to (New foo()) getName(), first create a new instance of foo, and then execute the getName method of this instance, but this instance does not have this method, so go to the prototype chain__ protot__ Look for examples above protot === Foo.prototype, so output 3;
  7. new new Foo().getName(), which is equivalent to new (New foo() Getname()), as described in 6 above, first output 3, and then new foo() Instance of getname().

3. Code output results

var F = function() {};
Object.prototype.a = function() {
  console.log('a');
};
Function.prototype.b = function() {
  console.log('b');
}
var f = new F();
f.a();
f.b();
F.a();
F.b()

Output result:

a
Uncaught TypeError: f.b is not a function
a
b

Resolution:

  1. f is not an instance of Function, because it is not a constructor. It calls the relevant properties and methods on the Function prototype chain, and can only access the Object prototype chain. Therefore, f.a() outputs a, while f.b() reports an error.
  2. F is a constructor, and F is an instance of the constructor Function. Because F instanceof {Object === true, F instanceof Function === true, it can be concluded that f is an instance of Object and Function, that is, f can access a and b. So F.a() outputs a and F.b() outputs b.

4. Code output results

function Foo(){
    Foo.a = function(){
        console.log(1);
    }
    this.a = function(){
        console.log(2)
    }
}

Foo.prototype.a = function(){
    console.log(3);
}

Foo.a = function(){
    console.log(4);
}

Foo.a();
let obj = new Foo();
obj.a();
Foo.a();

Output result: 4 2 1

Resolution:

  1. Foo.a() this is the static method a that calls foo function. Although there is a higher priority attribute method a in foo, foo is not called at this time, so the result of Foo's static method a is output at this time: 4
  2. let obj = new Foo(); The new method is used to call the function and return the function instance object. At this time, the attribute method inside the foo function is initialized and the prototype chain is established.
  3. obj.a() ; Call method a on the obj instance, which currently has two a methods: one is the internal attribute method, and the other is the method on the prototype. When both exist, first find the ownProperty. If not, go to the prototype chain, so call the a output on the instance: 2
  4. Foo.a() ; The method with the same name has been initialized according to the property of foo in step 2, so it is known that the method with the same name has been initialized according to the property of foo in step 2

5. Code output results

function Dog() {
  this.name = 'puppy'
}
Dog.prototype.bark = () => {
  console.log('woof!woof!')
}
const dog = new Dog()
console.log(Dog.prototype.constructor === Dog && dog.constructor === Dog && dog instanceof Dog)

Output result: true

Parsing: because constructor is an attribute on prototype, dog The constructor actually points to dog prototype. constructor; The constructor property points to the constructor. instanceof actually detects whether the type is on the prototype chain of the instance.

Constructor is an attribute on prototype, which is easy to ignore. The functions of constructor and instanceof are different. Perceptually, constructor has strict restrictions. It can only strictly compare whether the constructor of the object is the specified value; Instanceof is relatively loose. As long as the detected type is on the prototype chain, it will return true.

6. Code output results

var A = {n: 4399};
var B =  function(){this.n = 9999};
var C =  function(){var n = 8888};
B.prototype = A;
C.prototype = A;
var b = new B();
var c = new C();
A.n++
console.log(b.n);
console.log(c.n);

Output result: 9999 4400

Resolution:

  1. console.log(b.n). When looking for b.n, first look for whether the B object itself has the N attribute. If not, it will go to the prototype to look for it. When var b = new B() is executed, this N = 9999 (this points to B at this time) returns the B object. The B object has its own n attribute, so 9999 is returned.
  2. console.log(c.n). Similarly, when var c = new C() is executed, the C object does not have its own n attribute. Look up and find the N attribute on the prototype. Because A.n + + (at this time, N in object A is 4400), 4400 is returned.

7. Code output problem

function A(){
}
function B(a){
  this.a = a;
}
function C(a){
  if(a){
this.a = a;
  }
}
A.prototype.a = 1;
B.prototype.a = 1;
C.prototype.a = 1;
 
console.log(new A().a);
console.log(new B().a);
console.log(new C(2).a);

Output result: 1 undefined 2

Resolution:

  1. console.log(new A().a) , the object created by new a() for the constructor has no a attribute, so go to its prototype and find that the attribute value of the a attribute of the prototype is 1, so the output value is 1;
  2. console.log(new B().a) , ew B() is the object created by the constructor. The constructor has parameter a, but the object does not pass parameters, so the output value is undefined;
  3. console.log(new C(2).a) , new C() is the object created by the constructor. The constructor has parameter a and the argument passed is 2. Execute the function internally. if is found to be true, execute this A = 2, so the value of attribute a is 2.

8 code output problem

function Parent() {
    this.a = 1;
    this.b = [1, 2, this.a];
    this.c = { demo: 5 };
    this.show = function () {
        console.log(this.a , this.b , this.c.demo );
    }
}

function Child() {
    this.a = 2;
    this.change = function () {
        this.b.push(this.a);
        this.a = this.b.length;
        this.c.demo = this.a++;
    }
}

Child.prototype = new Parent();
var parent = new Parent();
var child1 = new Child();
var child2 = new Child();
child1.a = 11;
child2.a = 12;
parent.show();
child1.show();
child2.show();
child1.change();
child2.change();
parent.show();
child1.show();
child2.show();

Output result:

parent.show(); // 1  [1,2,1] 5

child1.show(); // 11 [1,2,1] 5
child2.show(); // 12 [1,2,1] 5

parent.show(); // 1 [1,2,1] 5

child1.show(); // 5 [1,2,1,11,12] 5

child2.show(); // 6 [1,2,1,11,12] 5

This topic is worthy of God Emperor. He involves many knowledge points, such as the direction of this, prototype, prototype chain, class inheritance, data type, etc.

Resolution:

  1. parent.show(), you can get the required value directly. There's nothing to say;
  2. child1.show(), the constructor of Child originally points to Child. The title explicitly points the prototype object of Child class to an instance of parent class. Please note that Child Prototype refers to the instance of parent, not the class of parent.
  3. child2.show(), there's nothing to say about this;
  4. parent.show(), parent is an instance of the parent class, child The prototype refers to another instance of the parent class. The two do not affect each other in the heap memory, so the above operations do not affect the parent instance, so the output result remains unchanged;
  5. child1.show(), what happens after Child1 executes the change() method?
  • this.b.push(this.a). Due to the dynamic pointing characteristics of this, this B will point to child B array on prototype, this A will point to the a attribute of child1, so child prototype. B becomes * * [1,2,1,11] * *;
  • this.a = this.b.length, this A and this The direction of B is consistent with the previous sentence, so the result is Child1 A becomes 4;
  • this.c.demo = this.a + +, since child1 has no C attribute, this C will point to child prototype. c,this. The value of a is 4, which is the original type, so it will be assigned directly during assignment operation, child prototype. c. The result of demo is 4, while this A then increases to 5 (4 + 1 = 5).
  1. Child2 executes the change() method, and both child2 and child1 are instances of the child class, so their prototype chain points to the same prototype object child Prototype, that is, the same parent instance, so child2 All statements in change() that affect the prototype object will affect the final output of child1.
  • this.b.push(this.a). Due to the dynamic pointing characteristics of this, this B will point to child B array on prototype, this A will point to the a attribute of child2, so child prototype. B becomes * * [1,2,1,11,12] * *;
  • this.a = this.b.length, this A and this The direction of B is consistent with the previous sentence, so the result is child2 A becomes 5;
  • this.c.demo = this.a + +, since child2 has no C attribute, this C will point to child prototype. c. Therefore, the execution result is child prototype. c. The value of demo becomes child2 The value of a is 5, while child2 A finally increases to 6 (5 + 1 = 6).

9. Code output results

function SuperType(){
    this.property = true;
}

SuperType.prototype.getSuperValue = function(){
    return this.property;
};

function SubType(){
    this.subproperty = false;
}

SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
    return this.subproperty;
};

var instance = new SubType();
console.log(instance.getSuperValue());

Output result: true

In fact, this code is implementing prototype chain inheritance. SubType inherits SuperType, which essentially rewrites the prototype object of SubType and replaces it with an instance of a new type. The prototype of SubType has been rewritten, so instance The constructor points to a SuperType. The details are as follows:

Write at the end:

Thank you for your patience. After reading such a long article. Is there any gain from reading here? I have to say that these interview questions are really a test of people's basic JavaScript ability, especially the later prototype and inheritance related questions, which are too convoluted and worthy of careful study!

Recently, the author is busy with his graduation thesis, which may be updated slowly. Please forgive me.

If you think this article is helpful, remember to praise it.

Topics: Javascript Interview