Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How much do you know about modern JavaScript?

2025-01-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

Today, I would like to talk to you about modern JavaScript, many people may not know much about it. In order to make you understand better, the editor has summarized the following contents for you. I hope you can get something from this article.

Conceptual variable declaration: var, const, let

In JavaScript, there are three keywords you can use to declare a variable, and there are some differences between them. Those are var, let and const.

Simple explanation

Variables declared with the const keyword cannot be reassigned, while let and var can.

I suggest that you always use const to declare your variables by default, and use let if you need to change it, or if you need to reassign it later.

Can scope reallocate changeable temporary dead zone constBlockNoYesYesletBlockYesYesYesvarFunctionYesYesNo simple example const person = "Nick"; person = "John" / / will cause an error, person cannot reassign let person = "Nick"; person = "John"; console.log (person) / / "John", use let to allow reassignment details

The scope of a variable roughly means "where can I access this variable?"

Var

The variable declared by var is in function scope, which means that when a variable is created in a function, everything in the function can access it.

In addition, function scope variables created in a function cannot be accessed outside this function.

I suggest you think of it as an X-scoped variable, which means that this variable is an attribute of X.

Function myFunction () {var myVar = "Nick"; console.log (myVar); / / "Nick"-myVar can be accessed to} console.log (myVar) in this function; / / an error ReferenceError is thrown, but myVar cannot be accessed outside the function

Continuing to focus on the scope of variables, here is a more subtle example:

Function myFunction () {var myVar = "Nick"; if (true) {var myVar = "John"; console.log (myVar); / / "John" / / actually, myVar is a function scope, we just erase the previous myVar value "Nick" and redeclare it as "John"} console.log (myVar); / / "John"-see how the instructions in the if statement block affect this value} console.log (myVar) / / an error ReferenceError is thrown, but myVar cannot be accessed outside the function

In addition, during execution, the variables declared by var are moved to the top of the scope. This is what we call variable declaration promotion (var hoisting).

The code for this part:

Console.log (myVar) / / undefined-- No error var myVar = 2

When executed, it is resolved as:

Var myVar;console.log (myVar) / / undefined-- No error myVar = 2

Fool's Wharf Note: variable promotion and function declaration promotion can be seen in Hoisting (variable promotion and function declaration promotion) in JavaScript.

Let

Var and let are roughly the same, but variables declared with let have the following features:

Block-level scope (block scoped)

Cannot access and use until it is assigned

Cannot be redeclared within the same scope

Let's take a look at our previous example, which uses block-level scope (block scoping):

Function myFunction () {let myVar = "Nick"; if (true) {let myVar = "John"; console.log (myVar); / / "John" / / actually myVar is in block-level scope, (in if block) we just create a new variable myVar. / / this variable is not accessible outside the if statement block, / / completely independent of the first myVar variable created! } console.log (myVar); / / "Nick", you can see that the instruction in the if statement block does not affect the value} console.log (myVar); / / the error ReferenceError,myVar cannot be accessed outside the function.

Now, let's see what it means that the let (and const) variables are not accessible until they are assigned:

Console.log (myVar) / / throws a reference error ReferenceError! let myVar = 2

Unlike the var variable, if you read and write before the let or const variable is assigned, an error will occur. This phenomenon is often referred to as a temporary dead zone (Temporal dead zone) or TDZ.

Note: technically, let and const variables are also promoted when they are declared, but that doesn't mean their assignments will also be promoted. But because it is designed to be unusable before assignment, we intuitively feel that it has not been promoted, but there is actually an improvement. If you want to know more details, please read this article.

In addition, you cannot redeclare a let variable:

Let myVar = 2 myVar = 3; / / throw syntax error SyntaxErrorconst

The variable declared by const is very similar to let, but it cannot be reassigned.

Summarize the const variables:

Block level scope

Cannot be accessed before assignment

Within the same scope, you cannot redeclare

Cannot be reassigned

Const myVar = "Nick"; myVar = "John" / / throws an error and does not allow reassignment const myVar = "Nick"; const myVar = "John" / / throws an error and does not allow redeclaration

But here is one small detail: the const variable is not immutable; specifically, if the variable declared by const is a value of type object and array, it is mutable.

For objects:

Const person = {name: 'Nick'}; person.name =' John' / / this is valid! The person variable is not completely reassigned, but the value is changed console.log (person.name) / / "John" person = "Sandra" / / throws an error because variables declared with const cannot be reassigned

For arrays:

Const person = []; person.push ('John'); / / this is valid! The person variable is not completely reallocated, but the value is changed console.log (person [0]) / / "John" person = ["Nick"] / / throws an error because variables declared with const cannot be reassigned and extended to read

How let and const are scoped in JavaScript-WesBos

Temporal Dead Zone (TDZ) Demystified

Arrowhead function

ES6 JavaScript updates introduce the arrow function, which is another way to declare and use functions. Here are the benefits they bring:

More concise

The value of this inherits from the peripheral scope

Implicit return

A simple example

Simplicity and implicit return

Function double (x) {return x * 2;} / / the traditional method console.log (double (2)) / / 4const double = x = > x * 2; / / the same function is written with an implicitly returned arrow function console.log (double (2)) / / 4

Reference to this

In the arrow function, this means enclosing the this value of the execution context. Basically, with the arrow function, you don't need to perform tricks like "that = this" before calling the function in the function.

Function myFunc () {this.myVar = 0; setTimeout () = > {this.myVar++; console.log (this.myVar) / / 1}, 0);} specify simplicity

The arrow function is more concise than the traditional function in many ways. Let's look at all possible scenarios:

Implicit VS explicitly returns

Explicit return (explicit return) refers to the explicit use of the keyword return in the function body.

Function double (x) {return x * 2; / / this function shows that it returns x * 2 and uses the * return* keyword}

In the traditional way of writing a function, the return is always explicit. But if you are using the arrow function, you can perform an implicit return (implicit return), which means that you do not need to use the keyword return to return a value.

To do an implicit postback, the code must be written in one line.

Const double = (x) = > {return x * 2; / / here is the explicit return}

Since there is only one return value here, we can do an implicit return.

Const double = (x) = > x * 2

To do this, we just need to remove the parentheses and the return keyword. That's why it's called an implicit return, and the return keyword is gone, but this function does return x * 2.

Note: if your function does not return a value (which has side effects), it will not return explicitly or implicitly.

In addition, if you want to implicitly return an object (object), you must wrap it in parentheses, otherwise it will conflict with block braces:

Const getPerson = () = > ({name: "Nick", age: 24}) console.log (getPerson ()) / / {name: "Nick", age: 24}-the arrow function implicitly returns an object

There is only one parameter

If your function accepts only one argument, you can omit the parentheses that wrap it. If we take the above double code as an example:

Const double = (x) = > x * 2; / / this arrow function accepts only one argument

Parentheses for package parameters can be omitted:

Const double = x = > x * 2; / / this arrow function accepts only one argument.

No parameters

When you do not provide any arguments to the arrow function, you must add parentheses, otherwise a syntax error will be thrown.

() = > {/ / provide parentheses, everything works properly const x = 2; return x;} = > {/ / without parentheses, this does not work properly! Const x = 2; return x;} this reference

To understand the subtlety of the arrow function, you must know how this works in JavaScript.

In an arrow function, this is equivalent to the this value of the closed execution context. This means that an arrow function does not create a new this, but grabs it from its outer scope.

If there is no arrow function, and you want to access variables through this in a function inside a function, you can only use techniques such as that = this or self = this.

For example, you use the setTimeout function in myFunc:

Function myFunc () {this.myVar = 0; var that = this; / / that = this technique setTimeout (function () {/ / in the scope of this function, a new * this* is created that.myVar++; console.log (that.myVar) / / 1 console.log (this.myVar) / / undefined-see appellate function declaration}, 0);}

But if you use the arrow function, this grabs from its outer scope:

Function myFunc () {this.myVar = 0; setTimeout (() = > {/ / this value comes from its peripheral scope, in this case, the myFunc function this.myVar++; console.log (this.myVar) / / 1}, 0);} useful resources

Arrow functions introduction-WesBos

JavaScript arrow function-MDN

Arrow function and lexical this

Default value of function parameter

Starting after the ES2015 JavaScript update, you can set default values for the parameters of the function using the following syntax:

Function myFunc (x = 10) {return x } console.log (myFunc ()) / / 10-- No value is provided, so 10 in myFunc is assigned to xconsole.log (myFunc (5)) / / 5-there is a parameter value, so in myFunc x equals 5 console.log (myFunc (undefined)) / / 10-provides a undefined value, so the default value is assigned to xconsole.log (myFunc (null)) / / null-provides a value (null) For more information, please see below

The default parameters apply to two and only two cases:

No parameters provided

Provide undefined undefined parameters

In other words, if you pass in null, the default parameters are not applied.

Note: default value assignments can also be used with deconstruction parameters (see the next concept to see an example).

Extended reading

Default parameter value-ES6 Features

Default parameters-MDN

Deconstruct objects and arrays

Destructuring is an easy way to create new variables by extracting values from data stored in an object or array.

To take a simple example, destructuring can be used to deconstruct parameters in a function, or a usage such as this.props in a React project.

Illustrate with sample code

Object

Let's consider all the properties of the following objects:

Const person = {firstName: "Nick", lastName: "Anderson", age: 35, sex: "M"}

Do not use deconstruction:

Const first = person.firstName;const age = person.age;const city = person.city | | "Paris"

With deconstruction, only 1 line of code is required:

Const {firstName: first, age, city = "Paris"} = person; / / it's that simple! Console.log (age) / / 35-A new variable age is created and its value is equivalent to person.ageconsole.log (first) / / "Nick"-a new variable first is created and its value is equal to person.firstName A new variable first is created and is equal to person.firstNameconsole.log (firstName) / / Undefined-although person.firstName exists But the new variable is called firstconsole.log (city) / / "Paris"-- a new variable city is created, and because person.city is undefined (undefined), city will be equivalent to the default value, which is "Paris".

Note: in const {age} = person;, the parentheses after the const keyword are not used to declare objects or blocks of code, but rather to structuring syntax.

Function parameter

Structuring is often used to deconstruct object parameters in a function.

Do not use deconstruction:

Function joinFirstLastName (person) {const firstName = person.firstName; const lastName = person.lastName; return firstName +'-'+ lastName;} joinFirstLastName (person); / / "Nick-Anderson"

When deconstructing the object parameter person, we can get a more concise function:

Function joinFirstLastName ({firstName, lastName}) {/ / by deconstructing the person parameter, we create the variables return firstName +'-'+ lastName;} joinFirstLastName (person); / / "Nick-Anderson", respectively.

The use of deconstruction in the arrow function makes the development process more enjoyable:

Const joinFirstLastName = ({firstName, lastName}) = > firstName +'-'+ lastName;joinFirstLastName (person); / / "Nick-Anderson"

Array

Let's consider the following array:

Const myArray = ["a", "b", "c"]

Do not use deconstruction:

Const x = myArray [0]; const y = myArray [1]

Use deconstruction:

Const [x, y] = myArray; / / it's that simple! Console.log (x) / / "a" console.log (y) / / "b" useful resources

ES6 Features-Destructuring Assignment

Destructuring Objects-WesBos

ExploringJS-Destructuring

Array method-map / filter / reduce

Both map,filter and reduce are methods provided by arrays, and they are derived from functional programming.

To sum up:

Array.prototype.map () takes an array, performs some operations on its elements, and returns an array with converted elements.

Array.prototype.filter () takes an array, decides whether to retain it according to the element itself, and returns an array that contains only reserved elements.

Array.prototype.reduce () takes an array, merges these elements into a single value (and returns).

I recommend using them as much as possible to follow the principles of functional programming (functional programming) because they are composable, concise, and elegant.

With these three methods, you can avoid using for and forEach in most cases. When you try to make a for loop, try combining map,filter and reduce. It may be difficult for you to do this at first because it requires you to learn a new way of thinking, but once you get it, things will become easier.

Fool's Wharf Note: JavaScript functional programming suggestions take a look at the following articles

Currying (Corialization) and Partial Application (partial function Application) in JavaScript

Teach you JavaScript functional programming step by step (part I)

Teach you JavaScript functional programming step by step (part II)

Teach you JavaScript functional programming step by step (part 3)

A Compendium of JavaScript functional programming terms

Simple examples const numbers = [0,1,2,3,4,5,6]; const doubledNumbers = numbers.map (n = > n * 2); / / [0,2,4,6,8,10,12] const evenNumbers = numbers.filter (n = > n% 2 = 0); / / [0,2,4,6] const sum = numbers.reduce ((prev, next) = > prev + next, 0); / / 21

Calculate the total sum of students with a score of more than 10 by combining map,filter and reduce:

Const students = [{name: "Nick", grade: 10}, {name: "John", grade: 15}, {name: "Julia", grade: 19}, {name: "Nathalie", grade: 9},] Const aboveTenSum = students .map (student = > student.grade) / / We map the student array to the array of their scores. Filter (grade = > grade > = 10) / / We filter the score array to keep the elements above 10 points. Reduce (prev, next) = > prev + next, 0) / / We will add up all scores above 10 console.log (aboveTenSum) / / 44-10 (Nick) + 15 (John) + 19 (Julia). Nathalie below 10 is ignored.

Let's consider the following array:

Const numbers = [0,1,2,3,4,5,6]; Array.prototype.map () const doubledNumbers = numbers.map (function (n) {return n * 2;}); console.log (doubledNumbers); / / [0,2,4,6,8,10,12]

What's going on here? We use the .map method in the numbers array, and map will iterate over each element of the array and pass it to our function. The goal of this function is to generate and return a new value so that map can replace the original array.

Let's explain this function to make it a little clearer:

Const doubleN = function (n) {return n * 2;}; const doubledNumbers = numbers.map (doubleN); console.log (doubledNumbers); / / [0,2,4,6,8,10,12]

Numbers.map (doubleN) will produce [doubleN (0), doubleN (1), doubleN (2), doubleN (3), doubleN (4), doubleN (5), doubleN (6)] and they are equivalent to [0,2,4,6,8,10,12].

Note: if you do not need to return a new array and only want to execute a loop with side effects, using the for / forEach loop will better suit your needs.

Array.prototype.filter () const evenNumbers = numbers.filter (function (n) {return n% 2 = 0; / / return true if "n" meets the condition, and false if "n" does not meet the condition. }); console.log (evenNumbers); / / [0,2,4,6]

We use the .filter method in the numbers array, and the filter iterates through each element in the array and passes it to our function. The goal of the function is to return a Boolean value that determines whether the current value is retained. The array returned after filtering will contain only the reserved values.

Array.prototype.reduce ()

The goal of the reduce method is to reduce all the elements in the iterated array to a single value. How you aggregate these elements is up to you.

Const sum = numbers.reduce (function (acc, n) {return acc + n;}, 0 / / initial value of the accumulator iteration variable); console.log (sum) / / 21

Just like the .map and .filter methods, the .reduce method is applied to the array and takes a function as the first parameter.

Here are some differences:

.reduce accepts two parameters

The first argument is a function that will be called in each iteration step.

The second parameter is the value of the accumulator variable (in this case, acc) in the first iteration step (read the next one).

Function parameter

The function passed as the first argument to .reduce requires two arguments. The first (in this case, acc) is the accumulator variable, while the second parameter (n) is the current element.

The value of the accumulator variable is equal to the return value of the function in the previous iteration step. In the first step of the iteration, acc is equal to the value passed by the second parameter when you do. Reduce (Fool's Wharf Note: that is, the initial value of the accumulator).

Perform the first iteration

Acc = 0 because we take 0 as the second parameter of reduce

N = 0 the first element of the number array

The function returns acc + n-> 0 + 0-> 0

Perform the second iteration

Acc = 0 because it is the value returned by the last iteration

The second element of the n = 1 number array

The function returns acc + n-> 0 + 1-> 1

Perform the third iteration

Acc = 1 because it is the value returned by the last iteration

The third element of the n = 2 number array

The function returns acc + n-> 1 + 2-> 3

Perform the fourth iteration

Acc = 3 because it is the value returned by the last iteration

The fourth element of the n = 3 number array

The function returns acc + n-> 3 + 3-> 6

[.] Carry out the last iteration

Acc = 15 because it is the value returned by the last iteration

The last element of the n = 6 number array

The function returns acc + n-> 15 + 6-> 21

Because it is the last iteration step, .reduce will return 21.

Extended reading

Understanding map / filter / reduce in JS

Unfold operator "…"

ES2015 has introduced the unfold operator..., which can expand multiple iterating elements, such as arrays, to the appropriate location.

Simple code example const arr1 = ["a", "b", "c"]; const arr2 = [... arr1, "d", "e", "f"]; / / ["a", "b", "c", "d", "e", "f"] function myFunc (x, y,... params) {console.log (x); console.log (y) Console.log (params)} myFunc ("a", "b", "c", "d", "e", "f") / / "a" / / "b" / / ["c", "d", "e", "f"] const {x, y,... z} = {x: 1, y: 2, a: 3, b: 4}; console.log (x); / / 1console.log (y); / / 2console.log (z) / / {a: 3, b: 4} const n = {x, y,... z}; console.log (n); / / {x: 1, y: 2, a: 3, b: 4} instructions apply to iterations (such as arrays)

If we have the following two arrays:

Const arr1 = ["a", "b", "c"]; const arr2 = [arr1, "d", "e", "f"]; / / [["a", "b", "c"], "d", "e", "f"]

The first element of arr2 is an array because arr1 is injected into arr2. But the arr2 we really want is an array of pure letters. To do this, we can spread arr1 to arr2.

By expanding the operator:

Const arr1 = ["a", "b", "c"]; const arr2 = [... arr1, "d", "e", "f"]; / / ["a", "b", "c", "d", "e", "f"] function residual parameters

In the function arguments, we can use the rest operator to inject the parameters into an array that we can loop through. There is already an argument object bound to each function, which is equivalent to passing all the parameters in the array to the function.

Function myFunc () {for (var I = 0; I)

< arguments.length; i++) { console.log(arguments[i]); }}myFunc("Nick", "Anderson", 10, 12, 6);// "Nick"// "Anderson"// 10// 12// 6 但是如果说,我们希望创造的是一个包含各科成绩和平均成绩的新学生。将前两个参数提取为两个单独的变量,并把剩下的元素生成一个可迭代的数组是不是更加方便呢? 这正是 rest 操作符允许我们做的事情! function createStudent(firstName, lastName, ...grades) { // firstName = "Nick" // lastName = "Anderson" // [10, 12, 6] -- "..." 将传递所有剩余参数,并创建一个包含它们的 "grades" 数组变量 const avgGrade = grades.reduce((acc, curr) =>

Acc + curr, 0) / grades.length; / / calculate the GPA based on grade return {firstName: firstName, lastName: lastName, grades: grades, avgGrade: avgGrade}} const student = createStudent ("Nick", "Anderson", 10,12,6); console.log (student); / {/ / firstName: "Nick", / / lastName: "Anderson", / / grades: [10,12,6], / / avgGrade: 9.33333333334hand /}

Note: in this example, the createStudent function is not really good because we are not checking whether grades.length exists or if it is equal to 0. But this example is now written in this way, which can help us better understand the operation of the remaining parameters, so I did not deal with the above situation.

Object property expansion

At this point, I recommend that you read previous instructions about iterations and function parameters about the rest operator.

Const myObj = {x: 1, y: 2, a: 3, b: 4}; const {x, y,... z} = myObj; / / where the object is deconstructed console.log (x); / / 1console.log (y); / / 2console.log (z) / / {a: 3, b: 4} / z is the remaining part of the object after deconstruction: after removing the x and y attributes, the remaining part of the myObj object is deconstructed const n = {x, y,... z}; console.log (n); / / the properties of the z object are expanded to expand resources in n.

TC39-Object rest/spread

Spread operator introduction-WesBos

JavaScript & the spread operator

6 Great uses of the spread operator

Shorthand for object properties

When assigning a variable to an object property, if the variable name is the same as the attribute name, you can do the following:

Const x = 10 Const myObj = {x}; console.log (myObj.x) / / 10 description

Usually (before ES2015) when you declare a new object literal and want to use a variable as the object property value, you will write code like this:

Const x = 10 Const y = 20 Const myObj = {x: X, / / assign x to myObj.x y: y / / assign y variable to myObj.y}; console.log (myObj.x) / / 10console.log (myObj.y) / / 20

As you can see, this is actually quite repetitive, because the property names of the myObj are the same as the names of the variables to be assigned to these attributes.

With ES2015, when the variable name is the same as the attribute name, you can abbreviate the following:

Const x = 10 Const y = 20 th Const myObj = {x, y}; console.log (myObj.x) / / 10console.log (myObj.y) / / 20 extended resources

Property shorthand-ES6 Features

Promises

Promises is an object that can be returned synchronously from an asynchronous function (reference).

Promises can be used to avoid callback callback hell, and they are encountered more and more frequently in modern JavaScript projects.

Simple code example const fetchingPosts = new Promise ((res, rej) = > {$.get ("/ posts") .done (posts = > res (posts)) .fail (err = > rej (err));}); fetchingPosts .then (posts = > console.log (posts)) .catch (err = > console.log (err))

When you execute an Ajax request, the response is not synchronous because the resource request takes time. If the resource you want is not available for some reason (404), it may never even be requested.

To deal with such situations, ES2015 provides us with promises. Promises can have three different states:

Waiting (Pending)

Reach (Fulfilled)

Reject (Rejected)

Suppose we want to use promises to make Ajax requests to get X resources.

Create promise

We first need to create a promise. We will use the get method of jQuery to perform an Ajax request on the X resource.

Const xFetcherPromise = new Promise (/ / create promise using the "new" keyword and save it to a variable function (resolve, reject) {/ / Promise constructor requires a function with the parameters resolve and reject as arguments $.get ("X") / / execute the Ajax request. Done (function (X) {/ / once the request is complete. Resolve (X) / /... Take X as a parameter to resolve promise}) .fail (function (error) {/ / if the request fails. Reject (error); / / Reject promise error as a parameter});})

As shown in the previous example, the Promise object requires an execution function with two parameters (resolve and reject). These two parameters process the promise of the pending state as fulfilled and rejected, respectively.

Promise is in a pending state after the instance is created, and its executor function executes immediately. Once the resolve or reject function is called in the executing function, Promise will call the relevant handler.

The usage of Promise processor

In order to get the promise result (or error), we must attach the handler by doing the following:

XFetcherPromise. Then (function (X) {console.log (X);}) .catch (function (err) {console.log (err)})

If promise succeeds, resolve is executed and the function passed by the .then argument is executed.

If it fails, reject is executed and the function passed by the. Catch parameter is executed.

Note: if the promise is already fulfilled or rejected when the corresponding handler is attached, the handler will be called

Therefore, there is no competition condition between the completion of the asynchronous operation and the attachment of its handler. (reference: MDN) (MDN).

Extended reading

JavaScript Promises for dummies-Jecelyn Yeen

JavaScript Promise API-David Walsh

Using promises-MDN

What is a promise-Eric Elliott

JavaScript Promises: an Introduction-Jake Archibald

Promise documentation-MDN

Template string

A template string is an expression interpolation (expression interpolation) of single-line and multi-line strings.

In other words, it is a new string syntax that you can use more easily in JavaScript expressions (such as variables).

Simple code example const name = "Nick"; `Hello ${name}, the following expression is equal to four: ${2q2} `; / / Hello Nick, the following expression is equal to four: 4 extension reading

String interpolation-ES6 Features

ES6 Template Strings-Addy Osmani

Template string with a label (tag)

Template tags are prefix functions that can be used as template strings (template literal). When a function is called by this clock, the first argument is the array of strings that appear between the template interpolation variables, and the subsequent argument is the value of the interpolation variable. You can use the unfold operator. Capture all of these parameters. (reference: MDN).

Note: a famous library called styled-components relies heavily on this feature.

The following is an example of a toy they work with.

Function highlight (strings,... values) {/ / Fool Wharf Note: in order to better understand the parameters of the function, I have added these two lines of code. For special instructions, see the instructions below in the sample code. Console.log (strings); / / (3) ["I like", "on", ".", raw: Array (3)] console.log (values); / / (2) ["jam", "toast"] const interpolation = strings.reduce ((prev, current) = > {return prev + current + (values.length? "" + values.shift () + ":");}, "); return interpolation;} const condiment =" jam "; const meal =" toast " Account`I like ${condiment} on ${meal}. `; / / "I like jam on toast."

-Fool Wharf bets begin-

Fool's Wharf Note, about the first parameter:

The first argument to the label function is an array of string literals (in this case, "I like", "on", and "."). If we call Secrett`I like ${condiment} on ${meal} `(notice that there is no "."), then the first parameter is still an array of three elements: ["I like", "on", ""], paying special attention to the empty string that the last element is "."

The raw property of a string

Strings is indeed an array, but it also has a raw attribute. Its attribute value strings.raw is also an array, and its elements represent the corresponding string in strings that was entered by the user in the template string (Template literals) before it was escaped. Let's look at an example:

Const myTag = (strs,... exprs) = > {console.log (strs); / / (3) ["x", "\ y", "", raw: Array (3)] console.log (strs.raw); / / (3) ["x", "\ y", "console.log (exprs); / / [1,2]}; const obj = {a: 1, b: 2} Const result = myTag`x ${obj.a}\\ y$ {obj.b} `

In the above example, the corresponding string before "\ y" is escaped is "\", so it is obvious that the length of the two strings is different.

String.raw is a static method of ES2015, a built-in object String, which can be used as a Tag to replace only embedded expressions without escaping characters.

Const raw = string. Raw`1\\ 2\\ ${1\ 2} `; console.log (raw); / 1\ 2\\ 3console.log (raw.length); / / 7const x = `1\ 2\ ${1\ 2}`; console.log (x); / 1\ 2\ 3console.log (x.length); / / 5 circumvent the problem

Template literals follows the rules for escaping strings:

(1) start with\ u, followed by 4 hexadecimal digits, for example,\ u00B1 for ±

(2) start with\ u and use hexadecimal numbers enclosed in curly braces, for example,\ u {2F804} indicates you

(3) start with\ x, followed by 2 hexadecimal digits, for example,\ xB1 for ±

(4) start with\, followed by a decimal number to represent the octal literal (Note: not supported under strict mode)

When the interpreter encounters\ u and\ x, it will report a grammatical error if it finds that the following characters do not meet the above conditions. For example,

> latex`\ unicode` > Uncaught SyntaxError: Invalid Unicode escape sequence

No longer expand, specific reference: Template literals.

Fool's Wharf Note, for the rest of the parameters:

Each parameter after the first parameter is a replacement expression that has been evaluated. Look at the following example:

Var a = 5 return values var b = 10 political function tag (strings,... values) {console.log (values [0]); / 15 console.log (values [1]); / / 50 return values [0] + values [1]; / / 65} tag`Hello ${a + b} world ${a * b} `

In the above example, the remaining two parameter values are 15 and 50, respectively.

-end of Fool Wharf bets

A more interesting example:

Function comma (strings,... values) {return strings.reduce ((prev, next) = > {let value = values.shift () | | []; value = value.join (","); return prev + next + value;}, "");} const snacks = ['apples',' bananas', 'cherries']; comma`I like ${snacks} to snack on.`; / / "I like apples, bananas, cherries to snack on." Extended reading

Wes Bos on Tagged Template Literals

Library of common template tags

Import / export of ES6 modules (imports / exports)

The ES6 module is used to access variables or functions in modules that are explicitly exported in the module.

I strongly recommend that you check out the import/export on MDN (see the extended reading resources below), which are concise and complete.

Illustrate named exports with sample code

Named exports are used to export multiple values from a module.

Note: you name the exported variable as a first-class citizen (first-class citizens).

/ / mathConstants.jsexport const pi = 3.14 pi export const exp = 2.7 × export const alpha = 0.35 /-/ / myFile.jsimport {pi, exp} export'. / mathConstants.js' / / named import-similar to the deconstructing syntax console.log (pi) / / 3.14console.log (exp) / / 2.7 as constants from /-/ / mySecondFile.jsimport * import'. / mathConstants.js'; / / inject all exported values into the constants variable console.log (constants.pi) / / 3.14console.log (constants.exp) / / 2.7g

Although named imports look like destructuring, they have different syntax and are not the same. They do not support default values, nor do they support deep deconstruction.

In addition, you can use aliases, but the syntax is different from the syntax used in deconstruction:

Import {foo as bar} from 'myFile.js'; / / foo is imported and injected into a new bar variable default import / export (imports / exports)

For default exports, there can be only one default export per module. The default export can be a function, class, object, or anything else. This value is considered the "primary" export value because it will be the easiest import. Reference: MDN.

/ / coolNumber.jsconst ultimateNumber = 42 × export default ultimateNumber;//-/ / myFile.jsimport number from'. / coolNumber.js';// is exported by default and will be automatically injected into the variable number independent of its name; console.log (number) / / 42

Function export:

/ / sum.jsexport default function sum (x, y) {return x + y;} /-/ / myFile.jsimport sum from'. / sum.js';const result = sum (1,2); console.log (result) / / 3 extended Reading

Detailed explanation of ECMAScript 6 Modules (module) system and grammar

ES6 Modules in bulletpoints

Export-MDN

Import-MDN

Understanding ES6 Modules

Destructuring special case-import statements

Misunderstanding ES6 Modules-Kent C. Dodds

Modules in JavaScript

This in JavaScript

The behavior of the this operator is different from other languages and, in most cases, is determined by how the function is called. (reference: MDN).

The concept of this has a lot of details, which is not so easy to understand, and I strongly recommend that you take a closer look at the following extended reading. Therefore, I will provide my personal understanding and thoughts on this. I learned this tip from this article written by Yehuda Katz.

Function myFunc () {.} / / at the end of each statement, you can find the value of this myFunc.call ("myString", "hello") / / "myString" in myFunc-first The parameter value of .call is injected into * this*// in non-strict-mode myFunc ("hello") / / window-- myFunc () is the syntax sugar of myFunc.call (window, "hello") / / in strict mode (strict-mode) myFunc ("hello") / / undefined-- myFunc () is myFunc.call (undefined Syntax sugar var person = {myFunc: function () {...}} person.myFunc.call (person, "test") / / person object-- first The parameter value of .call is injected into the * this*person.myFunc ("test") / / person object-- person.myFunc () is the syntax sugar of person.myFunc.call (person, "test") var myBoundFunc = person.myFunc.bind ("hello") / / creates a function And inject "hello" into the * this* person.myFunc ("test") / / person object-- the bind method has no effect on the original method myBoundFunc ("test") / / "hello"-- myBoundFunc binds the person.myFunc with "hello" to the * this* extension

Understanding JavaScript Function Invocation and "this"-Yehuda Katz

JavaScript this-MDN

Class (Class)

JavaScript is a prototype-based language (whereas Java is a category-based language). ES6 introduces JavaScript classes, which are syntactic sugars for prototype-based inheritance, rather than a new model based on class inheritance (reference).

If you are familiar with classes in other languages, the word class is indeed easy to misunderstand. If you really have this problem, avoid thinking about the behavior of the JavaScript class in this way and think of it as a completely different new concept.

Since this document does not fundamentally teach you the JavaScript language, I will believe that you know what prototypes are and how they behave. If not, see the extensions listed below in the sample code to make it easier for you to understand these concepts:

Understanding Prototypes in JS-Yehuda Katz

A plain English guide to JS prototypes-Sebastian Porto

Inheritance and the prototype chain-MDN

A simple example

Before ES6, the prototype method:

Var Person = function (name, age) {this.name = name; this.age = age;} Person.prototype.stringSentence = function () {return "Hello, my name is" + this.name + "and Isimm" + this.age;}

Use the ES6 class (class) * syntax:

Class Person {constructor (name, age) {this.name = name; this.age = age;} stringSentence () {return "Hello, my name is" + this.name + "and Ihumm" + this.age;}} const myPerson = new Person ("Manu", 23); console.log (myPerson.age) / / 23console.log (myPerson.stringSentence ()) / / "Hello, my name is Manu and I'm 23 extended Reading

A better understanding of the prototype:

Understanding Prototypes in JS-Yehuda Katz

A plain English guide to JS prototypes-Sebastian Porto

Inheritance and the prototype chain-MDN

A better understanding of classes:

ES6 Classes in Depth-Nicolas Bevacqua

ES6 Features-Classes

JavaScript Classes-MDN

Extends and super keywords

The extends keyword is used in a class declaration or class expression to create a class that is a subclass of another class (see: MDN). The subclass inherits all the properties of the superclass, and you can add new properties or modify inherited properties.

The super keyword is used to call the function of the object's parent, including its constructor.

The super keyword must be used before using the this keyword in the constructor.

Call super () to call the parent class constructor. If you want to pass some parameters from the constructor of a class to its parent constructor, you can use super (arguments) to call it.

If the parent class has a method of X (or even static), it can be called in the subclass using super.X ().

The simple code example class Polygon {constructor (height, width) {this.name = 'Polygon'; this.height = height; this.width = width;} getHelloPhrase () {return `Hi, I am a ${this.name} `;}} class Square extends Polygon {constructor (length) {/ / here, it calls the length of the constructor of the parent class, / / the width and height provided to Polygon. Super (length, length); / / Note: in derived classes, you must call super () before you can use 'this'. / / ignore this, which will result in referencing errors. This.name = 'Square'; this.length = length;} getCustomHelloPhrase () {const polygonPhrase = super.getHelloPhrase (); / / access the parent method return `${polygonPhrase} with a length of ${this.length}` through the super.X () syntax;} get area () {return this.height * this.width;}} const mySquare = new Square (10) Console.log (mySquare.area) / / 100console.log (mySquare.getHelloPhrase ()) / /'Hi, I am a Square'-- Square inherits from Polygon and can access its method console.log (mySquare.getCustomHelloPhrase ()) / /'Hi, I am a Square with a length of 10'

Note: if we try to use this before calling super () in the Square class, we will raise a reference error:

Class Square extends Polygon {constructor (length) {this.height; / / reference error, you must first call super ()! / here, which calls the length of the constructor of the parent class, and / / the width and height provided to the Polygon. Super (length, length); / / Note: in derived classes, you must call super () before you can use 'this'. / / ignore this, which will result in referencing errors. This.name = 'Square';}} extended Reading

Extends-MDN

Super operator-MDN

Inheritance-MDN

Async and wait (Async Await)

In addition to promises, there is a new syntax that you may encounter, which is asynchronous async / await.

The purpose of the async / await function is to simplify the behavior of using promise synchronously and to perform some processing on a set of promises. Just as promises is similar to structured callbacks, async / await is similar to combining generators and promises. Asynchronous functions always return a Promise. (reference: MDN)

Note: you must understand what promises is and how they work, and then try to understand async / await because they depend on promises.

Note 2: [await must be used in the async function] (https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial- c7ec10518dd9#f3f0), which means that you cannot use await at the top of the code because it is not within the asynchronous function.

A simple code example async function getGithubUser (username) {/ / async keyword allows await to be used in a function, meaning that the function returns a promise const response = await fetch (`code / / execution is paused here until the Promise returned by fetch is resolved return response.json () } getGithubUser ('mbeaudru') .then (user = > console.log (user)) / / record the user response-await syntax cannot be used because this code is not in the async function. Catch (err = > console.log (err)); / / if an error is thrown in our asynchronous function, we will capture it here and illustrate it with sample code

Async / Await is based on the concept of promises, but they allow for a more mandatory code style.

The async operator marks a function as asynchronous and will always return a Promise. You can use the await operator in the async function to pause the execution of this line of code until the Promise resolves or rejects is returned in the expression.

Async function myFunc () {/ / We can use the * await* operator because this function is the return "hello world" of async;} myFunc () .then (msg = > console.log (msg)) / / "hello world"-because of the async operator, the return value of myFunc becomes a promise

When the asynchronous function runs into the return statement, the returned value is used to fulfilled Promise. If an error is thrown in the async function, the Promise state changes to rejected. If no value is returned from the async function, Promise is still returned and resolves is null when the execution of the async function completes.

The await operator is used to wait for Promise fulfilled and can only be used in the body of the async function. In this case, code execution is paused until promise fulfilled.

Note: fetch is a function that allows AJAX requests to be executed and returns a Promise.

First, let's look at how to get a github user through promises:

Function getGithubUser (username) {return fetch (`https://api.github.com/users/${username}`).then(response = > response.json ());} getGithubUser ('mbeaudru') .then (user = > console.log (user)) .catch (err = > console.log (err))

Equivalent to here async / await:

Async function getGithubUser (username) {/ / promise + await keyword allows const response = await fetch (`stop / / execute stop here until promise gets fulfilled return response.json ();} getGithubUser ('mbeaudru'). Then (user = > console.log (user)) .catch (err = > console.log (err))

The async / await syntax is especially convenient when you need to chain interdependent promises.

For example, if you need to get a token so that you can get blog posts on the database, and then get the author information:

Note: the await expression needs to be enclosed in parentheses so that the methods and properties of its resolved value can be called on the same line.

Async function fetchPostById (postId) {const token= (await fetch ('token_url')) .json () .token; const post = (await fetch (`/ posts/$ {postId}? token=$ {token}`)) .json (); const author = (await fetch (`/ users/$ {post.authorId}`)) .json (); post.author = author; return post;} fetchPostById (' gzIrzeo64') .then (post = > console.log (post)) .catch (err = > console.log (err)); error handling

Unless we wrap try / catch blocks around await expressions, we will not catch exceptions-whether they are thrown in your asynchronous function or paused during await-their promise to return the reject async function.

Using the throw statement in the async function is the same as the Promise that returns reject. (reference: PonyFoo).

Note: Promises behaves the same!

The following is an example of how promises handles error chains:

Function getUser () {/ / this promise will be rejected! Return new Promise ((res, rej) = > rej ("User not found!"));} function getAvatarByUsername (userId) {return getUser (userId) .then (user = > user.avatar);} function getUserAvatar (username) {return getAvatarByUsername (username) .then (avatar = > ({username, avatar}));} getUserAvatar ('mbeaudru') .then (res = > console.log (res) .catch (err = > console.log (err)); / / "User not found!"

Equivalent to practical async / await:

Async function getUser () {/ / this promise will be rejected! Throw "User not found!";} async function getAvatarByUsername (userId) = > {const user = await getUser (userId); return user.avatar;} async function getUserAvatar (username) {var avatar = await getAvatarByUsername (username); return {username, avatar};} getUserAvatar ('mbeaudru') .then (res = > console.log (res)) .catch (err = > console.log (err); / / "User not found!" Extended reading

Use the Async (asynchronous) function and Await (wait) in ES2017

New feature of ES2017: Async Functions (Asynchronous function)

Async/Await-JavaScript.Info

ES7 Async/Await

6 Reasons Why JavaScript's Async/Await Blows Promises Away

JavaScript awaits

Using Async Await in Express with Node 8

Async Function

Await

Using async / await in express with node 8

True / false values (Truthy / Falsy)

In JavaScript, a truthy or falsy value is a value that is converted to a Boolean value when evaluated in a Boolean context. One of the most common examples of Boolean contexts is the evaluation of if conditions:

Each value is converted to true unless they are equal to the following values:

False

0

"" (empty string)

Null

Undefined

NaN

Here is an example of a Boolean context (boolean context):

If conditional evaluation

If (myVar) {}

MyVar can be any first-class first-class citizen (variable, function, Boolean), but it will be converted to a Boolean value because it will be performed on the value in the Boolean context.

Logic is not! After the operator

This operator returns false if its individual operands can be converted to true; otherwise, it returns true.

! 0 / / true-- 0 is a falsy (false) value, so it returns trueworthy true 0 / / false-0 is a falsy (false) value, so! 0 returns true, so! (! 0) returns false! "" / / false-- the empty string is a falsy (false) value, so NOT (NOT false) equals false

Constructor through Boolean object

New Boolean (0) / / falsenew Boolean (1) / / true

When evaluating a ternary expression

MyVar? "truthy": "falsy"

MyVar evaluates in a Boolean context.

Extended reading

Truthy (MDN)

Falsy (MDN)

Truthy and Falsy values in JS-Josh Clanton

Simple description of static method

The static keyword is used to declare static methods. A static method is a method that belongs to a class object and is inaccessible to any instance of that class.

Simple code example class Repo {static getName () {return "Repo name is modern-js-cheatsheet"}} / / Please note that we do not have to create an instance of the Repo class console.log (Repo.getName ()) / / Repo name is modern-js-cheatsheetlet r = new Repo (); console.log (r.getName ()) / / throws a TypeError: repo.getName is not a function details

Static methods can be called in another static method by using the this keyword, which does not apply to non-static methods. Non-static methods cannot access static methods directly using the this keyword.

Call another static method in a static method.

To call another static method in a static method, you can use the this keyword, like this

Class Repo {static getName () {return "Repo name is modern-js-cheatsheet"} static modifyName () {return this.getName () +'- added-this'}} console.log (Repo.modifyName ()) / / Repo name is modern-js-cheatsheet-added-this calls static methods in non-static methods.

Non-static methods can call static methods in two ways

# use the class (class) name

To access a static method in a non-static method, we can use the class name and call the static method like a property. For example, ClassName.StaticMethodName:

Class Repo {static getName () {return "Repo name is modern-js-cheatsheet"} useName () {return Repo.getName () + 'and it contains some really important stuff'}} / / We need to instantiate this class (class) to use the non-static method let r = new Repo () console.log (r.useName ()) / / Repo name is modern-js-cheatsheet and it contains some really important stuff

# practical constructor

Static methods can be called as properties on the constructor object.

Class Repo {static getName () {return "Repo name is modern-js-cheatsheet"} useName () {/ / call the static method return this.constructor.getName () + 'and it contains some really important stuff'}} / / We need to instantiate this class (class) to use the non-static method let r = new Repo () console.log (r.useName ()) / / Repo name is modern-js-cheatsheet and it contains some really important stuff to extend the reading

Static keyword- MDN

Static Methods- Javascript.info

Static Members in ES6- OdeToCode

Glossary scope (Scope)

There are "visible" values and expressions in the context, or they can be referenced. If the variable or expression is not in the current scope, it will not be available.

Source: MDN

Variability of variables (Variable mutation)

If a variable changes after its initial value, we call it variable.

Var myArray = []; myArray.push ("firstEl") / / myArray has changed

If a variable cannot be changed, we will say that the variable is immutable.

After reading the above, do you have any further understanding of modern JavaScript? If you want to know more knowledge or related content, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report