preface

The author encountered many problems and solved many problems when learning the front end. 22 years is coming, also have to start preparing for internship, spring recruitment autumn recruitment.

But I don’t know what knowledge points will be tested in the interview, and I don’t know how to prepare for the interview.

So I’m going to throw out some of the common questions and break down the important ones in detail.

Problem resolution

Const, let, var

One of the features that comes with ES6 is the addition of lets and const, which can be used for variable declarations. The question is, how are they different from VAR?

var

Before ES6, you had to use var declarations. However, some of the problems with front-end development are related to variables declared using VAR. That’s why there has to be a new way to declare variables. First, let’s learn more about VAR before we get into these issues.

Var scope:

Scope is essentially the range of variables/functions that can be accessed. Var can be declared in global scope or function/local scope.

When a var variable is declared outside the outermost function, the scope is global. This means that any variable declared with VAR outside the outermost function can be used in Windows.

When a VAR is declared in a function, the scope is local. This means that it can only be accessed within a function

var greeter = 'hey hi';

function newFunction() {
    var hello = 'hello';
}
Copy the code

Here, greeter is global-scoped because it exists outside of a function, whereas Hello is function-scoped. Therefore, we cannot access the variable Hello outside the function. So if we do this:

console.log(hello); // error: hello is not defined
Copy the code

The var variable can be redeclared and modified

This means that we can perform the following operations in the same scope without error

var greeter = 'hey hi';
var greeter = 'say Hello instead';
console.log(greeter); // say Hello instead
greeter = 'say ayo instead';
console.log(greeter); // say ayo instead
Copy the code

Var variable promotion:

Variable promotion is a JavaScript mechanism whereby variable and function declarations are moved to the top of their scope before code is executed. This means that if we do this:

console.log(greeter);
var greeter = 'say hello';
Copy the code

The above code would be interpreted as:

var greeter;
console.log(greeter); // greeter is undefined
greeter = 'say hello';
Copy the code

Therefore, variables declared by var are promoted to the top of their scope and initialized with undefined.

let

Let has now become the preferred variable declaration option. This is not surprising, as it is an improvement over the VAR declaration. It also solves the VAR problem we just introduced. Let’s consider why this is so.

Let is a block-level scope

A block is a block of code defined by {}, with a block in braces. Anything inside curly braces is contained in a block-level scope.

Therefore, variables declared in a block with a let can only be used in that block.

let greeting = 'say Hi';
let times = 4;

if (times > 3) {
    let hello = 'say Hello instead';
    console.log(hello); // "say Hello instead"
}
console.log(hello); // hello is not defined
Copy the code

We see that using Hello outside its block of code (the curly braces that define it) returns an error. This is because the let variable is block-scoped.

Lets can be modified but cannot be redeclared

Just like var, variables declared with let can be modified within their scope. Unlike var, however, let variables cannot be redeclared in their scope. Consider the following example:

let greeting = 'say Hi';
let greeting = 'say Hello instead'; // error: Identifier 'greeting' has already been declared
Copy the code

However, if the same variable is defined in different scopes, there will be no error:

let greeting = 'say Hi';
if (true) {
    let greeting = 'say Hello instead';
    console.log(greeting); // "say Hello instead"
}
console.log(greeting); // "say Hi"
Copy the code

Why are there no mistakes? This is because the two instances are scoped differently, so they are treated as different variables.

This fact shows that let is a better choice than VAR. When using let, you don’t have to worry about the name of the 🤔 variable because the variable exists only in its block-level scope.

The variable of let increases

Just like var, the let declaration is promoted to the top of the scope. But the difference is this:

  • withvarDeclared variables are promoted to the top of their scope and initialized with undefined.
  • withletDeclared variables are promoted to the top of their scope and their values are not initialized.

Therefore, if you try to use the let variable before the declaration, you will receive a Reference Error.

const

Variables declared as const hold constant values. The const declaration has some similarities to the let declaration

Variables declared by const are in block-level scope

Like let declarations, const declarations can only be accessed in the block-level scope in which they are declared

Const cannot be modified and cannot be redeclared

This means that the value of a variable declared with const remains the same. Cannot be modified or redeclared. Therefore, if we declare a variable using const, we will not be able to do this:

const greeting = 'say Hi';
greeting = 'say Hello instead'; // error: Assignment to constant variable.
const greeting = 'say Hello instead'; // error: Identifier 'greeting' has already been declared
Copy the code

Therefore, each const declaration must be initialized at declaration time.

This behavior is different when objects are declared with const. A const object cannot be updated, but its properties can be updated. So, if we declare a const object as

const greeting = {
    message: 'say Hi',
    times: 4,
};
Copy the code

You can’t do it like this:

const greeting = {
    words: 'Hello',
    number: 'five',
}; // error:  Assignment to constant variable.
Copy the code

But here’s what we can do:

greeting.message = 'say Hello instead';
Copy the code

This updates the value of greeting.message without returning an error.

The const variable is promoted

Like let, const declarations are promoted to the top, but not initialized.

conclusion

  • varDeclaration is global scope or function scope, whileletandconstIs the block scope.
  • varVariables can be updated and redeclared within their scope;letVariables can be updated but cannot be redeclared;constVariables can neither be updated nor redeclared.
  • They are all elevated to the top of their scope. However, while using variablesundefinedInitialize thevarVariable, but not initializedletandconstThe variable.
  • Although it can be declared without initializationvarandlet, but must be initialized during declarationconst.

Talk about basic data types

What are the basic data types

The seven basic data types are undefined, NULL, Boolean, Number, String, BigInt, and Symbol

Reference data type: Object

Basic data type determination

  • typeof
  • instanceof
  • Object.prototype.toString()

What does Typeof NULL return, and why?

Typeof NULL returns Object. This is because the machine code of Object is 000 and the machine code of NULL is all 0

If you want to determine the specific typeof an object, you can use instanceof. If you want to determine the specific typeof an object, use instanceof. But instanceof can also be inaccurate. For example, an array can be judged as an Object by Instanceof. So we want to more accurately judge the type of Object instances, can take the Object. The prototype. ToString. Call method.

Closures and their usage

Closures are what

A free variable is neither a function parameter, nor a variable inside a function. It is actually a variable in the scope of another function.

From this, we can see that closures have two parts:

Closures = functions + free variables that functions can access

Here’s an example:

var a = 1;
function foo() {
    console.log(a);
}
foo();
Copy the code

Function foo can access variable a, but a is not a local variable of function foo, nor is it an argument to function foo, so a is a free variable.

So foo + foo’s free variable a forms a closure…

The use of closures

Let’s look at one of the most common closure problems:

var data = [];

for (var i = 0; i < 3; i++) {
  data[i] = function () {
    console.log(i);
  };
}

data[0]();
data[1]();
data[2]();
Copy the code

The answer is both 3’s, and let’s analyze why:

Before data[0] is executed, the VO of the global context is:

globalContext = { VO: { data: [...] , i: 3 } }Copy the code

In simple terms, when data[0] is executed, the for loop is complete, I is the global variable, and the value is 3. For example:

for (var i = 0; i < 3; i++) {}
console.log(i) // 3
Copy the code

When data[0] is executed, the scope chain of data[0] is:

The AO of data[0]Context does not have an I value, so it looks up globalContext.VO, where I is 3, so it prints 3.

Data [1] is the same as data[2].

So let’s switch to closures:

var data = []; For (var I = 0; var I = 0; i < 3; i++) { data[i] = (function (i) { return function(){ console.log(i); } })(i); } data[0](); data[1](); data[2]();Copy the code

The AO of data[0]Context does not have an I value, so the AO of data[0]Context does not have an I value, so the AO of data[0]Context looks up the anonymous function context. AO along the scope chain. Even globalContext.vo has a value of I (value 3), so it prints 0.

Data [1] is the same as data[2].

See closures for more details

What are the methods of traversal

Common traversal methods

For, map, forEach, filter, for… In, for… of

for

Use temporary variables to cache the length and avoid fetching the array length repeatedly. The optimization effect is more obvious when the array is large.

for(var j = 0,j < arr.length; J++) {// execute code}Copy the code

forEach

Iterate over each item in the number group, no return value, no effect on the original array, IE is not supported

Arr. ForEach ((value,index,array)=>{// execute code}) // If there are several items in the array, the anonymous callback function passed in should be executed several times;Copy the code

map

The map callback supports a return value. Return () return (); return (); return (); return (); return (); return ();

Arr. Map (function(value,index,array){//do something return XXX}) var ary = [12,23,24,42,1]; var res = ary.map(function (item,index,ary ) { return item*10; }) console.log(res); / / -- > (120230240420, 10); A copy of the original array has been made and console.log(ary) has been modified. / / -- >,23,24,42,1 [12]; The original array is unchangedCopy the code

for… of

Break, continue, and return statements can be responded to correctly

for (var value of myArray) {
console.log(value);
}
Copy the code

for… in

Access the subscript of the array instead of the actual array element value:

for (let i in arr) {
    console.log(arr[i]);
}
Copy the code

filter

Does not change the original array, returns the new array

Var arr = [73,84,56, 22,100] var newArr = arr.filter(item => item>80)Copy the code

for… In and for… The difference of

for… In is used to iterate over the key value of the object and the value on the prototype chain

for… “Of” is used to iterate over the value of an object

What are the new features of ES6

  • let,const
  • Arrow function
  • promise
  • async 和 await
  • set 、map
  • class
  • Symbol
  • deconstruction

The difference between an arrow function and a normal function

The main difference is that arrow functions don’t have this and argument

Without this

  • Cannot be used as a constructor
  • There is no prototype
  • Unable to getcall 、bind 、applychangethisPoint to the
  • It’sthisAlways point to the global execution environment in which it is defined
  • Arrow functions are not boundthisWill capture the context in which it is locatedthisValue as its own this value.
  • UnusableargumentsObject that does not exist in the function body.

But we can use the expansion operator to receive arguments, such as:

const testFunc = (... Args)=>{console.log(args) // Array output arguments}Copy the code

Promise

When a new Promise is passed, an executor() executor executes immediately;

Executor accepts two arguments, resolve and reject;

Be sure to master common Promise methods like then, All, Race, resolve, reject

The key to Promise is this

  • Three state
  • Chain calls

Let’s start with a scenario where we can consider the following request processing to get a user ID:

Get ('some_url', function (result) {//do something console.log(result.id); // Promise http.get('some_url', function (result) {//do something console.log(result.id); }); // use Promise new Promise(function (resolve) {http.get('some_url', function (result) { resolve(result.id) }) }).then(function (id) { //do something console.log(id); })Copy the code

At first glance, it might seem simpler not to use Promise. This is not the case. If you have several dependent front-end requests that are asynchronous, it would look uncomfortable to have the callback function nested layer by layer without promises. As follows:

Get ('some_url', function (id) {//do something http.get('getNameById', id, function (name) { //do something http.get('getCourseByName', name, function (course) { //dong something http.get('getCourseDetailByCourse', function (courseDetail) { //do something }) }) }) }); GetUserId (url) {return new Promise(function (resolve) {http.get(url, function (id) { resolve(id) }) }) } getUserId('some_url').then(function (id) { //do something return getNameById(id); GetNameById is the same Promise wrapper as getUserId. }). Then (function (name) {//do something return getCourseByName(name); }).then(function (course) { //do something return getCourseDetailByCourse(course); }).then(function (courseDetail) { //do something });Copy the code

Realize the principle of

At the end of the day, Promise still uses callback functions, but with the callback wrapped inside, using a chain of calls through the then method to make the nested layers of callbacks look like one, making it more intuitive and concise to write and understand.

At this time the interviewer may come to a soul of the ask, you can write Promise 👀… ?

Work in progress… Handwritten promises can’t be chained yet

Async and await

Async-await and Promise relationship

I often see that with async-await, is there any need to learn promise? Several features of async await are better than promise. I think async-await is nothing more than syntactic sugar of Promise and generator. Syntactic candy is just a way to make code smoother, and of course to make code more readable. Simply put: Async-await is built on top of promise and does not replace it.

Async function

Async functions are functions declared using the async keyword. Async functions are instances of AsyncFunction constructors and allow the await keyword. The async and await keywords allow us to write asynchronous behavior based on promises in a more concise way, without having to deliberately chain call promises.

async function basicDemo() { let result = await Math.random(); console.log(result); } basicDemo(); Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}Copy the code

The above code is the basic use of async-await. There are two unfamiliar keywords async, await, and the result of the function execution seems to return a promise object.

A comparison shows that the async function simply replaces the asterisk (*) of the Generator function with async, replaces yield with await, and returns a Promise😎, and that’s all.

async function demo01() { return 123; } demo01().then(val => { console.log(val); / / 123}); If async defines a function that returns a value, return 123; Resolve (123), and return without a declarative is the same as executing promise.resolve ();Copy the code

await

Await can be understood as short for async wait. Await must appear inside async functions and cannot be used alone.

// async function forDemo() {let arr = [1, 2, 3, 4, 5]; for (let i = 0; i < arr.length; i ++) { await arr[i]; } } forDemo(); Async function forBugDemo() {let arr = [1, 2, 3, 4, 5]; arr.forEach(item => { await item; }); } forBugDemo(); // Uncaught SyntaxError: Unexpected identifierCopy the code

Await can be followed by any JS expression. While “await” can wait for many types of things, its main purpose is to wait for the state of a Promise object to be resolved. If await is a promise object, the asynchronous function will stop executing and wait for the promise, or execute immediately if await is a normal expression.

function sleep(second) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(' enough sleep~'); }, second); }) } function normalFunc() { console.log('normalFunc'); } async function awaitDemo() { await normalFunc(); console.log('something, ~~'); let result = await sleep(2000); console.log(result); } awaitDemo(); // normalFunc // VM4036:13 something, ~~ // VM4036:15 enough sleep~Copy the code

Async&await instances, which also update changes

6. Prototype and prototype chain

Prototype chain is a chain structure composed of prototypes connected by PROto. The author has not fully learned to understand, and will add more in the future. 😢