The second stop of front-end learning - JavaScript

Table of contents

1 Introduction

2. Variables and data types

2.1 Declare variables

2.2 Basic types 

2.3 Object types 

2.3.1 Function Function​

 2.3.2 Array Array

2.3.3 Object Object ⭐️⭐️

 3. Operators and expressions

1) ===

2) ||

4) ...

5) [] {}

 4. Control Statements

1) for in

2) for of

3) try catch

5. API

5.1 Environment preparation

5.2 Front-end case

5.3 Using Templates 

 5.4 Fetch API 

Cross domain issues (important) 

5.5 Modularity


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

  1. Responsible for creating sub-objects, providing properties and methods for sub-objects, functionally equivalent to construction methods

  2. 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 prototypeproperty

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

  1. 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

  2. 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

  1. To uninstall the existing nodejs

  2. When prompted to select the nvm and nodejs directories, be sure to avoid spaces in the directories

  3. Select [run as administrator] cmd program to execute nvm command

  4. 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 listwill 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

  • 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

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/qq_59212867/article/details/128514981