【前端】ES6的20个新特性,助你轻松掌握现代JavaScript!

889 阅读8分钟

自从ECMAScript 2015(简称ES6)发布以来,它为开发者带来了许多强大且实用的新特性,提升了代码的可读性和开发效率。

今天,我将带你深入了解ES6的20大核心特性

在这里插入图片描述

1. 变量声明:let、const与var的区别

在ES6之前,var是唯一的变量声明方式,但它存在作用域不明确的问题。ES6引入了letconst,使变量声明更加严谨。

let声明

let声明的变量仅在其定义的块内有效,避免了全局污染。

{
    let x = 10;
    console.log(x); // 输出 10
}
console.log(x); // ReferenceError: x is not defined

const声明

const用于声明常量,必须在声明时赋值,且不可重新赋值。

const PI = 3.1415926;
// PI = 3.14; // 报错
const obj = { a: 1 };
obj.a = 20; // 合法,修改对象属性
// obj = { b: 1 }; // 报错,不能重新赋值

var声明

var声明的变量具有函数作用域,如果在函数外声明,则为全局变量。

function myFunction() {
    var x = 10;
    console.log(x); // 输出 10
}
myFunction();
console.log(x); // ReferenceError: x is not defined

2. 解构赋值:数组、对象与字符串

解构赋值是ES6的一大亮点,能够简化从数组或对象中提取数据的过程。

数组解构

let [a, b] = [1, 2];
console.log(a, b); // 1 2

let [c, , d] = [1, 2, 3];
console.log(c, d); // 1 3

对象解构

let obj = { name: '张三', age: 20 };
let { name, age } = obj;
console.log(name, age); // 张三 20

let { name: myName, age: myAge } = obj;
console.log(myName, myAge); // 张三 20

字符串解构

let str = 'hello';
let [h, e, l, l2, o] = str;
console.log(h, e, l, l2, o); // h e l l o

3. 对象扩展:简洁属性、动态属性与方法

ES6在对象方面也带来了诸多改进,使代码更简洁且功能更强大。

简洁属性

当属性名和变量名相同时,可以省略重复的部分。

const name = "小明";
let user = { name };
console.log(user); // { name: '小明' }

动态属性名

可以使用表达式计算属性名。

let prop = 'age';
let obj = {
    [prop]: 30,
    ['say' + 'Hi']() {
        console.log("Hi...");
    }
};
console.log(obj.age); // 30
obj.sayHi(); // Hi...

Object.assign()

用于对象合并,后面的属性会覆盖前面的同名属性。

let a = { name: '张三', width: 100 };
let b = { age: 20, width: 200 };
let ret = Object.assign({}, a, b);
console.log(ret); // { name: '张三', width: 200, age: 20 }

Object.is()

比较两个值是否严格相等,类似于===,但更严格。

console.log(Object.is(1, 1)); // true
console.log(Object.is("1", 1)); // false
console.log(Object.is({}, {})); // false

遍历对象

let obj = { name: '张三', age: 22 };
console.log(Object.values(obj)); // ['张三', 22]
console.log(Object.keys(obj)); // ['name', 'age']
console.log(Object.entries(obj)); // [['name', '张三'], ['age', 22]]

let map = new Map(Object.entries(obj));
console.log(map); // Map { 'name' => '张三', 'age' => 22 }

4. 数组扩展:扩展运算符与新方法

数组在ES6中得到了诸多增强,使操作更加便捷。

扩展运算符 (...)

用于解构和合并数组。

let arr1 = ["a", "b", "c"];
let arr2 = [...arr1];
arr1.push("d");
console.log(arr1, arr2); // ['a', 'b', 'c', 'd'] ['a', 'b', 'c']

let arr3 = ["x", "y", "z"];
let arr4 = [...arr1, ...arr3];
console.log(arr4); // ['a', 'b', 'c', 'd', 'x', 'y', 'z']

find()与findIndex()

find()返回第一个满足条件的元素,findIndex()返回其索引。

let arr = [1, 2, 3, 4, 5, 6];
let result = arr.find(item => item > 3);
console.log(result); // 4

let index = arr.findIndex(item => item > 3);
console.log(index); // 3

Array.of()与Array.from()

Array.of()用于创建数组,Array.from()将类数组对象转换为数组。

console.log(Array.of(1, 2, 3)); // [1, 2, 3]
let arrLike = { 0: "a", 1: "b", length: 2 };
console.log(Array.from(arrLike)); // ['a', 'b']

includes()与at()

includes()判断数组是否包含某元素,at()通过索引访问数组元素,支持负数索引。

let arr = [12, 3, 3, 2, 56, 5];
console.log(arr.includes(56)); // true
console.log(arr.at(-1)); // 5

5. 字符串扩展:新方法与优化

字符串在ES6中也得到了丰富的扩展,提升了操作的灵活性。

includes()、startsWith()与endsWith()

用于判断字符串是否包含、以某字符开头或结尾。

let str = "hello world";
console.log(str.includes("h")); // true
console.log(str.startsWith("he")); // true
console.log(str.endsWith("world")); // true

repeat()

重复字符串指定次数。

let str = "hello ";
console.log(str.repeat(3)); // 'hello hello hello '

padStart()与padEnd()

用于在字符串前后填充指定字符,达到目标长度。

let str = 'abc';
console.log(str.padStart(6, '0')); // '000abc'
console.log(str.padEnd(6, '0')); // 'abc000'

replace()与replaceAll()

用于替换字符串中的字符,replaceAll()可替换所有匹配项。

let s = "aflsdjflsefel";
console.log(s.replaceAll('s', 'a')); // 'afldjflaeafel'
console.log(s.replace('s', 'a')); // 'afldjflsefel'

trimStart()与trimEnd()

去除字符串开头或结尾的空格。

let s = '    hello world    ';
console.log(s.trimStart()); // 'hello world    '
console.log(s.trimEnd()); // '    hello world'

6. 二进制与八进制字面量

ES6引入了二进制和八进制的表示方法,提升了数值表示的灵活性。

let binary = 0b1010; // 二进制
console.log(binary); // 10

let octal = 0o12; // 八进制
console.log(octal); // 10

7. Symbol:唯一标识符

Symbol用于创建唯一且不可变的标识符,常用于对象属性的唯一键。

const sym1 = Symbol('desc');
const sym2 = Symbol('desc');
console.log(sym1 === sym2); // false

let obj = {
    [sym1]: 'value1',
    [sym2]: 'value2'
};
console.log(obj); // { [Symbol(desc)]: 'value1', [Symbol(desc)]: 'value2' }

8. 类与继承

ES6引入了class语法,使面向对象编程更加直观。

class Parent {
    constructor(name) {
        this.name = name;
    }

    greet() {
        console.log(`Hello, my name is ${this.name}.`);
    }
}

class Child extends Parent {
    constructor(name) {
        super(name);
    }
}

const child = new Child('Alice');
child.greet(); // Hello, my name is Alice.

9. Set与Map:新数据结构

SetMap提供了更高效的存储和查找数据的方式。

Set

Set用于存储唯一值。

const mySet = new Set();
mySet.add(1);
mySet.add(5);
mySet.add(5); // 不会添加重复项
console.log(mySet.has(5)); // true
console.log(mySet.size); // 2
mySet.delete(5);
console.log(mySet.size); // 1

Map

Map用于存储键值对,键可以是任意类型。

const myMap = new Map();
myMap.set('name', 'Alice');
myMap.set('age', 30);
console.log(myMap.get('name')); // Alice
console.log(myMap.has('age')); // true
console.log(myMap.size); // 2
myMap.delete('age');
console.log(myMap.size); // 1

10. Generator:控制函数执行

生成器函数允许暂停和恢复函数的执行,适用于异步编程。

function* tell() {
    console.log('1');
    yield 'a';
    console.log('2');
    yield 'b';
    console.log('3');
}

let it = tell();
it.next(); // 输出 1
it.next(); // 输出 2
it.next(); // 输出 3

11. Promise:优雅处理异步

Promise是处理异步操作的强大工具,避免了回调地狱。

基本用法

let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('Success!');
        // reject('Error!');
    }, 2000);
});

promise.then(res => {
    console.log('res', res);
}).catch(err => {
    console.log('err', err);
});

Promise方法

  • Promise.all():等待所有Promise完成。
  • Promise.race():第一个完成的Promise决定结果。
  • Promise.allSettled():所有Promise完成,不管成功或失败。
  • Promise.any():任意一个Promise成功即完成。
let p1 = Promise.resolve('p1');
let p2 = Promise.reject('p2');
let p3 = Promise.resolve('p3');

Promise.all([p1, p2, p3])
    .then(res => console.log('All:', res))
    .catch(err => console.log('Error:', err)); // Error: p2

Promise.race([p1, p3])
    .then(res => console.log('Race:', res)) // Race: p1
    .catch(err => console.log('Error:', err));

12. 模块化:export与import

ES6模块化使代码组织更清晰,支持按需加载。

导出模块

// math.js
export const pi = 3.14159;
export function add(a, b) {
    return a + b;
}
export default function log(message) {
    console.log(message);
}

导入模块

// main.js
import log, { pi, add } from './math.js';
console.log(pi); // 3.14159
console.log(add(2, 3)); // 5
log('Hello, ES6 Modules!');

13. 填充字符串的其他方法

除了padStartpadEnd,ES6还优化了字符串的填充方法,提升了代码的灵活性。

console.log('111'.padStart(6, '0')); // '000111'
console.log('12-12-12'.padStart(10, '0000-00-00')); // '00-12-12-12'

14. 对象新增方法

ES6为对象操作引入了多种新方法,简化了开发流程。

let obj = { name: '张三', age: 22 };
console.log(Object.values(obj)); // ['张三', 22]
console.log(Object.entries(obj)); // [['name', '张三'], ['age', 22]]
console.log(Object.keys(obj)); // ['name', 'age']

let map = new Map(Object.entries(obj));
console.log(map); // Map { 'name' => '张三', 'age' => 22 }

15. 字符串收尾去空格

ES6优化了字符串的收尾去空格方法,使其更具语义化。

let s = '    1324325 4324  4532       ';
console.log(s.trim()); // '1324325 4324  4532'
console.log(s.trimStart()); // '1324325 4324  4532       '
console.log(s.trimEnd()); // '    1324325 4324  4532'

16. 通过下标查找数组元素

at()方法允许通过正数或负数索引访问数组元素。

let arr = [12, 3, 3, 2, 56, 5];
console.log(arr.at(1)); // 3
console.log(arr.at(-1)); // 5

17. Generator的高级用法

生成器不仅能暂停函数执行,还能与异步操作结合使用,提升代码的可读性。

function* generatorExample() {
    const data1 = yield fetchData1();
    const data2 = yield fetchData2(data1);
    return data2;
}

const it = generatorExample();
it.next().value.then(data1 => it.next(data1).value)
    .then(data2 => it.next(data2).value)
    .then(result => console.log(result));

18. Async/Await:基于Promise的语法糖

async/await简化了异步代码的书写,使其更接近同步代码的风格。

async function fetchData() {
    try {
        let res1 = await fetchData1();
        let res2 = await fetchData2(res1);
        console.log(res2);
    } catch (err) {
        console.error(err);
    }
}

fetchData();

19. 模块的动态导入

ES6支持动态导入模块,根据需要加载,优化性能。

import('./math.js')
    .then(module => {
        console.log(module.pi);
        console.log(module.add(2, 3));
    })
    .catch(err => {
        console.error('模块加载失败', err);
    });

20. 其他ES6新特性

除了上述20大特性,ES6还引入了许多其他实用的功能,如默认参数、剩余参数、箭头函数、模板字面量等。这些特性共同构建了现代JavaScript的基础,使开发者能够编写更简洁、高效的代码。


总结

希望这篇文章能帮助你更好地理解和应用ES6新特性。如果你有任何疑问或心得,欢迎在下方留言讨论!👍

相关文章

【OpenAI】(一)获取OpenAI API Key的多种方式全攻略:从入门到精通,再到详解教程!!

【VScode】(二)VSCode中的智能AI-GPT编程利器,全面揭秘CodeMoss & ChatGPT中文版

【CodeMoss】(三)集成13种AI大模型(GPT4、o1等)、支持Open API调用、自定义助手、文件上传等强大功能,助您提升工作效率! >>> - CodeMoss & ChatGPT-AI中文版