[JavaScript] ES6及以后版本的新特性

devtools/2025/2/2 8:08:51/

文章目录

  • 箭头函数(Arrow Functions)
    • 为什么需要箭头函数?
    • 箭头函数的完整语法
    • 箭头函数中的 `this`
    • 实用场景
  • 解构赋值(Destructuring Assignment)
    • 为什么需要解构赋值?
    • 数组解构赋值的完整用法
    • 对象解构赋值的完整用法
    • 实用场景
  • 模块化(Modules)
    • 为什么需要模块化?
    • 模块的基本概念
  • 模板字面量(Template Literals)
    • 为什么需要模板字面量?
    • 模板字面量的基本语法
    • 高级用法
    • 使用场景
  • Promise与异步编程
    • 为什么需要 Promise 和异步编程?
    • Promise 的语法与用法
    • async 和 await
    • 实用场景

箭头函数(Arrow Functions)

为什么需要箭头函数?

  1. 代码简洁

对比代码:

javascript">// ES5 写法
const numbers = [1, 2, 3];
const squared = numbers.map(function (n) {return n * n;
});// ES6 箭头函数写法
const squared = numbers.map(n => n * n);
- ES5 中的函数定义通常会比较冗长,特别是在回调函数或嵌套逻辑中,代码可读性较差。
- 箭头函数通过简化语法,减少 `function` 和 `return` 等关键字的使用,使代码更加直观。
  1. 避免 this 问题
    • 在 ES5 中,函数的 this 是由调用时动态决定的,可能会指向全局对象或 undefined,造成意外错误。
    • 箭头函数继承了定义时的 this(即词法作用域),从而避免了 this 绑定问题。

箭头函数的完整语法

  1. 基本形式
javascript">const func = (param1, param2) => {// 函数体return param1 + param2;
};
  1. 省略规则
    • 如果函数体只有一行表达式,并且需要返回值,可以省略大括号 {}return
javascript">const add = (a, b) => a + b;
- 如果没有参数,必须加括号:
javascript">const greet = () => console.log("Hello!");
  1. 返回对象字面量
    如果需要返回一个对象字面量,必须用括号包裹,否则会与箭头函数的语法冲突:
javascript">const createPerson = (name, age) => ({ name, age });
console.log(createPerson("Kevin", 25)); // 输出 { name: "Kevin", age: 25 }

箭头函数中的 this

  1. this** 的词法作用域**:

示例:

javascript">// 普通函数中 this 的问题
function Timer() {this.seconds = 0;setInterval(function () {this.seconds++; // this 指向全局或 undefinedconsole.log(this.seconds);}, 1000);
}// 用箭头函数解决
function Timer() {this.seconds = 0;setInterval(() => {this.seconds++; // this 绑定到 Timer 对象console.log(this.seconds);}, 1000);
}
- 箭头函数不会创建自己的 `this`,它会从外层作用域中继承 `this`。
- 这在回调函数中尤为重要,避免了手动绑定 `this` 的麻烦。
  1. 无法用作构造函数
    箭头函数没有 [[Construct]] 方法,因此不能使用 new 来调用。
javascript">const Person = (name) => {this.name = name;
};// new Person("Kevin"); // 报错

实用场景

  1. 回调函数
javascript">const numbers = [1, 2, 3, 4];
const doubled = numbers.map(n => n * 2); // 简化 map 回调
  1. 事件监听
javascript">const button = document.querySelector("button");
button.addEventListener("click", () => {console.log("Button clicked!");
});

解构赋值(Destructuring Assignment)

为什么需要解构赋值?

  1. 简化代码
    在传统写法中,获取数组或对象的特定值需要多次声明变量。解构赋值直接在一行代码中完成这一任务,使代码更紧凑。对比代码:
javascript">// ES5 写法
const person = { name: "Kevin", age: 25 };
const name = person.name;
const age = person.age;// ES6 解构赋值
const { name, age } = person;
  1. 避免多次访问对象属性
    解构赋值减少了对同一对象或数组的多次访问,提升性能。

数组解构赋值的完整用法

  1. 按顺序提取值
javascript">const arr = [10, 20, 30];
const [first, second] = arr;
console.log(first, second); // 输出 10 20
  1. 跳过某些值
javascript">const arr = [1, 2, 3];
const [, second] = arr;
console.log(second); // 输出 2
  1. 使用默认值
javascript">const arr = [10];
const [first, second = 20] = arr;
console.log(second); // 输出 20

对象解构赋值的完整用法

  1. 基础用法
javascript">const obj = { x: 10, y: 20 };
const { x, y } = obj;
console.log(x, y); // 输出 10 20
  1. 别名(重命名)
javascript">const obj = { x: 10, y: 20 };
const { x: newX, y: newY } = obj;
console.log(newX, newY); // 输出 10 20
  1. 嵌套解构
javascript">const obj = { person: { name: "Kevin", age: 25 } };
const { person: { name, age } } = obj;
console.log(name, age); // 输出 Kevin 25

实用场景

  1. 函数参数
javascript">function greet({ name, age }) {console.log(`Hello, ${name}. You are ${age} years old.`);
}
greet({ name: "Kevin", age: 25 });
  1. 交换变量值
javascript">let a = 1, b = 2;
[a, b] = [b, a];
console.log(a, b); // 输出 2 1

模块化(Modules)

为什么需要模块化?

在 ES5 之前,JavaScript 没有原生模块化系统,开发者通常使用全局变量或外部库(如 require.js)来实现模块化。但这会导致代码难以维护、命名冲突等问题。


模块的基本概念

  1. 导出模块
    • 命名导出:可以导出多个变量或函数。
javascript">export const name = "Kevin";
export function greet() {console.log("Hello!");
}
- **默认导出**:每个模块只能有一个默认导出。
javascript">export default function greet() {console.log("Hello!");
}
  1. 引入模块
    • 引入命名导出
javascript">import { name, greet } from "./module.js";
- **引入默认导出**:
javascript">import greet from "./module.js";

好的,以下将针对剩余的 模板字面量(Template Literals)Promise与异步编程 进行更加详细的讲解,包括其语法背景、具体用法、以及背后的原理和实用场景。


模板字面量(Template Literals)

为什么需要模板字面量?

在 ES5 中,字符串的操作非常繁琐,尤其是在拼接变量时,需要使用 + 串联,且难以处理多行字符串。此外,插入表达式和动态生成内容也较为麻烦。
模板字面量 的出现解决了这些问题,提供了一种更加优雅的方式来处理字符串。


模板字面量的基本语法

  1. 模板字面量的定义:用反引号 ``(反引号 ` 而不是单引号 ')定义的字符串。**
javascript">const message = `这是一个模板字面量`;
  1. 插入变量(占位符)
    使用 ${} 将变量或表达式嵌入到字符串中:
javascript">const name = "Kevin";
const age = 25;
const message = `Hello, my name is ${name} and I am ${age} years old.`;
console.log(message); // 输出:Hello, my name is Kevin and I am 25 years old.
  1. 多行字符串
    在 ES5 中,我们需要通过 \n 或字符串拼接实现多行字符串,这不仅麻烦而且不直观。
    • ES5 写法
javascript">const text = "这是第一行\n" +"这是第二行";
console.log(text);
- **模板字面量写法**:
javascript">const text = `这是第一行
这是第二行`;
console.log(text); // 输出多行字符串
  1. 嵌入表达式
    可以直接在 ${} 中编写表达式,而不仅仅是变量:
javascript">const a = 10, b = 20;
const result = `结果是:${a + b}`;
console.log(result); // 输出:结果是:30

高级用法

  1. 函数调用
    模板字面量支持在 ${} 中直接调用函数:
javascript">function greet(name) {return `Hello, ${name}!`;
}
const message = `${greet("Kevin")}`;
console.log(message); // 输出:Hello, Kevin!
  1. 标签模板(Tagged Template Literals)
    标签模板允许我们通过函数对模板字面量进行自定义解析。
javascript">function highlight(strings, ...values) {return strings.reduce((result, str, i) => {return `${result}${str}<strong>${values[i] || ""}</strong>`;}, "");
}const name = "Kevin";
const age = 25;
const message = highlight`Name: ${name}, Age: ${age}`;
console.log(message); 
// 输出:Name: <strong>Kevin</strong>, Age: <strong>25</strong>
  1. 嵌套模板字面量
    支持嵌套使用模板字面量:
javascript">const user = { name: "Kevin", age: 25 };
const info = `User Info: ${`Name: ${user.name}, Age: ${user.age}`}`;
console.log(info); 
// 输出:User Info: Name: Kevin, Age: 25

使用场景

  1. 动态生成 HTML
    模板字面量非常适合用于构建动态 HTML 字符串:
javascript">const name = "Kevin";
const html = `<div><h1>${name}</h1><p>欢迎访问我的网站!</p></div>`;
console.log(html);
  1. 构建 SQL 查询
javascript">const table = "users";
const column = "name";
const sql = `SELECT ${column} FROM ${table} WHERE active = 1`;
console.log(sql);
// 输出:SELECT name FROM users WHERE active = 1

Promise与异步编程

为什么需要 Promise 和异步编程?

在 JavaScript 中,异步操作(如网络请求、文件读取、定时器等)是常见场景。
传统的异步处理方式(如回调函数)可能会导致 回调地狱(Callback Hell),使代码难以阅读和维护。

Promiseasync/await 的引入解决了这些问题,使异步代码更加可读和可维护。


Promise 的语法与用法

  1. 创建 Promise
    Promise 是一个对象,表示一个异步操作的最终完成(或失败)及其结果。
    它有三种状态:

示例:

javascript">const promise = new Promise((resolve, reject) => {const success = true;if (success) {resolve("操作成功");} else {reject("操作失败");}
});promise.then(result => console.log(result)) // 操作成功.catch(error => console.log(error)); // 捕获错误
- `pending`:初始状态,操作尚未完成。
- `fulfilled`:操作成功完成。
- `rejected`:操作失败。
  1. 链式调用
    Promise 支持链式调用,使代码逻辑更清晰。
javascript">const fetchData = () => {return new Promise(resolve => {setTimeout(() => resolve("数据加载完成"), 1000);});
};fetchData().then(data => {console.log(data);return "处理后的数据";}).then(processed => console.log(processed));
  1. Promise.all
    并行执行多个 Promise,并等待所有完成:
javascript">const p1 = new Promise(resolve => setTimeout(() => resolve(1), 1000));
const p2 = new Promise(resolve => setTimeout(() => resolve(2), 2000));Promise.all([p1, p2]).then(results => console.log(results)); 
// 输出:[1, 2]

async 和 await

  1. 为什么需要 async/await?
    • async/await 是 Promise 的语法糖,使异步代码看起来像同步代码,极大地提高了代码的可读性。
  2. 基本用法

示例:

javascript">const fetchData = () => {return new Promise(resolve => setTimeout(() => resolve("数据加载完成"), 1000));
};async function loadData() {const data = await fetchData();console.log(data); // 输出:数据加载完成
}loadData();
- 使用 `async` 声明一个函数,该函数返回一个 Promise。
- 使用 `await` 暂停异步操作,直到 Promise 完成。
  1. 错误处理
    可以使用 try...catch 捕获错误:
javascript">async function fetchWithErrorHandling() {try {const response = await fetch("https://api.example.com/data");const data = await response.json();console.log(data);} catch (error) {console.error("请求出错:", error);}
}

实用场景

  1. 数据请求
javascript">async function fetchData() {const response = await fetch("https://jsonplaceholder.typicode.com/posts/1");const post = await response.json();console.log(post);
}fetchData();
  1. 动画和定时器
javascript">const delay = ms => new Promise(resolve => setTimeout(resolve, ms));async function run() {console.log("开始");await delay(1000); // 等待 1 秒console.log("结束");
}run();

http://www.ppmy.cn/devtools/155390.html

相关文章

帝国CMS8.0终极栏目转换或批量改顺序成功后不能返回地址的解决方案

帝国CMS8.0终极栏目转换或批量改顺序成功后不能返回地址问题的解决办法&#xff1a; 修改 /e/class/classfun.php 文件&#xff0c; 查找2处 “$cache_ecmstourlurlencode(EcmsGetReturnUrl());” 修改为 “$cache_ecmstourlurlencode($_POST[&topic_c449dd39-aa1d-41…

数据分析系列--②RapidMiner导入数据和存储过程

一、下载数据 二、导入数据 1. 在本地计算机中创建3个文件夹 2. 从本地选择.csv或.xlsx 三、界面说明 四、存储过程 1.保存 Congratulations, you are done. 一、下载数据 点击下载AssociationAnalysisData.xlsx数据集 二、导入数据 1. 在本地计算机中创建3个文件夹 2. 从…

跨境支付领域中常用的英文单词(持续更新)

### **1. 支付方式 (Payment Methods)** 1. Credit Card 2. Debit Card 3. Bank Transfer 4. Wire Transfer 5. PayPal 6. Alipay 7. WeChat Pay 8. Apple Pay 9. Google Pay 10. Cryptocurrency 11. Digital Wallet 12. Mobile Payment 13. Cash on D…

BGP协议

BGP作为一种外部网关动态路由协议&#xff0c;其基于TCP的179号端口&#xff0c;其联系不同自治系统间的通讯 关于BGP的版本&#xff0c;最早只有1&#xff0c;2&#xff0c;3这三个版本&#xff0c;后经过改进有了BGP4&#xff0c;目前普遍使用BGP4版本&#xff0c;其可兼容I…

用一个例子详细说明python单例模式

单例模式是一种设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问该实例。这在需要控制资源&#xff08;如数据库连接、文件系统等&#xff09;的访问时非常有用。 下面是一个使用Python实现单例模式的例子&#xff1a; class Singleton:…

4. 劲舞团python解法——2024年省赛蓝桥杯真题

问题描述&#xff1a;4.劲舞团 - 蓝桥云课 小蓝最近迷上了一款名为 “劲舞团” 的游戏&#xff0c;具体来说&#xff0c;只要按照游戏中给出的键位提示依次按出对应的键位&#xff0c;游戏人物便可以跟随节奏跳舞。对于连续的 K 次正确敲击&#xff0c;如果任意连续的两次敲击…

(笔记+作业)书生大模型实战营春节卷王班---L0G2000 Python 基础知识

学员闯关手册&#xff1a;https://aicarrier.feishu.cn/wiki/QtJnweAW1iFl8LkoMKGcsUS9nld 课程视频&#xff1a;https://www.bilibili.com/video/BV13U1VYmEUr/ 课程文档&#xff1a;https://github.com/InternLM/Tutorial/tree/camp4/docs/L0/Python 关卡作业&#xff1a;htt…

5.3.2 软件设计原则

文章目录 抽象模块化信息隐蔽与独立性衡量 软件设计原则&#xff1a;抽象、模块化、信息隐蔽。 抽象 抽象是抽出事物本质的共同特性。过程抽象是指将一个明确定义功能的操作当作单个实体看待。数据抽象是对数据的类型、操作、取值范围进行定义&#xff0c;然后通过这些操作对数…