‹ 返回笔记 Esc·

JavaScript / TypeScript 问题与修复

DOM & BOM & CSSOM DOM - document.xxx 是表示网页文档的编程接口,它将网页的内容(包括 HTML 元素)表示为对象,并允许开发者通过脚本语言(如 JavaScript…

DOM & BOM & CSSOM

DOM - document.xxx

是表示网页文档的编程接口,它将网页的内容(包括 HTML 元素)表示为对象,并允许开发者通过脚本语言(如 JavaScript)动态修改这些内容。通过 document 对象,JavaScript 可以访问和操作整个 HTML 文档的结构、内容和样式。

1// 通过 id 查找 HTML 元素
2var x=document.getElementById("intro");
3// 通过标签名查找 HTML 元素
4var y=x.getElementsByTagName("p");
5// 通过类名找到 HTML 元素
6var x=document.getElementsByClassName("intro");
7// 改变 HTML 内容
8document.getElementById("p1").innerHTML="新文本!";
9// 改变 HTML 样式
10document.getElementById("p2").style.color="blue";
11// 对事件做出反应
12<h1 onclick="this.innerHTML='Ooops!'">点击文本!</h1>
13// 创建 <p> 元素:
14var para = document.createElement("p");
15// 为 <p> 元素创建一个新的文本节点:
16var node = document.createTextNode("这是一个新的段落。");

BOM - window.xxx

BOM 是指浏览器的编程接口,它提供与浏览器窗口、历史记录、导航、显示区域等相关的交互能力。BOM 的核心对象是 window,它代表浏览器窗口,并包含多个子对象用于控制浏览器特性和操作。

1window.location: 获取或设置当前页面的 URL
2window.history: 访问浏览器的历史记录。
3window.alert(): 显示警告对话框。
4window.open(): 打开新窗口或标签。
5window.setTimeout(): 设置定时器,延迟执行代码。
6window.navigator: 获取浏览器的信息(如用户代理、平台等)。

CSSOM

CSSOM 是 CSS 对象模型,类似于 DOM,它是一个表示样式表(CSS)的编程接口。通过 CSSOM,开发者可以使用 JavaScript 动态地修改页面的样式,而不仅仅是通过修改 HTML 元素的 style 属性。


默认导入 & 命名导入

ES6 模块化规范

import axios from 'axios' 这是一个默认导入(default import)。axios 是 axios 库的默认导出,直接可以使用 axios 作为导入的对象。

1// math.js
2const multiply = (a, b) => a * b;
3export default multiply;
4// main.js
5import multiply from './math.js';
6console.log(multiply(4, 5));   // 输出: 20

import { Axios } from 'axios' 这是一个命名导入(named import)。在这种情况下,Axios 是 axios 库的一个命名导出成员。通过花括号,表示你从 axios 模块中只提取 Axios 这个具体导出,而不是整个模块。花括号{}用于从模块中解构出特定的导出成员。

1// math.js
2export const add = (a, b) => a + b;
3export const subtract = (a, b) => a - b;
4// main.js
5import { add, subtract } from './math.js';
6console.log(add(2, 3));        // 输出: 5
7console.log(subtract(5, 3));   // 输出: 2

import './mock' 通常用于执行一个模块中的副作用代码,比如模块在导入时会自动运行一些逻辑,而不需要显式导出任何内容。

1// mock.js
2console.log("Mock data initialized");
3// main.js
4import './mock';  // 导入时执行 mock.js 中的代码
5console.log("Main file executed");
6// 输出
7// Mock data initialized
8// Main file executed

默认导出方式

1export default multiply;  // 直接导出 multiply 作为默认导出。
2export { axios as default };  // 将现有的 axios 变量重命名为默认导出。

箭头函数

箭头函数的语法非常简洁,省略了 function 关键字,并且如果只有一个参数,可以省略括号。如果函数体只有一个表达式,还可以省略大括号和 return 关键字。

  1. 箭头函数的简写形式
1// 函数声明
2const functionName = (参数) => { 函数体 };
3// 没有参数
4const sayHello = () => {
5    console.log('Hello');
6};
7// 一个参数时可以省略括号
8const greet = name => {
9    console.log(`Hello, ${name}`);
10};
11// 两个参数及以上需要括号
12const add = (a, b) => {
13    return a + b;
14};
15// 如果函数体只有一行表达式,可以省略大括号和 return
16const addShort = (a, b) => a + b;
  1. 箭头函数中的 this 绑定 箭头函数的一个重要特性是不会创建自己的 this。它的 this 值是从外层上下文中继承的,也就是定义时的 this,而不是调用时的 this。这和普通函数不同,普通函数的 this 是动态绑定的,取决于函数是如何调用的。
1function Person() {
2    this.age = 0;
3    setInterval(function() {
4        this.age++;  // `this` 在这里指向全局对象 (在严格模式下是 `undefined`)
5        console.log(this.age);  // 输出 NaN 或 undefined
6    }, 1000);
7}
8const p = new Person();

在这个例子中,setInterval 的回调函数中的 this 不指向 Person 对象,而是指向全局对象(在浏览器中是 window)。因此,this.age 会出错。

1function Person() {
2    this.age = 0;
3    setInterval(() => {
4        this.age++;  // `this` 指向外层的 Person 对象
5        console.log(this.age);  // 正确输出:1, 2, 3, ...
6    }, 1000);
7}
8const p = new Person();

在这里,箭头函数不会绑定自己的 this,它继承了外部 Person 构造函数的 this,所以可以正确更新 this.age。

1- 普通函数的 this:
2- 箭头函数的 this:

3. 箭头函数不能用作构造函数 不能使用 new 关键字实例化箭头函数。尝试使用 new 会抛出错误。

1const Person = (name) => {
2    this.name = name;
3};
4// 错误:箭头函数不能作为构造函数
5const p = new Person('zailiang');  // TypeError: Person is not a constructor

模板字符串

模板字符串通过反引号(`)来定义,并且允许在字符串中使用 ${} 来嵌入表达式。

  1. 字符串插值 模板字符串的最大优势是可以在字符串中插入 JavaScript 表达式,而不用像传统字符串那样使用加号(+)进行拼接。
1const name = 'Zailiang';
2const age = 30;
3const message = `My name is ${name}, and I am ${age} years old.`;
4console.log(message);
5// 输出: My name is Zailiang, and I am 30 years old.
  1. 多行字符串 使用模板字符串,你可以直接编写多行字符串,而不用像以前那样在每一行的末尾添加 \n 或者手动拼接字符串。
1const multiLineString = `This is a string
2that spans across
3multiple lines.`;
4console.log(multiLineString);
5// 输出:
6// This is a string
7// that spans across
8// multiple lines.
  1. 表达式求值 模板字符串不仅可以嵌入简单的变量,还可以插入更复杂的表达式:
1const a = 10;
2const b = 20;
3const result = `The result of 10 * 20 is ${a * b}.`;
4console.log(result);
5// 输出: The result of 10 * 20 is 200.
  1. 函数调用 你甚至可以在模板字符串中调用函数,并将函数的返回值嵌入字符串中:
1function greet(name) {
2  return `Hello, ${name}!`;
3}
4const message = `${greet('Zailiang')} How are you today?`;
5console.log(message);
6// 输出: Hello, Zailiang! How are you today?
  1. 标签模板字符串 模板字符串还支持一种更高级的用法,称为 标签模板字符串(Tagged Templates)。它允许你将模板字符串和一个函数绑定在一起,函数可以对模板字符串中的内容进行处理。
1function tag(strings, ...values) {
2  console.log(strings);  // 模板字符串的静态部分
3  console.log(values);   // 插值表达式的值
4  return 'Processed string';
5}
6const result = tag`Hello, ${name}. You are ${age} years old.`;
7// 输出:
8// ["Hello, ", ". You are ", " years old."]
9// ["Zailiang", 30]
10console.log(result);
11// 输出: Processed string

函数声明与函数表达式的区别

函数是一种可调用的对象,它必须通过调用的方式来执行,并返回其内部逻辑处理后的结果。这个调用的行为就是在函数名后面加上 (),即 函数调用运算符。如果不加 (),只是引用了函数名,那么你得到的就是函数本身(即它的定义),而不是它的返回值。

函数声明:是标准的函数定义方式,函数声明会在代码执行之前被提升,因此可以在定义之前调用。

函数表达式:函数是作为一个表达式定义的,可以是匿名的,也可以有名字。它的特点是函数不会提前提升(hoisting)。

函数声明(Function Declaration)

1function sayHello() {
2    console.log("Hello");
3}
4
5sayHello();  // 输出: Hello

匿名函数表达式(Function Expression)

1const sayHello = function() {
2    console.log("Hello");
3};
4
5sayHello();  // 输出: Hello

命名函数表达式(Function Expression)

1const add = function sum(a, b) {
2    return a + b;
3};
4
5console.log(add(2, 3));  // 输出: 5

index.ts/index.js 这种写法导入

如果是 src/api/index.ts 则引入为 '@/api'

如果是 src/api/user.ts 则引入为 '@/api/user'

1import { activateVIP, getUserLevel, deleteUserLevel } from '@/api'