Table of contents
Cross domain issues (important)
1 Introduction
JavaScript ("JS" for short) is a lightweight, interpreted or just-in-time compiled programming language with function priority . Although it is famous as a scripting language for developing Web pages , it is also used in many non- browser environments. JavaScript is based on prototype programming, a multi-paradigm dynamic scripting language, and supports object -oriented, imperative, declarative, and functional programming paradigm.
The standard for JavaScript is ECMAScript . ES. As of 2012, all browsers fully support ECMAScript 5.1, and older browsers support at least ECMAScript 3 standards. On June 17, 2015, ECMA International released the sixth edition of ECMAScript, which is officially called ECMAScript 2015, but is often referred to as ECMAScript 6 or ES2015.
JavaScript is the most popular scripting language in the world. It can be used to change page content, control multimedia, create images, animations, etc.
The latest version has reached es6
2. Variables and data types
2.1 Declare variables
(1)let
let variable name = value
-
Variables declared by let can be assigned multiple times, for example
let a = 100; // 初始值是 100
a = 200; // ok, 被重新赋值为 20
2) const
-
The const modified is called a constant, which can only be assigned once
const b = 300; // 初始值是 300
b = 400; // error, 不能再次赋值
-
const does not mean that what it refers to is not modifiable, e.g.
const c = [1,2,3];
c[2] = 4; // ok, 数组内容被修改成 [1,2,4]
c = [5,6]; // error, 不能再次赋值
3) was
Variables declared with var can be assigned multiple times, for example
x var f = 100;f = 200;
2.2 Basic types
1,2) undefined and null
-
Execute an expression or function, no result is returned , and undefined appears
-
When accessing an element that does not exist in an array or an attribute that does not exist in an object , undefined appears
-
Define variable, not initialized , undefined appears
example :
console.log(1); // 函数没有返回值, 结果是 undefined
let a = 10; // 表达式没有返回值, 结果是 undefined
let b = [1,2,3];
console.log(b[10]); // 数组未定义元素是 undefined
let c = {"name":"张三"};
console.log(c.age); // 对象未定义属性是 undefined
let d;
console.log(d); // 变量未初始化是 undefined
both have in common
-
There are no properties, methods
-
The two are collectively called Nullish
difference between the two
-
undefined generated by js
-
null provided by the programmer
3) string ⭐️
Three ways to write js string
let a = "hello"; // 双引号
let b = "world"; // 单引号
let c = `hello`; // 反引号
The html code is as follows, how to express it with strings in java and js?
<a href="1.html">超链接</a>
Java seems to be more cumbersome, the double quotes in the a tag need to use escape characters
String s1 = "<a href=\"1.html\">超链接</a>";
String s2 = """
<a href="1.html">超链接</a>""";
js is more flexible
let s1 = '<a href="1.html">超链接</a>';
let s2 = `<a href="1.html">超链接</a>`;
Template strings
Requirements: splicing request parameters of URI, such as
/test?name=zhang&age=18
/test?name=li&age=20
traditional splicing
let name = ; // zhang li ...
let age = ; // 18 20 ...
let uri = "/test?name=" + name + "&age=" + age;
Template string method (must use `` symbol)
let name = ; // zhang li ...
let age = ; // 18 20 ...
let uri = `/test?name=${name}&age=${age}`;
4,5) number and bigint⭐️
The number type identifies a double-precision floating decimal, for example
10 / 3; // 结果 3.3333333333333335
Since it is a floating point decimal, it can be divided by zero
10 / 0; // 结果 Infinity 正无穷大
-10 / 0; // 结果 -Infinity 负无穷大
Floating-point decimals have operational precision issues, for example
2.0 - 1.1; // 结果 0.8999999999999999
string to number
parseInt("10"); // 结果是数字 10
parseInt("10.5"); // 结果是数字 10, 去除了小数部分
parseInt("10") / 3; // 结果仍视为 number 浮点数, 因此结果为 3.3333333333333335
parseInt("abc"); // 转换失败,结果是特殊值 NaN (Not a Number)
To represent a real integer, you need to use bigint, and the number ends with n to indicate that it is a bigint type
10n / 3n;
6) boolean ⭐️
In js, it is not boolean that can be used for conditional judgment, you can use [number], [string]... as the judgment condition in the if statement
let b = 1;
if(b) { // true
console.log("进入了");
}
At this time, there is a rule. When a conditional judgment is required, this value is regarded as true or false, and the value regarded as true is classified as truthy, and the value regarded as false is classified as falsy
The following values are all falsy
-
false
-
Nullish (null, undefined)
-
0, 0n, NaN
-
"" '' ``
i.e. a string of length zero
Most of the remaining values are truthy
Note: There are a few that are easy to be regarded as falsy but are actually truthy
-
"false", "0"
i.e. false for strings and zero for strings -
[]
empty array -
{}
empty object
2.3 Object types
2.3.1 Function Function
1. Define the function
function 函数名(参数) {
// 函数体
return 结果;
}
example
function add(a, b) {
return a + b;
}
2. Call the function
add(1, 2);// 返回 3
Features of function calls in js: There are no restrictions on the type and number of parameters, for example
add('a', 'b'); // 返回 ab
add(4, 5, 6); // 返回 9, 第三个参数没有被用到, 不会报错
add(1); // 返回 NaN, 这时 b 没有定义是 undefined, undefined 做数学运算结果就是 NaN
3. Default parameters
To achieve the effect of default parameters in java (spring), you have to do this:
Specify the defaultValue default value
@RestController
public class MyController {
@RequestMapping("/page")
@ResponseBody
public void page(
@RequestParam(defaultValue="1") int page,
@RequestParam(defaultValue="10") int size
){
// ...
}
}
Js:
function pagination(page = 1, size = 10) {
console.log(page, size);
}
4. Anonymous functions
Grammar: (with a layer of brackets outside~)
(function (参数) {
// 函数体
return 结果;
})
example
(function(a,b){
return a + b;
})
5. Usage scenarios
The first scenario: call immediately after definition (double brackets)
(function(a,b){
return a + b;
})(1,2)
The second scenario: as a method of other objects, such as
page has elements
<p id="p1">点我啊</p>
This element has an onclick method, which will be executed after the mouse clicks on this element. The onclick method is initially null and needs to be assigned before it can be used
document.getElementById("p1").onclick = (function(){
console.log("我要被点死啦~...");
});
6. Arrow functions
grammar:
(参数) => {
// 函数体
return 结果;
}
-
If there are no parameters, () should still be reserved
-
If there is only one parameter, () can be omitted
-
If there is only one line of code in the function body, {} can be omitted
-
If this line of code is the result, return can be omitted
document.getElementById("p1").onclick = () => console.log("aa");
7. Functions are objects
The following forms are very uncommon in js!
1. Can participate in assignment, for example, named functions can also participate in assignment
function abc() {
console.log("bb");
}
document.getElementById("p1").onclick = abc;
2. It has attributes and methods, executes console.dir(abc)
, and the output results are as follows
ƒ abc()
arguments: null
caller: null
length: 0
name: "abc"
➡prototype: {constructor: ƒ}
[[FunctionLocation]]: VM1962:1
➡[[Prototype]]: ƒ ()
➡[[Scopes]]: Scopes[1]
-
Among them, the ones marked with f are methods, and the ones without are attributes
-
Those with the ➡ symbol can continue to expand, and are omitted due to space limitations
-
[[ ]]
Those with are built-in properties, which cannot be accessed, but can only be viewed -
It is relatively important that
[[Prototype]]
and[[Scopes]]
will be mentioned later in inheritance and scope
3. Can be used as method parameters
function a() {
console.log('a')
}
function b(fn) { // fn 将来可以是一个函数对象
console.log('b')
fn(); // 调用函数对象
}
b(a)
4. Can be used as method return value
function c() {
console.log("c");
function d() {
console.log("d");
}
return d;
}
c()()
c() is called d, so c()() becomes d()
8. Function scope
Functions can be nested (very common in js code, but the nested form is more anonymous functions, arrow functions)
function a() {
function b() {
}
}
See the example below
function c() {
var z = 30;
}
var x = 10;
function a() {
var y = 20;
function b() {
// 看这里
console.log(x, y);
}
b();
}
a();
The function of method b is as shown in the figure below
The background here only shows the scope that does not include its own method body
-
The scope is defined by the function as the dividing line, and all functions are the global scope
-
When looking up variables, look from the inside out
-
If the variable is found in the inner scope, it will stop searching and will not look for the outer layer
-
The variable cannot be found in all scopes, and an error is reported
-
-
The scope is essentially the property of the function object, which can be viewed and debugged through console.dir
Supplement: The difference between let and var (scope)
If the outer layer of the function refers to a let variable, then the ordinary {} in the outer layer will also serve as a scope boundary, and the outermost let also occupies a script scope
let x = 10;
if(true) {
let y = 20;
function b() {
console.log(x,y);
}
console.dir(b);
}
If the outer layer of the function refers to a var variable, the outer ordinary {} will not be regarded as a boundary
var x = 10;
if(true) {
var y = 20;
function b() {
console.log(x,y);
}
console.dir(b);
}
If the var variable has the same name, they will be regarded as the same variable in the same scope
var e = 10;
if(true) {
var e = 20;
console.log(e); // 打印 20
}
console.log(e); // 因为是同一个变量,还是打印 20
If it is let, it is treated as two variables in two scopes
let e = 10;
if(true) {
let e = 20;
console.log(e); // 打印 20
}
console.log(e); // 打印 10
To distinguish the e inside from the e outside, the easiest way is to change it to let, or use a function to define the scope
Therefore, in most cases, it is recommended to use let to declare variables~
2.3.2 Array Array
grammar
// 创建数组
let arr = [1,2,3];
// 获取数组元素
console.log(arr[0]); // 输出 1
// 修改数组元素
array[0] = 5; // 数组元素变成了 [5,2,3]
// 遍历数组元素,其中 length 是数组属性,代表数组长度
for(let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
-
push、shift、splice
let arr = [1,2,3];
arr.push(4); // 向数组尾部(右侧)添加元素, 结果 [1,2,3,4]
arr.shift(); // 从数组头部(左侧)移除元素, 结果 [2,3,4]
arr.splice(1,1); // 删除【参数1】索引位置的【参数2】个元素,结果 [2,4]
-
join
let arr = ['a','b','c'];
arr.join(); // 默认使用【,】作为连接符,结果 'a,b,c'
arr.join(''); // 结果 'abc'
arr.join('-'); // 结果 'a-b-c'
-
map、filter、forEach
let arr = [1,2,3,6];
function a(i) { // 代表的新旧元素之间的变换规则
return i * 10
}
// arr.map(a) // 具名函数,结果 [10,20,30,60]
// arr.map( (i) => {return i * 10} ); // 箭头函数
arr.map( i => i * 10 ); // 箭头函数
-
The function passed to map, the parameter represents the old element, and the return value represents the new element
Internal implementation of map (pseudocode)
function map(a) { // 参数是一个函数
let narr = [];
for(let i = 0; i < arr.length; i++) {
let o = arr[i]; // 旧元素
let n = a(o); // 新元素
narr.push(n);
}
return narr;
}
filter example
let arr = [1,2,3,6];
arr.filter( (i)=> i % 2 == 1 ); // 结果 [1,3]
-
The function passed to filter, the parameter represents the old element, returns true to indicate the element to be left
forEach example
let arr = [1,2,3,6];
/*for(let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}*/
arr.forEach( (i) => console.log(i) );
two titles
-
Higher order functions, map, filter, forEach
-
A callback function, such as a function passed in as an argument
2.3.3 Object Object ⭐️⭐️
grammar
let obj = {
属性名: 值,
方法名: 函数,
get 属性名() {},
set 属性名(新值) {}
}
Example 1
let stu1 = {
name: "小明",
age: 18,
study: function(){
console.log(this.name + "爱学习");
}
}
Example 2
let name = "小黑";
let age = 20;
let study = function(){
console.log(this.name + "爱学习");
}
let stu2 = { name, age, study }
Example 3 (emphasis)
let stu3 = {
name: "小白",
age: 18,
study(){
console.log(this.name + "爱学习");
}
}
-
Note : The object method is written in this way, only inside the object
Example 4 get, set method
let stu4 = {
_name: null, /*类似于java中私有成员变量*/
get name() {
console.log("进入了get");
return this._name;
},
set name(name) {
console.log("进入了set");
this._name = name;
}
}
call get, set
stu4.name = "小白"
console.log(stu4.name)
Features: attribute addition and deletion
Compare Object in Java
-
Objects in Java are created using classes as templates. Objects cannot be separated from the scope of class templates. The properties and available methods of an object are determined.
-
js object does not require any templates, its properties and methods can be added or subtracted at any time
let stu = {name:'张三'};
stu.age = 18; // 添加属性
delete stu.age; // 删除属性
stu.study = function() { // 添加方法
console.log(this.name + "在学习");
}
Add get, set, need to use Object.definePropery
let stu = {_name:null};
Object.defineProperty(stu, "name", {
get(){
return this._name;
},
set(name){
this._name = name;
}
});
-
Parameter 1: target object
-
Parameter 2: attribute name
-
Parameter 3: Definition of get, set
Features: this
First, let's have an understanding of this in Java
public class TestMethod {
static class Student {
private String name;
public Student(String name) {
this.name = name;
}
public void study(Student this, String subject) {
System.out.println(this.name + "在学习 " + subject);
}
}
public static void main(String[] args) {
Student stu = new Student("小明");
// 下面的代码,本质上是执行 study(stu, "java"),因此 this 就是 stu
stu.study("java");
}
}
-
this in Java is an implicit parameter
-
In Java, we say that this represents the object that calls the method
this in js is also an implicit parameter, but it is related to the function runtime context
For example, a "single-out" function
function study(subject) {
console.log(this.name + "在学习 " + subject)
}
have a test
study("js"); // 输出 在学习 js
Returns an empty string.
This is because the function is executed at this time, the global object window is regarded as this, and the name property of the window object is an empty string
Same function if as a method of an object
let stu = {
name:"小白",
study
}
In this case, the current object will be used as this
stu.study('js'); // 输出 小白在学习 js
You can also dynamically change this
let stu = {name:"小黑"};
study.call(stu, "js"); // 输出 小黑在学习 js
When the study is executed this time, the first parameter stu of the call is used as this
One exception is that the this appearing in the arrow function is understood by the outer this
use anonymous function
let stu = {
name: "小花",
friends: ["小白","小黑","小明"],
play() {
this.friends.forEach(function(e){
console.log(this.name + "与" + e + "在玩耍");
});
}
}
stu.play()
The output is:
Playing with Xiaobai Playing
with Xiaohei Playing
with Xiaoming
The previous this.name is an empty string
If you use an arrow function,
let stu = {
name: "小花",
friends: ["小白","小黑","小明"],
play() {
this.friends.forEach(e => {
console.log(this.name + "与" + e + "在玩耍");
})
}
}
-
The function where this.name is located is an arrow function, so this depends on its outer play function, and play is a method belonging to stu, so this represents the stu object
The output is:
Xiao Hua and Xiao Bai are playing
Xiao Hua and Xiao Hei are playing
Xiao Hua and Xiao Ming are playing
Another way to use arrow functions is to define a variable equal to this
let stu = {
name: "小花",
friends: ["小白","小黑","小明"],
play() {
let me = this;
this.friends.forEach(function(e){
console.log(me.name + "与" + e + "在玩耍");
});
}
}
Features: prototypal inheritance
let father = {
f1: '父属性',
m1: function() {
console.log("父方法");
}
}
let son = Object.create(father);
console.log(son.f1); // 打印 父属性
son.m1(); // 打印 父方法
-
father is the parent object, when son calls .m1 or .f1, if the own object does not exist, it goes to the parent object to find
-
son himself can add his own properties and methods
-
There are special properties in son
__proto__
to represent its parent object, js term: prototype object of son -
Different browsers
__proto__
display differently when printing the attributes of son-
Edge print console.dir(son) shows
[[Prototype]]
-
Firefox print console.dir(son) shows
<prototype>
-
Feature: Function-based prototypal inheritance
For convenience reasons, js provides a function-based prototype inheritance
function responsibility
Responsible for creating sub-objects, providing properties and methods for sub-objects, functionally equivalent to construction methods
The function has a special attribute prototype, which is the parent object of the child object created by the function
Notice! The name is different, the role of this property is to provide a prototype for the new object
function cons(f2) {
// 创建子对象(this), 给子对象提供属性和方法
this.f2 = f2;
this.m2 = function () {
console.log("子方法");
}
}
// cons.prototype 就是父对象
cons.prototype.f1 = "父属性";
cons.prototype.m1 = function() {
console.log("父方法");
}
Create child objects with the new keyword
let son = new cons("子属性")
The subobject's __proto__
is the function's prototype
property
Json
When we talked about the http request format before, we talked about the data format of json. Its syntax looks very similar to the js object, for example:
A json object can look like this:
{
"name":"张三",
"age":18
}
A js object looks like this:
{
name:"张三",
age:18
}
So what is the difference between them? I summed up these points
-
Essentially different
-
The json object is essentially a string. Its responsibility is to serve as a format for transferring data between the client and the server. Its attributes are just like
-
The js object is a real object, which can have attribute methods
-
-
grammatical details are different
-
Only null, true|false, numbers, strings (only double quotes), objects, arrays can be contained in json
-
There cannot be other js object features in json, such as methods, etc.
-
Attributes in json must be enclosed in double quotes
-
Conversion of json string to js object
JSON.parse(json字符串); // 返回js对象
JSON.stringify(js对象); // 返回json字符串
3. Operators and expressions
There are mainly the following types:
-
+ - * / % **
-
+= -= *= /= %= **=
-
++ --
-
bit operation, shift operation
-
== != > >= < <=
-
=== !==
⭐️ -
&& || !
⭐️ -
?? ?.
⭐️ -
...
⭐️ -
Destructuring assignment ⭐️
Like addition, subtraction, multiplication and division, which is the same as in Java, it doesn't make much sense to say it, so pick a few that you haven't seen before and write~
1) ===
Strict equality operator, used for logical judgment, also known as absolute equality, the value and type are equal to be considered equal
1 == 1 // 返回 true
1 == '1' // 返回 true,会先将右侧的字符串转为数字,再做比较
1 === '1' // 返回 false,类型不等,直接返回 false
typeof Check the type of a value
typeof 1 // 返回 'number'
typeof '1' // 返回 'string'
2) ||
Requirement: If parameter n is not passed, give it a [male]
function test(n = '男') {
console.log(n);
}
it's ok
function test(n) {
if(n === undefined) {
n = '男';
}
console.log(n);
}
You can also do this: the three-bit operator
function test(n) {
n = (n === undefined) ? '男' : n;
console.log(n);
}
Or even this:
function test(n) {
n = n || '男';
console.log(n);
}
Its syntax is:
值1 || 值2
If value 1 is Truthy, return value 1, if value 1 is Falsy return value 2
3) ?? and ?.
??
grammar
值1 ?? 值2
-
Value 1 is nullish, return value 2
-
Value 1 is not nullish, return value 1
Requirement, if the parameter n is not passed or null, give it a 【male】
If the traditional method
function test(n) {
if(n === undefined || n === null) {
n = '男';
}
console.log(n);
}
use? ?
function test(n) {
n = n ?? '男';
console.log(n);
}
?.
Requirements, the function parameter is an object, which may contain sub-properties
For example, the parameter might be
let stu1 = {
name:"张三",
address: {
city: '北京'
}
};
let stu2 = {
name:"李四"
}
let stu3 = {
name:"李四",
address: null
}
Now to access subproperties (problems)
Like stu1, there is an address attribute, and no error will be reported, but like stu2, stu3 will report an error
function test(stu) {
console.log(stu1.address.city)
}
Now that is to say, through a certain method, if there is such a sub-attribute, it will be output, if not, no error will be reported
by traditional means
function test(stu) {
if(stu.address === undefined || stu.address === null) {
console.log(undefined);
return;
}
console.log(stu.address.city)
}
use? .
What it means is: when a property is nullish, short circuit and return undefined
function test(stu) {
console.log(stu.address?.city)
}
4) ...
This is a spread operator
Function 1: Break up the array and pass the elements to multiple parameters
let arr = [1,2,3];
function test(a,b,c) {
console.log(a,b,c);
}
Requirements, pass the array elements to the function parameters in turn
traditional writing
test(arr[0],arr[1],arr[2]); // 输出 1,2,3
Spread operator notation
test(...arr);
-
Breaking up can be understood as [removing] the square brackets outside the array, leaving only the array elements
Function 2: copy array or object
array:
let arr1 = [1,2,3];
let arr2 = [...arr1]; // 复制数组
object
let obj1 = {name:'张三', age: 18};
let obj2 = {...obj1}; // 复制对象
Note : The spread operator copy is a shallow copy, for example
let o1 = {name:'张三', address: {city: '北京'} }
let o2 = {...o1};
Function 3: Merge arrays or objects
merge array
let a1 = [1,2];
let a2 = [3,4];
let b1 = [...a1,...a2]; // 结果 [1,2,3,4]
let b2 = [...a2,5,...a1] // 结果 [3,4,5,1,2]
merge object
let o1 = {name:'张三'};
let o2 = {age:18};
let o3 = {name:'李四'};
let n1 = {...o1, ...o2}; // 结果 {name:'张三',age:18}
let n2 = {...o3, ...o2, ...o1}; // 结果{name:'李四',age:18}
-
Attributes with the same name appear when copying an object, and the later ones will overwrite the previous ones
5) [] {}
destructuring assignment
[ ]
used when declaring variables
let arr = [1,2,3];
let [a, b, c] = arr; // 结果 a=1, b=2, c=
used when declaring parameters
let arr = [1,2,3];
function test([a,b,c]) {
console.log(a,b,c) // 结果 a=1, b=2, c=3
}
test(arr);
{ }
used when declaring variables
let obj = {name:"张三", age:18};
let {name,age} = obj; // 结果 name=张三, age=18
used when declaring parameters
let obj = {name:"张三", age:18};
function test({name, age}) {
console.log(name, age); // 结果 name=张三, age=18
}
test(obj)
4. Control Statements
There are mainly the following
-
if ... else
-
switch
-
while
-
do ... while
-
for
-
for ... in
⭐️ -
for ... of
⭐️ -
try ... catch
⭐️
Let’s not talk about if...else, swtich, while, which are not used in Java~ just talk about the stars
1) for in
Mainly used to traverse objects
let father = {name:'张三', age:18, study:function(){}};
for(const n in father) {
console.log(n);
}
-
Where const n represents the property name traversed
-
Note 1: The method name can also be traversed (it is actually a special attribute)
-
Note 2: When traversing the child object, the properties of the parent object will be traversed
let son = Object.create(father);
son.sex = "男";
for(const n in son) {
console.log(n);
}
-
Note 3: To get the attribute value in for in, use the [] syntax instead of the . syntax
for(const n in son) {
console.log(n, son[n]);
}
2) for of
It is mainly used to traverse the array, and it can also be other iterable objects, such as Map, Set, etc.
let a1 = [1,2,3];
for(const i of a1) {
console.log(i);
}
let a2 = [
{name:'张三', age:18},
{name:'李四', age:20},
{name:'王五', age:22}
];
for(const obj of a2) {
console.log(obj.name, obj.age);
}
for(const {name,age} of a2) {
console.log(name, age);
}
3) try catch
Throw an exception, the same as Java
let stu1 = {name:'张三', age:18, address: {city:'北京'}};
let stu2 = {name:'张三', age:18};
function test(stu) {
try {
console.log(stu.address.city)
} catch(e) {
console.log('出现了异常', e.message)
} finally {
console.log('finally');
}
}
5. API
5.1 Environment preparation
1) install nvm
nvm is (node version manager), the advantage is that it is convenient to switch node.js version
Reference Big Brother: Introduction, installation, and use of nvm (simple and clear)_Yang.'s blog-CSDN blog_nvm
Installation Precautions
-
To uninstall the existing nodejs
-
When prompted to select the nvm and nodejs directories, be sure to avoid spaces in the directories
-
Select [run as administrator] cmd program to execute nvm command
-
Set the domestic mirror address before the first run (after npm is installed)
nvm node_mirror http://npm.taobao.org/mirrors/node/
nvm npm_mirror https://npm.taobao.org/mirrors/npm/
First check what versions are available
nvm list available
output
| CURRENT | LTS | OLD STABLE | OLD UNSTABLE |
|--------------|--------------|--------------|--------------|
| 18.7.0 | 16.16.0 | 0.12.18 | 0.11.16 |
| 18.6.0 | 16.15.1 | 0.12.17 | 0.11.15 |
| 18.5.0 | 16.15.0 | 0.12.16 | 0.11.14 |
| 18.4.0 | 16.14.2 | 0.12.15 | 0.11.13 |
| 18.3.0 | 16.14.1 | 0.12.14 | 0.11.12 |
| 18.2.0 | 16.14.0 | 0.12.13 | 0.11.11 |
| 18.1.0 | 16.13.2 | 0.12.12 | 0.11.10 |
| 18.0.0 | 16.13.1 | 0.12.11 | 0.11.9 |
| 17.9.1 | 16.13.0 | 0.12.10 | 0.11.8 |
| 17.9.0 | 14.20.0 | 0.12.9 | 0.11.7 |
| 17.8.0 | 14.19.3 | 0.12.8 | 0.11.6 |
| 17.7.2 | 14.19.2 | 0.12.7 | 0.11.5 |
| 17.7.1 | 14.19.1 | 0.12.6 | 0.11.4 |
| 17.7.0 | 14.19.0 | 0.12.5 | 0.11.3 |
| 17.6.0 | 14.18.3 | 0.12.4 | 0.11.2 |
| 17.5.0 | 14.18.2 | 0.12.3 | 0.11.1 |
| 17.4.0 | 14.18.1 | 0.12.2 | 0.11.0 |
| 17.3.1 | 14.18.0 | 0.12.1 | 0.9.12 |
| 17.3.0 | 14.17.6 | 0.12.0 | 0.9.11 |
| 17.2.0 | 14.17.5 | 0.10.48 | 0.9.10 |
It is recommended to install LTS (Long Term Support)
nvm install 16.16.0
nvm install 14.20.0
Executing nvm list
will list the installed versions
switch to 16.16.0
nvm use 16.16.0
switch to 14.20.0
nvm use 14.20.0
2) Check npm
Npm is a js package manager, similar to maven in the java world, make sure it uses a domestic image
check image
npm get registry
If the return is not https://registry.npm.taobao.org/
, you need to do the following settings
npm config set registry https://registry.npm.taobao.org/
3) Build a front-end server
Create a new client folder to save the project, enter the folder, open powershell to execute
npm install express --save-dev
These three files will appear, which means that the environment has been set up
Then modify the package.json file and change the server to module
{
"type": "module",
"devDependencies": {
"express": "^4.18.1"
}
}
Write main.js code
import express from 'express'
const app = express()
app.use(express.static('./'))
app.listen(7070)
Finally execute the main.js code (running the front-end server)
node main.js
5.2 Front-end case
Preliminary effect
architecture
-
Only static pages on the front end, using Express server
-
The backend uses the Tomcat server to obtain database data through frameworks such as SpringBoot and MyBatis
1) Find element
-
document.getElementById - look up an element by id value
-
[document|element].querySelector - finds the first matching element based on the selector
-
[document|element].querySelectorAll - Find all matching elements based on selector
For example, there is the following Html code:
<div>
<div class="title">学生列表</div>
<div class="thead">
<div class="row bold">
<div class="col">编号</div>
<div class="col">姓名</div>
<div class="col">性别</div>
<div class="col">年龄</div>
</div>
</div>
<div class="tbody">
<div class="row">
<div class="col">1</div>
<div class="col">张三</div>
<div class="col">男</div>
<div class="col">18</div>
</div>
</div>
</div>
implement
document.querySelector('.title'); // 找到 <div class="title">学生列表</div>
implement
document.querySelector('.col'); // 找到 <div class="col">编号</div>
implement
document.querySelectorAll('.col');
/*
找到的是一个集合
<div class="col">编号</div>
<div class="col">姓名</div>
<div class="col">性别</div>
<div class="col">年龄</div>
<div class="col">1</div>
<div class="col">张三</div>
<div class="col">男</div>
<div class="col">18</div>
*/
implement
const thead = document.querySelector('.thead');
// 只在 thead 元素范围内找
thead.querySelectorAll('.col');
/*
找到的是一个集合
<div class="col">编号</div>
<div class="col">姓名</div>
<div class="col">性别</div>
<div class="col">年龄</div>
*/
According to the id attribute search can be used
document.getElementById("id值")
can also be used
document.querySelector("#id值")
2) Modify element content
-
element.innerHTML
-
element.textContent
For example
document.querySelector('.title').innerHTML = '侠客列表'
Their difference:
innerHTML parses tags within the content, such as
textContext does not parse tags in content
Assigning an empty string to innerHTML or textContent can realize the effect of emptying the label content.
5.3 Using Templates
Look directly at the code:
<div>
<div class="title">学生列表</div>
<div class="thead">
<div class="row bold">
<div class="col">编号</div>
<div class="col">姓名</div>
<div class="col">性别</div>
<div class="col">年龄</div>
</div>
</div>
<div class="tbody">
</div>
</div>
<template id="tp">
<div class="row">
<div class="col">xx</div>
<div class="col">xx</div>
<div class="col">xx</div>
<div class="col">xx</div>
</div>
</template>
<script>
// 将来这些数据从 java 端返回
let array = [
{ id: 1, name: '张三', sex: '男', age: 18 },
{ id: 2, name: '李四', sex: '女', age: 17 }
];
const tp = document.getElementById("tp");
const row = tp.content;
const [c1,c2,c3,c4] = row.querySelectorAll(".col");
const tbody = document.querySelector('.tbody');
for(const {id,name,sex,age} of array) {
c1.textContent = id;
c2.textContent = name;
c3.textContent = sex;
c4.textContent = age;
// 复制元素
const newRow = document.importNode(row, true);
// 建立父子关系,左边父,右边子
tbody.appendChild(newRow);
}
</script>
5.4 Fetch API
Fetch API can be used to obtain remote data, it has two ways to receive results, synchronous and asynchronous
Format:
fetch(url, options) // 返回 Promise
Synchronously
const 结果 = await Promise
// 后续代码
-
The await keyword must be used within a function marked async
-
Subsequent code will not be executed until the result is returned
asynchronous mode
Promise
.then(结果 => { ... })
// 后续代码
-
Subsequent code can be executed without waiting for the result to return
Example: have students.json file on express server
[
{ "id": 1, "name": "张三", "sex": "男", "age": 18 },
{ "id": 2, "name": "李四", "sex": "女", "age": 17 }
]
Now use the fetch api to get these data and display
Synchronously
<script>
async function findStudents() {
try {
// 获取响应对象
const resp = await fetch('students.json')
// 获取响应体, 按json格式转换为js数组
const array = await resp.json();
// 显示数据
const tp = document.getElementById("tp");
const row = tp.content;
const [c1,c2,c3,c4] = row.querySelectorAll(".col");
const tbody = document.querySelector('.tbody');
for(const {id,name,sex,age} of array) {
c1.textContent = id;
c2.textContent = name;
c3.textContent = sex;
c4.textContent = age;
// 复制元素
const newRow = document.importNode(row, true);
// 建立父子关系
tbody.appendChild(newRow);
}
} catch (e) {
console.log(e);
}
}
findStudents()
</script>
-
fetch('students.json') will send the request internally, but the response result cannot be returned immediately, so await is to wait for the response result to return
-
Among them, resp.json() does not return the result immediately, it also returns the Promise object, and it also needs to cooperate with await to get the result
asynchronous mode
<script>
fetch('students.json')
.then( resp => resp.json() )
.then( array => {
// 显示数据
const tp = document.getElementById("tp");
const row = tp.content;
const [c1,c2,c3,c4] = row.querySelectorAll(".col");
const tbody = document.querySelector('.tbody');
for(const {id,name,sex,age} of array) {
c1.textContent = id;
c2.textContent = name;
c3.textContent = sex;
c4.textContent = age;
// 复制元素
const newRow = document.importNode(row, true);
// 建立父子关系
tbody.appendChild(newRow);
}
})
.catch( e => console.log(e) )
</script>
-
The first then is to call the arrow function in it after the response is returned, and the arrow function parameter is the resp response object
-
The second then is to call the arrow function in it after the json parsing is completed, and the arrow function parameter is the parsing result (in this case, an array array)
-
Only when the previous then returns a Promise object can the next then be chained
Cross domain issues (important)
As shown in the picture:
In layman's terms, the html in the browser comes from our front-end server, localhost7070, but our request to obtain data is sent to localhost8080, which is our back-end server, which does not pass the same-origin detection of the browser, so later The data responded by the terminal cannot be read.
Homology judgment has the following rules:
-
As long as one of the protocol, host, and port is different, the source is different, for example
-
http://localhost:7070/a and https://localhost:7070/b are different sources
-
-
The same-origin check is the behavior of the browser, and it is only for fetch and xhr requests
-
If it is other clients, such as java http client, postman, they do not check the same origin
-
Requests sent through form submissions or browsers directly entering url addresses will not perform same-origin checks
-
-
For more information, please refer to
Two solutions:
1. Request response header resolution
as shown in the picture
-
A fetch request cross-domain will carry an Origin header, which represents [where the requested resource originates from], through which the target can identify whether cross-domain occurs
-
In our example: student.html sends a fetch request and tells tomcat that I originate from localhost:7070
-
-
The target resource tells the browser [which sources are allowed to use this response] by returning the Access-Control-Allow-Origin header
-
In our example: tomcat returns a fetch response, telling the browser that this response allows resource usage from localhost:7070
-
How to return this Access-Control-Allow-Origin header specifically? 90
It's very simple, we just need to add an annotation @CrossOrigin("Front-end server address") above the code of the back-end service request
In this way, the response header returned by the server will have Access-Control-Allow-Origin
2. By proxy
The first step is to install a plugin
npm install http-proxy-middleware --save-dev
import in main.js
import {createProxyMiddleware} from 'http-proxy-middleware'
Set proxy address:
app.use('/api', createProxyMiddleware({ target: 'http://localhost:8080', changeOrigin: true }));
main.js
import express from 'express'
import {createProxyMiddleware} from 'http-proxy-middleware'
const app = express()
app.use('/api', createProxyMiddleware({ target: 'http://localhost:8080', changeOrigin: true }));
app.use(express.static('./'))
app.listen(7070)
In this way, our api request represents our localhost:8080 interface.
5.5 Modularity
Single export const, let, function
export const a = 10;
export let b = 20;
export function c() {
console.log('c');
}
export together
const a = 10;
let b = 20;
function c() {
console.log('c')
}
export {a,b,c}
Export default, only one
export const a = 10;
export let b = 20;
export function c() {
console.log('c')
}
export default b;
import syntax
<script type="module">
import 语句
</script>
entire import
import * as module from '/1.js'
console.log(module.a) // 输出10
console.log(module.b) // 输出20
module.c() // 输出c
single import
import {a,c} from '/1.js'
console.log(a) // 输出10
c() // 输出c
import default
import x from '/1.js'
console.log(x) // 输出20