一、基础知识复习
大约 7 分钟约 2159 字
(一)变量
1.var
- 没有块级作用域
- 变量提升:无论在何处声明变量,都会在执行任何代码之前进行处理
- MDN - var 变量提升
a = "Hello";
var a;
2.let
- 有块级作用域
{
let a = "Hello";
console.log(a);
}
console.log(a);
3.const
- 和
let
类似,具有块级作用域,但是只能赋值一次 - 对于一些常量可以使用
const
声明
{
const b = "React";
console.log(b);
b = "ha"; // 报错
}
console.log(b);
const MAX_SIZE = 1000;
4.使用优先级
- 优先使用
const
- 需要修改值时用
let
- 尽量不出现
var
(二)解构赋值
1.数组解构
// let a, b;
// let arr = ['a', 'b'];
// [a, b] = arr;
// console.log(a, b);
const [a, b] = arr; // 常用
2.函数返回值解构
function fn() {
return ["c", "d"];
}
const [c, d] = fn();
...
扩展运算符
3. ...
变量,会接收剩余所有元素,只能放最后
arr = ["e", "f", "g", "h"];
const [e, f, , h] = arr; // 跳过g
const [i, j, ...rest] = arr; // rest = ['g','h']
4.对象解构
const obj = {
k: 1,
l: 2,
m: 3,
};
// 变量名和属性名不同
({ k: name, l: age, m: gender } = obj);
// 变量名和属性名相同
const { k, l, m } = obj;
5.解构数组交换变量
// 利用数组的解构来交换两个变量的位置
const o = 10,
p = 20;
[o, p] = [p, o];
// 交换数组中两个元素的位置
arr = [1, 3, 2];
[arr[1], arr[2]] = [arr[2], arr[1]];
(三)展开
1.展开数组
- 通过
...
扩展运算符展开一个数组
function fn(a, b, c) {
return a + b + c;
}
const arr = [1, 2, 3];
// 计算数组中三个数字的和
let res = fn(...arr);
2.拷贝数组
// 浅复制
const arr2 = [...arr];
// 创建新数组
const arr2 = [7, 8, 9, ...arr, 4, 5, 6];
3.拷贝对象
const obj = {
a: 1,
b: 2,
c: 3,
};
// 浅复制
const obj2 = { ...obj };
// 创建新对象
const obj2 = { a: 5, ...obj, d: 4 };
(四)箭头函数
1.格式
- 只有一个参数
参数 => 返回值
- 没有参数
() => 返回值
- 多个参数
(参数1, 参数2, ...) => 返回值
2.返回值
- 必须是一个表达式
- 如果是一个对象,则需要用
()
包裹返回语句() => ({ a: 1 })
- 如果有多条语句,则需要用
{}
包裹返回语句() => { if()...switch()... }
const fn = function (a) {
return a + "hello";
};
const fn2 = (a) => a + "hello";
const fn3 = (a, b) => a + b;
3.特点
arguments
1)没有 arguments
用于保存函数实参- 使用
args
代替剩余参数(可自定义命名)
function fn() {
console.log(arguments.length);
}
fn();
const fn2 = (...args) => {
console.log(arguments);
console.log(args);
};
fn2(1, 2, 3);
function fn3(a, b, ...args) {
console.log(args);
}
fn3();
const fn4 = (a, b, ...args) => {
console.log(args);
};
fn4(1, 2, 3);
this
2)没有自身的 - 内部的
this
是函数外层作用域的this
- 无法通过
call()
、apply()
、bind()
修改内部的this
值
const fn5 = () => {
console.log(this);
};
fn5(); // window
const obj = {
hello: () => {
console.log(this);
},
};
obj.hello(); // window
const obj2 = {
hello: function () {
console.log(this);
},
};
obj2.hello(); // {hello: f} =>obj2
3)无法作为构造函数使用
new fn3(); // 报错
(五)模块化
1.最原始的模块化写法
- 有依赖问题,需要按顺序引入依赖库
<script src="...."></script>
2.模块化原则
- 作为一个模块,不希望把内部逻辑变量都暴露出去
- 作为导入方,也不希望导入无用的变量
export
导出
3. - 决定一个模块中哪些内容可以被外部查看
1)默认导出
- 一个模块中只能有一个默认导出
export default xxx;
2)命名导出
export const b = 20;
const a = 10;
export const b = 20;
export const c = 30;
const obj = {
a: 1,
};
const fn = () => {
return a + b;
};
// 默认导出
export default a;
// 同时命名导出
export { obj, fn };
import
导入
4. - 用于将外部模块中导出的内容导入到当前模块中
- 默认情况下,
script
标签不能使用import
语句,必须设置type
为module
1)导入默认导出的变量
xxx
可以自定义,不需要与导出的模块变量名对应- 在网页中导入时,模块路径必须写完整
- 以
./
或../
开头,扩展名也需要写上,脚手架中可以省略.js
和.jsx
- 以
import xxx from './m1.js';
2)导入命名导出的变量
- 变量名需要与导出模块中的变量名对应
- 导出后可重命名
import { b, c as hello } from './m1.js';
<script type="module">
// 导入m1模块中的默认导出变量
import ha from "./m1.js";
console.log(ha);
</script>
<script type="module">
// 导入m1模块中的命名导出变量
import { b, c as hello } from "./m1.js";
console.log(b, hello);
</script>
<script type="module">
// 导入多种暴露变量
import a, { obj } from "./m1.js";
</script>
(六)类
1.定义类
- 类是对象的模版
- 决定了一个对象中有哪些属性和方法
- 使用
class
关键字定义类
class Person {
// 直接定义属性
name = "111";
age = 2;
// 构造函数
// 通过new创建对象时调用构造函数
// 通过this可引用当前对象,将参数赋值给对象中的属性
constructor(name, ...args) {
console.log(111, args);
this.name = name;
}
// 直接定义实例方法
run() {
console.log("hhhhhhh");
}
}
const p1 = new Person();
const p2 = new Person();
console.log(p1, p2, p1 === p2);
p1.run();
const p3 = new Person("a", 2);
console.log(p3);
2.类的特点
- 类中的所有代码都会在严格模式下执行
- 严格模式特点之一:函数
this
不是window
而是undefined
警告
在类中方法的 this
不是固定的
- 以方法形式调用时,
this
就是当前实例 - 以函数形式执行时,
this
是undefined
- 在有些场景下,希望方法中的
this
是固定的,不会因调用方式不同而改变- 使用
bind
修改this
值【较麻烦】 - 使用箭头函数定义类中的方法【常用】
- 使用
class MyClass {
// 将fn的this绑定为当前实例——较麻烦
// constructor() {
// this.fn = this.fn.bind(this);
// }
fn() {
console.log(this);
}
fn2 = () => {
console.log(this);
};
}
const mc = new MyClass();
console.log(mc);
// 以方法形式调用
mc.fn(); // MyClass {}
// 以函数形式执行
const test = mc.fn;
test(); // undefined
mc.fn2();
const test2 = mc.fn2;
test2();
(七)继承
- 提取多个类的重复代码
- 通过继承可以使得类中拥有其他类中的属性和方法
- 使用
extend
继承一个类,继承后相当于将该类的代码复制到当前类中 - 被继承的类为父类,继承父类的类为子类
- 子类继承父类后,将获得父类中所有的属性和方法
- 可以创建同名属性和方法来对父类属性和方法进行重写
- 子类重写构造函数时,必须在所有的
this
操作前使用super()
调用父类的构造函数
class Dog {
constructor(name, age) {
this.name = name;
this.age = age;
}
say = () => {
console.log(111);
};
}
class Cat {
constructor(name, age) {
this.name = name;
this.age = age;
}
say = () => {
console.log(222);
};
}
// 提取多个类重复代码
class Animal {
constructor(name, age) {
this.name = name;
this.age = age;
}
say = () => {
console.log(000);
};
}
class Snake extends Animal {
constructor(name, age, length) {
super(name, age);
this.length = length;
}
say = () => {
console.log(111);
};
}
class Mouse {}
const snake = new Snake("aaa", 2, 10);
console.log(snake);
snake.say();
const mouse = new Mouse("bbb", 3);
console.log(mouse);
mouse.say();
(八)静态属性
- 直接通过类调用的属性和方法称为静态属性和静态方法
- 使用
static
声明静态属性和静态方法 - 静态方法的
this
不是实例对象而是当前类对象
class MyClass {
name = "111";
fn = () => {
console.log(222);
};
static age = 17;
static fn2 = () => {
console.log(111);
console.log(this);
};
}
const mc = new MyClass();
mc.fn();
// MyClass.fn(); // 不能直接通过类名调用非静态属性和方法
console.log(MyClass.age, MyClass.fn2());
(九)数组方法
map()
1. - 不破坏原数组
- 根据原数组返回一个新数组
- 需要回调函数作为参数,回调函数的返回值作为新数组中的元素
- 回调函数有三个参数
item
:当前元素index
:当前元素索引array
:当前数组
- 使用场景:将数组元素映射成统一结构的新数组,切忌当成
forEach
使用
filter()
2. - 不破坏原数组
- 从原数组中过滤得到符合条件的元素
- 根据回调函数的返回值决定是否保留元素,
true
保留,false
不保留
find()
3. - 从原数组中过滤得到符合条件的 第一个 元素
reduce()
4. - 用于合并数组中的元素
- 有两个参数
1)参数 1:回调函数
- 必需
- 指定运算规则,有四个参数
previousValue
:上一次调用该回调函数的运算结果currentValue
:当前值index
:当前索引值array
:当前数组
2)参数 2:初始值
- 可选
- 指定第一次运算时的
previousValue
- 如果不指定则直接从第二个元素开始计算
const arr = [1, 2, 3, 4, 5];
console.log(arr.map((item, index, array) => item + 2));
console.log(arr.filter((item) => item % 2 === 0));
console.log(arr.find((item) => item % 2 === 0));
console.log(
arr.reduce((preValue, curValue, index, array) => preValue + curValue),
0,
);