一、基础知识复习

郁子大约 7 分钟约 2159 字笔记React18李立超

(一)变量

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

1)没有 arguments

  • 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);

2)没有自身的 this

  • 内部的 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.模块化原则

  • 作为一个模块,不希望把内部逻辑变量都暴露出去
  • 作为导入方,也不希望导入无用的变量

3. export 导出

  • 决定一个模块中哪些内容可以被外部查看

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 };

4. import 导入

  • 用于将外部模块中导出的内容导入到当前模块中
  • 默认情况下, script 标签不能使用 import 语句,必须设置 typemodule

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 就是当前实例
  • 以函数形式执行时, thisundefined
  • 在有些场景下,希望方法中的 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());

(九)数组方法

1. map()

  • 不破坏原数组
  • 根据原数组返回一个新数组
  • 需要回调函数作为参数,回调函数的返回值作为新数组中的元素
  • 回调函数有三个参数
    • item :当前元素
    • index :当前元素索引
    • array :当前数组
  • 使用场景:将数组元素映射成统一结构的新数组,切忌当成 forEach 使用

2. filter()

  • 不破坏原数组
  • 从原数组中过滤得到符合条件的元素
  • 根据回调函数的返回值决定是否保留元素, true 保留, false 不保留

3. find()

  • 从原数组中过滤得到符合条件的 第一个 元素

4. reduce()

  • 用于合并数组中的元素
  • 有两个参数

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,
);
上次编辑于: