Es6新特性

1. letconst

概念
  • let:用于声明 块级作用域 的变量。
  • const:用于声明 块级作用域 的常量,声明后不可重新赋值(但可以修改对象的属性或数组的内容)。
原理

JavaScript 在 ES5 中只有全局作用域和函数作用域,没有块级作用域。letconst 引入了块级作用域,使得变量的生命周期仅限于块内(例如 {} 中),避免了变量污染和提升问题。

用法

javascript 复制代码
// let 示例
if (true) {
    let x = 10;
    console.log(x); // 10
}
// console.log(x); // 报错,x 未定义

// const 示例
const PI = 3.14;
// PI = 3.14159; // 报错,常量不可重新赋值
const obj = { name: 'John' };
obj.name = 'Alice'; // 可以修改对象的属性

var 的区别

  • var 有函数作用域和提升(hoisting),而 letconst 有块级作用域,无提升。
  • var 允许重复声明,而 letconst 不允许。
javascript 复制代码
var x = 10;
var x = 20; // 合法
let y = 10;
// let y = 20; // 报错,重复声明

2. 箭头函数

概念

箭头函数是一种简化函数定义的语法,使用 =>。它没有自己的 thisargumentssupernew.targetthis 继承自外层作用域。

原理

普通函数的 this 是动态绑定的,取决于调用方式。而箭头函数的 this 是静态绑定的,继承自定义时的外层作用域。

用法
javascript 复制代码
// 普通函数
function add(a, b) {
    return a + b;
}

// 箭头函数
const add = (a, b) => a + b;
console.log(add(2, 3)); // 5

// this 绑定示例
const person = {
    name: 'John',
    greet: function() {
        setTimeout(() => {
            console.log(`Hello, ${this.name}`); // this 继承自 greet
        }, 1000);
    }
};
person.greet(); // Hello, John
与普通函数的区别
  • 箭头函数不能作为构造函数(不能使用 new)。
  • 箭头函数没有 arguments 对象。
  • 箭头函数不能使用 yield,不能作为生成器函数。

3. 模板字符串

概念

模板字符串使用反引号(`````),可以嵌入变量和多行文本,支持表达式。

原理

模板字符串在编译时会被解析为普通字符串,嵌入的变量和表达式会被替换为实际值。

用法
javascript 复制代码
const name = 'Alice';
const age = 25;
const message = `Hello, my name is ${name} and I am ${age} years old.`;
console.log(message); // Hello, my name is Alice and I am 25 years old.

// 多行文本
const multiLine = `
    This is line 1.
    This is line 2.
`;
console.log(multiLine);
与传统字符串的区别
  • 传统字符串需要使用 + 拼接变量,模板字符串更简洁。
  • 模板字符串支持多行文本,传统字符串需要手动换行符 \n

4. 解构赋值

概念

解构赋值允许从数组或对象中提取值,并赋值给变量。

原理

解构赋值是一种语法糖,底层仍然是通过逐个赋值实现。

用法
javascript 复制代码
// 数组解构
const [a, b] = [1, 2];
console.log(a, b); // 1 2

// 对象解构
const { name, age } = { name: 'John', age: 25 };
console.log(name, age); // John 25

// 默认值
const [x = 10, y = 20] = [1];
console.log(x, y); // 1 20
与传统赋值的区别
  • 传统赋值需要逐个提取值,解构赋值更简洁。
  • 解构赋值支持默认值,避免变量为 undefined

5. 默认参数

概念

默认参数允许在函数定义时为参数设置默认值,如果调用时未提供该参数,则使用默认值。

原理

在函数调用时,如果参数值为 undefined,则使用默认值。

用法
javascript 复制代码
function greet(name = 'Guest') {
    console.log(`Hello, ${name}`);
}
greet(); // Hello, Guest
greet('Alice'); // Hello, Alice
与传统方法的区别
  • 传统方法需要在函数体内判断参数是否为 undefined,默认参数更简洁。

6. 扩展运算符和剩余参数

概念
  • 扩展运算符(...:用于展开数组或对象。
  • 剩余参数(...:用于将剩余的参数收集为一个数组。
原理

扩展运算符将数组或对象的内容"展开"为独立的值。剩余参数将剩余的值"收集"为一个数组。

用法
javascript 复制代码
// 扩展运算符
const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4]

// 剩余参数
function sum(...numbers) {
    return numbers.reduce((acc, num) => acc + num, 0);
}
console.log(sum(1, 2, 3)); // 6
arguments 的区别
  • arguments 是一个类数组对象,剩余参数是一个真正的数组

7. 类和继承

概念

ES6 引入了 class 关键字,用于定义类和继承。

原理

class 是语法糖,底层仍然是基于原型链的继承。

用法
javascript 复制代码
class Animal {
    constructor(name) {
        this.name = name;
    }
    speak() {
        console.log(`${this.name} makes a noise.`);
    }
}

class Dog extends Animal {
    speak() {
        console.log(`${this.name} barks.`);
    }
}

const dog = new Dog('Rex');
dog.speak(); // Rex barks.

与传统原型链的区别

  • class 语法更直观,易于理解。
  • extends 关键字简化了继承的实现。

8. **模块化(importexport

概念

ES6 引入了模块化语法,允许将代码分割成多个文件,通过 importexport 进行导入和导出。

原理

模块化将代码组织为独立的单元,每个模块有自己的作用域。

用法
javascript 复制代码
// 导出模块
export const name = 'John';
export function greet() {
    console.log('Hello!');
}

// 导入模块
import { name, greet } from './module.js';
console.log(name); // John
greet(); // Hello!
与 CommonJS 的区别
  • CommonJS 使用 requiremodule.exports,ES6 模块化语法更现代化。
  1. Symbol
概念

Symbol 是一种新的原始数据类型,表示 唯一 的值。通常用于创建对象的唯一属性名,避免属性名冲突。

原理

每次调用 Symbol() 都会生成一个唯一的值,即使传入相同的参数。

用法
javascript 复制代码
const sym1 = Symbol('key');
const sym2 = Symbol('key');
console.log(sym1 === sym2); // false,Symbol 是唯一的

const obj = {
    [sym1]: 'value' // 使用 Symbol 作为属性名
};
console.log(obj[sym1]); // value
与字符串属性的区别
  • 字符串属性名可以被覆盖,而 Symbol 属性名是唯一的,不会冲突。

10. 迭代器(Iterators)和生成器(Generators)

概念
  • 迭代器 :一种对象,具有 next() 方法,用于按顺序访问集合的元素。
  • 生成器 :一种特殊的函数,使用 function* 声明,可以生成多个值。
原理

迭代器和生成器基于 协程 的机制,允许函数暂停和恢复执行。

用法
javascript 复制代码
// 迭代器
const iterator = {
    data: [1, 2, 3],
    next() {
        return {
            value: this.data.shift() || undefined,
            done: this.data.length === 0
        };
    }
};
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }

// 生成器
function* generateNumbers() {
    yield 1;
    yield 2;
    yield 3;
}
const gen = generateNumbers();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
与普通函数的区别
  • 普通函数只能返回一个值,而生成器可以返回多个值。
  • 生成器的执行可以被暂停和恢复。

11. Promise

概念

Promise 是一种异步编程的解决方案,用于处理异步操作的结果。

原理

Promise 是一个对象,表示一个异步操作的最终状态(完成或失败)。它有三种状态:pendingfulfilledrejected

用法
javascript 复制代码
const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('Success!'); // 异步操作成功
    }, 1000);
});

promise
    .then(result => console.log(result)) // Success!
    .catch(error => console.log(error)); // 处理错误
与回调函数的区别
  • 回调函数容易导致"回调地狱",而 Promise 使用链式调用,代码更清晰。

12. Map 和 Set

概念
  • Map:一种键值对的集合,键可以是任意类型的值。
  • Set:一种唯一值的集合,不允许重复值。
原理

MapSet 是基于哈希表实现的,适合存储和查找大量数据。

用法
javascript 复制代码
// Map
const map = new Map();
map.set('name', 'John');
map.set(1, 'One');
console.log(map.get('name')); // John

// Set
const set = new Set([1, 2, 3, 3]);
console.log(set); // Set { 1, 2, 3 }
与普通对象的区别
  • Map 的键可以是任意类型的值,而普通对象的键只能是字符串或 Symbol
  • Set 会自动去重,而普通数组不会。

13. Proxy

概念

Proxy 是一种对象,用于定义基本操作的自定义行为(如属性查找、赋值、函数调用等)。

原理

Proxy 可以"拦截"对目标对象的操作,并在操作执行前后添加自定义逻辑。

用法
javascript 复制代码
const target = {
    name: 'John'
};
const handler = {
    get(obj, prop) {
        return prop in obj ? obj[prop] : 'Unknown';
    }
};
const proxy = new Proxy(target, handler);
console.log(proxy.name); // John
console.log(proxy.age); // Unknown
与直接访问对象的区别
  • 直接访问对象无法拦截操作,而 Proxy 可以实现自定义行为。

14. Reflect

概念

Reflect 是一个内置对象,提供与 Proxy 相同的操作,用于简化代码和统一行为。

原理

Reflect 方法通常与 Proxy 配对使用,例如 Reflect.get()Reflect.set() 等。

用法
javascript 复制代码
const obj = { name: 'John' };
console.log(Reflect.get(obj, 'name')); // John
Reflect.set(obj, 'age', 25);
console.log(obj.age); // 25
与直接调用的区别
  • Reflect 提供了一种更标准化的方式来操作对象。

15. 字符串新增方法

  • includes():检查字符串是否包含指定子串。
  • startsWith():检查字符串是否以指定子串开头。
  • endsWith():检查字符串是否以指定子串结尾。
用法
javascript 复制代码
const str = 'Hello, world!';
console.log(str.includes('world')); // true
console.log(str.startsWith('Hello')); // true
console.log(str.endsWith('!')); // true
indexOf 的区别
  • includes()startsWith()endsWith() 更语义化,直接返回布尔值。

16. 数组新增方法

  • Array.from():将类数组对象或可迭代对象转换为数组。
  • Array.of():创建包含任意数量元素的数组。
  • find():查找符合条件的第一个元素。
  • findIndex():查找符合条件的第一个元素的索引。
  • fill():填充数组的指定范围。
用法
javascript 复制代码
const arr = Array.from('abc');
console.log(arr); // ['a', 'b', 'c']

const numbers = Array.of(1, 2, 3);
console.log(numbers); // [1, 2, 3]

const firstEven = [1, 3, 5, 6, 7].find(num => num % 2 === 0);
console.log(firstEven); // 6

Array.prototype.fill() 是 ES6 引入的一个数组方法,用于用一个固定值填充数组的指定范围。它非常方便,特别是在需要初始化或重置数组时使用。

javascript 复制代码
array.fill(value, start, end)
  • value:用来填充数组的值。
  • start (可选):开始填充的索引(包含该索引),默认为 0
  • end(可选):结束填充的索引(不包含该索引),默认为数组的长度。

使用示例

javascript 复制代码
// 1. 填充整个数组
const arr = [1, 2, 3, 4, 5];
arr.fill(0); // 用 0 填充整个数组
console.log(arr); // [0, 0, 0, 0, 0]

// 2. 填充指定范围
const arr = [1, 2, 3, 4, 5];
arr.fill(0, 1, 3); // 从索引 1 到 3(不包含 3)用 0 填充
console.log(arr); // [1, 0, 0, 4, 5]

// 3. 从某个索引开始填充
const arr = [1, 2, 3, 4, 5];
arr.fill(0, 2); // 从索引 2 开始用 0 填充
console.log(arr); // [1, 2, 0, 0, 0]

// 4. 填充稀疏数组 如果数组是稀疏的(有空位),fill() 会跳过这些空位,只填充有值的位置:
const arr = [1, , , 4]; // 数组有空的索引
arr.fill(0, 1, 3); // 从索引 1 到 3 用 0 填充
console.log(arr); // [1, 0, 0, 4]

//注意事项
//修改原数组:fill() 会直接修改原数组,而不是返回一个新数组。
//负数索引:可以使用负数索引,表示从数组末尾开始计算:
<JAVASCRIPT>
const arr = [1, 2, 3, 4, 5];
arr.fill(0, -3, -1); // 从倒数第 3 个到倒数第 1 个用 0 填充
console.log(arr); // [1, 2, 0, 0, 5]

//超出范围的索引:
//如果 start 或 end 超出数组的索引范围,fill() 会自动调整到数组的边界:
const arr = [1, 2, 3, 4, 5];
arr.fill(0, 10); // start 超出范围,相当于不填充
console.log(arr); // [1, 2, 3, 4, 5]

实际应用场景

javascript 复制代码
// 初始化数组:
const arr = new Array(5).fill(0); // 创建一个长度为 5 的数组,所有元素为 0
console.log(arr); // [0, 0, 0, 0, 0]
 
//重置数组的一部分:
const scores = [95, 80, 70, 60, 85];
scores.fill(0, 2, 4); // 将索引 2 和 3 的值重置为 0
console.log(scores); // [95, 80, 0, 0, 85]

// 生成固定值的数组:
const defaultValues = new Array(10).fill('default'); // 生成 10 个 'default'
console.log(defaultValues); // ['default', 'default', ..., 'default']

//与 map() 的区别
//fill() 是直接填充值,而 map() 是通过回调函数生成新值。
//示例:
const arr1 = new Array(5).fill(0); // [0, 0, 0, 0, 0]
const arr2 = new Array(5).fill().map((_, i) => i); // [0, 1, 2, 3, 4]
相关推荐
deckcode4 分钟前
css基础-display 常用布局
前端·css·css3
拉不动的猪12 分钟前
数组和对象的另类用法
前端·javascript·node.js
web_1553427465630 分钟前
SpringMVC 请求参数接收
前端·javascript·算法
LoveYa!41 分钟前
HTML5 初探:新特性与本地存储的魔法
前端·笔记·学习·html·html5
你脸上有BUG1 小时前
前端样式库推广——TailwindCss
前端·css·样式·tailwindcss
_未知_开摆1 小时前
Error: The project seems to require pnpm but it‘s not installed.
前端·webpack·vue
肉肉不吃 肉2 小时前
父子组件传递数据和状态管理数据
前端·javascript·vue.js·pinia
不会叫的狼2 小时前
回调方法传参汇总
前端
霸王蟹2 小时前
Vue3自定义指令实现前端权限控制 - 按钮权限
前端·javascript·vue.js·笔记·学习·html
前端极客探险家2 小时前
《Next.js 14 App Router 实战:用「Server Actions」重构全栈表单的最佳实践》
开发语言·javascript·重构