[fed-task-01-01] ES new features, asynchronous, TypeScript

Posted May 26, 20208 min read

Short answer questions

Question 1

Please state the final execution result of the following code and explain why?

var a = [];
for(var i = 0; i <10; i ++) {
    a [i]= function() {
        console.log(i);
    }
}
a [6]();

The final execution result is:print 10.

Reason:during the for loop, use var to define the loop variable i(there is a variable promotion), and then assign a function to the a array element in sequence, and print i in the function; calling a [6]() after the loop ends, which is equivalent to Print i in the global environment, and now i has become 10.

Question 2

Please state the final execution result of the following code and explain why?

var temp = 123;
if(true) {
    console.log(tmp);
    let tmp;
}

The final execution result is:a reference error is reported, and 'tmp' cannot be accessed before initialization.

The reason is that when the let/const keyword is used to declare variables in block-level scope, there is a temporary dead zone, and using these variables before the declaration will report an error.
ES6 clearly stipulates that if let and const commands exist in the block, the variables declared by these commands in this block form a closed scope from the beginning. Any use of these variables before declaration will result in an error.

Question 3

Combined with ES6 new syntax, find the smallest value in the array in the simplest way?

var arr = [12, 34, 32, 89, 4];

Answer:Math.min(... arr)

Question 4

Please explain in detail the specific differences between the three ways of declaring variables var, let, const?

  1. Use var to declare variables
  • There is a case of variable promotion
  • Access to variables defined in the subsequent will return undefined
  • Variables declared by var can be accessed in other scopes
  1. Use let to declare variables
  • Using the let command will create a block-level scope
  • Variables declared by let are only valid in block scope
  • In the same scope, variables cannot be declared repeatedly using let
  1. Use const to declare constants
  • Constants declared using const cannot be modified
  • Assignment is required when using const to declare a constant
  • Use const to declare a constant that references type data, you can add/delete/modify attributes to this constant, but you cannot directly modify the value of this constant(the memory address cannot be modified)

Question 5

Please state the final execution result of the following code and explain why?

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

The final execution result is:print out 20.

Reason:The callback of setTimeout is an arrow function, the arrow function will not change the direction of this. this always points to the first function looking up along the scope, to see how this function is eventually called. The title is called obj.fn() in this way, so this in fn points to obj.

Question 6

Briefly describe the purpose of the Symbol type?

Symbol is a new type of original data proposed by ES2015. The main uses are:

  • Create unique key values ​​for objects
  • Can simulate the private members of the realization object
  • Can be used as a constant

Question 7

Talk about what is a shallow copy? What is a deep copy?

In the process of assigning the data of the reference type, the memory address is actually copied. For example, the b object is assigned to the a variable. Both variables point to the same memory address. After the a variable is modified, the b object will also change. What we hope to get is that modifying a will not affect b, and these two objects will not affect each other. For this kind of scene, you can use shallow copy and deep copy.

Shallow copying refers to copying all the attribute values ​​of an object to a new object to perform a layer of attribute copying, but if the attribute value is also an object, the address of that object is still copied, and the above problem will still occur. This situation can be solved by using deep copy. Even if the attribute value is an object, deep copy can also achieve unlimited hierarchical copying, cutting off the relationship between two reference type variables without affecting each other.

Shallow copy method:traversing object property assignment, Object.assign(), spread operator ...

Deep copy method:shallow copy + recursion, JSON.parse(JSON.stringify(obj))

The JSON.parse(JSON.stringify()) method has certain limitations:
Note the following when serializing:

  • Time object => string form
  • RegExp, Error => {}
  • Will lose function, undefined
  • NaN, Infinity, -Infinity => null
  • If there is a circular reference in the object, the deep copy cannot be achieved

The ultimate deep copy method can refer to the deep copy of lodash, but if you do not encounter the above situation in daily development, using JSON.parse(JSON.stringify()) is enough ...

Question 8

Talk about how do you understand JS asynchronous programming, what does EventLoop do, what is a macro task, what is a micro task?

JS is single-threaded and can only do one thing at a time. Two pieces of JS cannot be executed at the same time. The main reason is to avoid conflicts in DOM rendering. The solution is asynchronous, and the asynchronously written code is not executed according to the writing method, and there are too many callbacks, which leads to poor readability and difficulty in understanding, so there is a promise/async await.

EventLoop refers to event polling, which is a specific solution of js to achieve asynchronous. The synchronization code is directly executed in the main thread(call stack), and the stack is pushed to the stack. Asynchronous tasks will be placed in the message queue(Queue) in sequence. EventLoop will monitor the call stack and the message queue. When the code in the call stack is executed, it will take the first task in the message queue to the call stack for execution. And so on.

Asynchronous tasks can be divided into macro tasks and micro tasks, and the execution order of these two tasks is different. Macro tasks will be put into the message queue in turn to wait for event polling to be executed, while micro tasks are placed at the end of the call stack to be executed, that is, micro tasks are executed before macro tasks.

  • Macro task:At present, most asynchronous calls are executed as macro tasks
  • Micro tasks:Promise, MutationObserver, process.nextTick in node

Question 9

Will the following asynchronous code be improved using Promise?

setTimeout(function() {
    var a = 'hello';
    setTimeout(function() {
        var b = 'lagou';
        setTimeout(function() {
            var c = 'I Love U';
            console.log(a + b + c);
        }, 10);
    }, 10);
}, 10);

answer:

function task(msg) {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            resolve(msg);
        }, 10);
    });
};

task('hello')
    .then(msg => task(msg + 'lagou'))
    .then(msg => task(msg + 'I Love U'))
    .then(msg => console.log(msg));

Question 10

Please briefly describe the relationship between TypeScript and JavaScript?

TypeScript is a superset(extension set) of JavaScript. It is based on JS and has some additional extension features. These extension features include:a powerful type system and good support for ES6 +. TS will eventually be compiled into JS and run.

Question 11

What are the advantages and disadvantages of TypeScript in your opinion?

advantage:

  1. Use TS new features to develop the project, the robustness of the project code is enhanced, and the code errors are exposed earlier.
  2. The editor support is good, for example:VSCode, there are many intelligent tips, the coding is more accurate, and the development efficiency is improved.
  3. Using TS's strongly typed features to develop projects can make project code reconstruction more reliable.
  4. Use the strongly typed features of TS to write code, which can reduce many unnecessary type judgments.
  5. TS will eventually be compiled into JS to run, and ES6 + can be compiled into ES5/ES3 with good compatibility.
  6. TS is gradual, you can use JS to write code, and you can slowly apply new features to the project.

Disadvantages:

  1. Introduce many concepts and new grammar, there is a certain learning cost, for some small projects will increase the development cost
  2. If you encounter problems during the development process, the online information about TS may be less than that of JS. You need to spend some effort to find the information to solve the problem

Study notes

1 New features of ECMAScript

Proxy object

The advantages of Proxy over Object.defineProperty()?

  • In addition to set and get monitoring, Proxy also has other monitoring callbacks for objects. has deleteProperty ownKeys apply and so on
  • Proxy better supports monitoring of array objects
  • Proxy supervises the reading and writing of objects in a non-intrusive way

Reflect object

Reflect provides a unified API for manipulating objects
When operating an object, it is possible to use the methods on Object, and it is also possible to use operators such as delete in, which are very chaotic and irregular for novices.
And Reflect solves this problem, it unifies the operation mode of the object

Set

Array deduplication

const arr = [1, 2, 1, 3, 4, 1];
//const result = Array.from(new Set(arr));
const result = [... new Set(arr)];

Map

The biggest difference between Map and Object:
Map can use any data type as a key
Object can only use strings as keys

Symbol

Use Symbol as the key of the object, the main function is to add a unique value to the object

As of ES2019, ECMAScript has defined a total of 6 primitive types
string number boolean undefined null symbol
Plus the object data type is a total of 7 data types, in the future there will be a new original type, BigInt, ready to be released in ES2020

for ... of loop

The for ... of loop method will be used as a unified way to traverse all data structures in the future

//arr.forEach() //can not jump out of the loop, unless the error is actively reported
//arr.some();
//arr.every();

const arr = [100, 200, 300, 400];
for(const item of arr) {
    console.log(item);
    if(item> 100) {
        break; //You can use the break keyword to jump out of the loop
    }
}

Iterator

All data types that can be traversed by for ... of must implement an Iterator interface

2 JavaScript asynchronous programming

Promise

Promise object's then method will return a brand new Promise object
The later then method is to register the callback for the promise returned by the last then
The return value of the callback function in the previous then method will be used as the parameter of the subsequent then method callback
If the callback returns a Promise, then the callback of the then method will wait for its end

You can use Promise.race to implement request timeout

//The way to achieve request timeout, if a request does not respond within 500ms, it is considered timeout
const promise = ajax('/api/users.json');
const timeout = new Promise((resolve, reject) => {
    setTimeout(() => reject(new Error('timeout')), 500);
});

Promise.race([
    promise,
    timeout

])
.then(value => {
console.log(value);
})
.catch(error => {
console.log(error);
});

Macro tasks and micro tasks

The tasks in the callback queue are called "macro tasks"
During the execution of the macro task, some additional requirements can be added temporarily. You can choose to enter the queue as a new macro task, or you can use it as a micro task of the current task, and execute it immediately after the current task ends.
promise's callback will be executed as a micro task
The purpose of microtasking is to improve the overall responsiveness of the application

Macro tasks:At present, most asynchronous calls are executed as macro tasks
Microtasks:process.nextTick in Promise & MutationObserver & node

3 TypeScript

Display Chinese error message

input the command
yarn tsc --locale zh-CN

VSCode setting options
settings => typescript locale => zh-CN

Enumeration

If the enumerated keys are not assigned, the default is to increase from 0
Two-way key-value pair, you can get the value by key, you can also get the key by value

enum PostStatus {
    Draft,
    Unpublished,
    Published
}

If you confirm that the indexer will not be used to access the enumeration in the code, it is recommended to use the constant enumeration const

const enum PostStatus {
    Draft,
    Unpublished,
    Published
}

Interface

Can be understood as a specification/contract
Summary in one sentence:the interface is used to constrain the structure of the object

Read-only members:no modification is allowed after initialization

Class

Abstract members used to describe a class of concrete objects

Class access modifiers that can control the accessibility level of class members

  • public:common, default
  • private:private, only accessible within the current class
  • protected:protected, only accessible within and within the current class
  • readonly:read-only attribute

Abstract class
The abstract keyword, itself cannot execute new to create an instance, only subclasses can inherit

Generic

Taking a function as an example, generics are to specify a specific type when declaring a function, and then pass the specific type when calling
That is, to make the type that we cannot define clear into a parameter, let us pass this type parameter when it is used