自从ECMAScript 2015(简称ES6)发布以来,它为开发者带来了许多强大且实用的新特性,提升了代码的可读性和开发效率。
今天,我将带你深入了解ES6的20大核心特性
1. 变量声明:let、const与var的区别
在ES6之前,var是唯一的变量声明方式,但它存在作用域不明确的问题。ES6引入了let和const,使变量声明更加严谨。
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:新数据结构
Set和Map提供了更高效的存储和查找数据的方式。
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. 填充字符串的其他方法
除了padStart和padEnd,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的多种方式全攻略:从入门到精通,再到详解教程!!