JavaScript 笔记 --- part6 --- JS进阶 (part1)

JS 进阶(part1)

作用域

局部作用域

  • 定义: 局部作用域指的是在函数内部定义的变量,只能在函数内部访问,外部不能访问。

  • 特点: 局部作用域变量只能在函数内部或代码块中访问,外部不能访问。

  • 分类:

    • 函数作用域: 指的是在函数内部定义的变量,只能在函数内部访问,外部不能访问。

    • 块作用域: 指的是在代码块({})中定义的变量,可以在代码块中访问,外部不能访问。

全局作用域

  • 定义: 全局作用域指的是在函数外部定义的变量,可以在整个程序范围内访问。

  • 特点: 全局作用域变量可以在整个程序范围内访问。

  • 建议: 不建议在全局作用域定义变量,容易造成命名冲突。

作用域链

  • 定义: 作用域链是由一系列变量对象组成的链式结构,它决定了变量的查找方式。

  • 作用: 作用域链的作用是保证对变量的访问权限。

  • 机制: 当解释器在执行代码时,会在当前作用域和上层作用域中查找变量,如果在当前作用域中没有找到,则继续在上层作用域中查找,直到找到为止。

  • 特点: 子作用域能够访问父作用域, 但父作用域不能访问子作用域。

JS 垃圾回收机制

  • 定义: 垃圾回收机制是指自动释放不再使用的内存,以便为应用程序提供更多的内存空间。

  • 内存的生命周期:

    1. 分配: 当我们声明变量、函数或创建对象时,系统会在内存中分配一块内存空间。
    2. 使用: 程序运行时(读写内存),系统使用分配的内存空间。
    3. 释放: 程序运行结束时,系统释放分配的内存空间。
  • 注意:

    1. 全局变量: 全局变量的生命周期与程序运行时长相关,当程序结束时,系统会自动释放全局变量所占用的内存。
    2. 局部变量: 局部变量的生命周期与函数执行时长相关,当函数执行结束时,系统会自动释放局部变量所占用的内存。
    3. 内存泄露: 未释放或无法释放内存。
  • 算法说明:

    1. 标记清除: 定义"无法到达的对象", 从根部出发, 如果能找到标记对象, 暂时不清除, 找不到则清除。
    2. 引用计数: 定义"内存不再使用", 就是看一个对象是否有指向它的引用, 如果没有, 则说明该对象不再使用, 可以进行回收。 / 缺点: 嵌套引用时, 无法回收。

闭包

  • 定义: 闭包是指有权访问另一个函数作用域的函数,创建闭包的常见方式是函数嵌套。

  • 特点: 闭包 = 内层函数 + 外层函数的变量

  • 作用: 封闭数据, 提供操作, 外部也可以访问函数内部的变量

  • 优点:

    1. 可以读取函数内部的变量和参数
    2. 可以在函数外部修改变量的值
    3. 延迟初始化, 只有在调用函数时才初始化变量
  • 缺点:

    1. 内存泄漏, 闭包会占用内存, 导致内存泄漏
    2. 性能问题, 每次调用函数都会创建新的闭包, 性能较低
javascript 复制代码
function outer() {
  let a = 1;
  function inner() {
    console.log(a);
  }
  return inner;
}

cosnt fun = outer();
fun();

变量提升

  • 定义: 变量提升是指 JavaScript 在执行代码前,会将在当前作用域下, var 声明的变量和函数, 提升到当前作用域的最前面, 只提升声明, 不提升赋值。

  • 作用: 变量提升可以让变量在函数内部使用前就已经声明, 避免报错, 但实际开发中, 应该避免使用变量提升。

展开运算符

  • 定义: 展开运算符是指将数组或类数组对象转换为用逗号分隔的参数序列。

  • 作用: 展开运算符可以将数组或类数组对象转换为用逗号分隔的参数序列, 方便求最值和合并数组。

  • 语法: 展开运算符是三个点(...)

  • 注意: 展开运算符只能用于数组或类数组对象, 不能用于字符串, 对象, Map, Set 等。

javascript 复制代码
let arr = [1, 2, 3];
let arr2 = [4, 5, 6];

let newArr = [...arr, ...arr2]; // [1, 2, 3, 4, 5, 6]

let max = Math.max(...newArr); // 6

函数

函数提升

  • 定义: 函数提升是指 JavaScript 在执行代码前,会将在当前作用域下, 函数声明的函数, 提升到当前作用域的最前面。

函数参数

  • 动态参数

    • 定义: 动态参数指的是函数调用时, 传入的参数个数不确定, 可以是 0 个或多个。

    • 用法: 使用 arguments 对象(伪数组), 可以获取调用函数时传入的参数。

    • 作用: 可以实现函数的可变参数。

    javascript 复制代码
    function getSum() {
      let sum = 0;
      for (let i = 0; i < arguments.length; i++) {
        sum += arguments[i];
      }
      return sum;
    }
    
    let result = getSum(1, 2, 3); // 6
  • 剩余参数

    • 定义: 剩余参数指的是函数调用时, 传入的参数个数不确定, 但最后一个参数必须是数组。

    • 用法: 使用(a, b,...arr), 可以将传入的参数收集到真数组中。

    • 作用: 可以实现函数的可变参数。

    javascript 复制代码
    function getSum(a, b, ...arr) {
      let sum = a + b;
      for (let i = 0; i < arr.length; i++) {
        sum += arr[i];
      }
      return sum;
    }
    
    let result = getSum(1, 2, 3); // 6

箭头函数

  • 定义: 箭头函数是 ES6 新增的一种函数, 与普通函数的区别在于, 箭头函数没有自己的 this, arguments, super, new.target, 并且没有原型链。
javascript 复制代码
// 普通的箭头函数
let add = (a, b) => {
  return a + b;
};
let result = add(1, 2); // 3

// 只有一个参数的箭头函数可以省略括号, 只有一个语句的箭头函数可以省略大括号, 并且有返回值
let add1 = (a) => a + 1;
let result1 = add1(1); // 2

// 返回一个对象
let obj = (name, age) => ({ name: name, age: age });

let resultObj = obj("Tom", 20); // {name: 'Tom', age: 20}
箭头函数参数
  • 箭头函数没有 arguments 对象, 不能使用 arguments.length, 不能使用 arguments[i]获取参数, 但有剩余参数。

  • 箭头函数不会创建自己的 this, 但可以使用上级作用域的 this。

解构赋值

数组解构

  • 定义: 将数组中的单元值快速依次批量赋值给变量。

  • 语法: let [变量 1, 变量 2, 变量 3] = 数组;

  • 注意: 当解构赋值的变量个数与数组的单元值个数不一致时, 多余的变量会被赋值为 undefined, 少于的变量会被忽略。

javascript 复制代码
/*普通数组解构*/
const arr = [1, 2, 3];
const [a, b, c] = arr;

/*交换变量的值*/
let x = 1;
let y = 2;
[x, y] = [y, x];
console.log(x, y); // 2 1

/*利用剩余参数*/
let [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(a, b, rest); // 1 2 [3, 4, 5]

/*防止undefined传递*/
let [a = 0, b = 0, c = 0] = [1, 2];
console.log(a, b, c); // 1 2 0

/*按需导入赋值*/
let [x, , y] = [1, 2, 3];
console.log(x, y); // 1 3

/*多维数组解构*/
let [a, b, [c, d]] = [1, 2, [3, 4]];
console.log(a, b, c, d); // 1 2 3 4

对象解构

  • 定义: 将对象中的属性值快速依次批量赋值给变量。

  • 语法: let {变量 1: 变量 2, 变量 3: 变量 4} = 对象;

  • 注意: 当解构赋值的变量个数与对象属性个数不一致时, 多余的变量会被赋值为 undefined, 少于的变量会被忽略。且变量名应该与属性名一致。

javascript 复制代码
/*普通对象解构*/
const obj = { name: "Tom", age: 20 };
const { name, age } = obj;

/*重新改名*/
const obj2 = { name: "Tom", age: 20 };
const { name: n, age: a } = obj2;
//      旧名  新名

/*对象数组的解构*/
const arr = [
  { name: "Tom", age: 20 },
  { name: "Jerry", age: 25 },
];
const [{ name, age }, { name: n, age: a }] = arr;

/*多级对象解构*/
const pig = {
  name: "小猪",
  family: {
    father: "爸爸",
    mother: "妈妈",
    sister: {
      Siname: "姐姐",
      Sname: "妹妹",
    },
  },
};

const {
  name,
  family: {
    father,
    mother,
    sister: { Sname, Siname },
  },
} = pig;

数组进阶

forEach 遍历

javascript 复制代码
let arr = [1, 2, 3];

arr.forEach(function (value, index) {
  console.log(value);
  console.log(index);
});

filter 过滤

javascript 复制代码
const arr = [1, 2, 3, 4, 5];

const newArr = arr.filter(function (value, index) {
  return value > 2;
});

map 映射

javascript 复制代码
const arr = [1, 2, 3, 4, 5];

const newArr = arr.map(function (value, index) {
  return value * 2;
});

reduce 归并

javascript 复制代码
const arr = [1, 2, 3, 4, 5];

const result = arr.reduce(function (prev, curr, index) {
  return prev + curr;
}, 0);// 如果有初值, 则作为第一次执行的 prev, 每一次循环的返回值作为下一次的 prev

find 找出第一个匹配项

javascript 复制代码
const arr = [1, 2, 3, 4, 5];

const result = arr.find(function (value, index) {
  return value > 2;
});

findIndex 找出第一个匹配项的索引

javascript 复制代码
const arr = [1, 2, 3, 4, 5];

const result = arr.findIndex(function (value, index) {
  return value > 2;
});

includes 判断是否包含

javascript 复制代码
const arr = [1, 2, 3, 4, 5];

const result = arr.includes(3);
相关推荐
妙极矣15 分钟前
JAVAEE初阶01
java·学习·java-ee
DC...16 分钟前
vue滑块组件设计与实现
前端·javascript·vue.js
我的golang之路果然有问题24 分钟前
案例速成GO+redis 个人笔记
经验分享·redis·笔记·后端·学习·golang·go
碎叶城李白29 分钟前
NIO简单群聊
java·nio
xxjiaz1 小时前
水果成篮--LeetCode
java·算法·leetcode·职场和发展
韩明君1 小时前
前端学习笔记(四)自定义组件控制自己的css
前端·笔记·学习
CodeFox1 小时前
动态线程池 v1.2.1 版本发布,告警规则重构,bytebuddy 替换 cglib,新增 jmh 基准测试等!
java·后端
ℳ₯㎕ddzོꦿ࿐1 小时前
Java集成Zxing和OpenCV实现二维码生成与识别工具类
java·opencv
雪落山庄1 小时前
LeetCode100题
java·开发语言·数据结构
吃面必吃蒜2 小时前
从 Vue 到 React:React 合成事件
javascript·vue.js·react.js