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:
- with
var
Declared variables are promoted to the top of their scope and initialized with undefined. - with
let
Declared 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
var
Declaration is global scope or function scope, whilelet
andconst
Is the block scope.var
Variables can be updated and redeclared within their scope;let
Variables can be updated but cannot be redeclared;const
Variables can neither be updated nor redeclared.- They are all elevated to the top of their scope. However, while using variables
undefined
Initialize thevar
Variable, but not initializedlet
andconst
The variable. - Although it can be declared without initialization
var
andlet
, 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 get
call
、bind
、apply
changethis
Point to the - It’s
this
Always point to the global execution environment in which it is defined - Arrow functions are not bound
this
Will capture the context in which it is locatedthis
Value as its own this value. - Unusable
arguments
Object 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. 😢