前端八股文es6篇 - 详解
好的,这里是专门针对 ES6+ 的前端面试“八股文”,它已经成为现代前端开发的绝对主流和面试必考内容。
一、核心语法与声明
1. let 与 const
(这部分在JS篇已详述,但它是ES6的基石,必须掌握)
let:块级作用域变量,不可重复声明,存在暂时性死区。const:用于声明常量,必须在声明时初始化。对于基本类型,值不可改变;对于引用类型,其指向的内存地址不可改变(但属性或元素可修改)。
2. 模板字符串
- 用法:使用反引号(
`)标识。 - 特性:
- 字符串插值:使用
${expression}嵌入变量或表达式。
const name = 'Alice'; console.log(`Hello, ${name}!`); // Hello, Alice! console.log(`1 + 2 = ${1 + 2}`); // 1 + 2 = 3- 多行字符串:直接换行即可,无需使用
\n或字符串连接符。
const multiLine = ` This is a multi-line string. `; - 字符串插值:使用
3. 箭头函数
- 语法:
(parameters) => { statements }或parameter => expression(单一参数可省略括号,单一表达式可省略大括号并隐式返回)。 - 特性与限制:
- 没有自己的
this:它继承自定义它时所处的外层作用域的this。这使得它特别适合用在回调函数(如setTimeout,map,filter)中,避免this指向错误。 - 没有
arguments对象:需要使用剩余参数(...args)来获取参数列表。 - 不能作为构造函数:使用
new调用会抛出错误。 - 没有
prototype属性。 - 不能用作 Generator 函数。
- 没有自己的
经典 this 对比示例:
const obj = {
value: 'abc',
traditional: function() {
setTimeout(function() {
console.log(this.value); // undefined (this 指向 window 或 undefined)
}, 100);
},
arrow: function() {
setTimeout(() => {
console.log(this.value); // 'abc' (this 继承自 arrow 函数,即 obj)
}, 100);
}
};
obj.traditional();
obj.arrow();
二、解构赋值
从数组或对象中提取值,对变量进行赋值。
1. 数组解构
- 基本用法:按顺序对应。
const [a, b] = [1, 2]; // a=1, b=2 - 跳过元素:使用空位。
const [a, , c] = [1, 2, 3]; // a=1, c=3 - 默认值:当解构出的值为
undefined时使用默认值。const [a = 5, b = 10] = [1]; // a=1, b=10 - 剩余模式:使用
...将剩余元素放入一个数组。const [a, ...rest] = [1, 2, 3, 4]; // a=1, rest=[2,3,4]
2. 对象解构
- 基本用法:按属性名对应。
const { name, age } = { name: 'Bob', age: 20 }; // name='Bob', age=20 - 重命名:
{ originalKey: newKey }。const { name: userName } = { name: 'Bob' }; // userName='Bob' - 默认值:
const { name = 'Anonymous', age = 0 } = { name: 'Bob' }; // name='Bob', age=0 - 混合使用:重命名 + 默认值。
const { name: userName = 'Anonymous' } = {}; // userName='Anonymous' - 函数参数解构:非常常用。
function greet({ name, age = 18 }) { console.log(`Hello, ${name}. You are ${age}.`); } greet({ name: 'Alice' }); // Hello, Alice. You are 18.
三、扩展运算符与剩余参数
1. 扩展运算符
- 用途:将可迭代对象(如数组、字符串)或对象“展开”为单个元素。
- 在数组中的使用:
const arr1 = [1, 2]; const arr2 = [...arr1, 3, 4]; // [1, 2, 3, 4] (数组合并) console.log(Math.max(...arr1)); // 2 (将数组展开为参数) - 在对象中的使用(ES2018):
const obj1 = { a: 1, b: 2 }; const obj2 = { ...obj1, c: 3 }; // { a:1, b:2, c:3 } (对象浅拷贝与合并)
2. 剩余参数
- 用途:将不定数量的参数表示为一个数组。取代了
arguments。 - 在函数参数中的使用:
function sum(...numbers) { return numbers.reduce((prev, curr) => prev + curr, 0); } sum(1, 2, 3); // 6 - 在解构中的使用:
const [a, b, ...others] = [1, 2, 3, 4, 5]; // a=1, b=2, others=[3,4,5] const { a, b, ...restProps } = { a:1, b:2, c:3, d:4 }; // a=1, b=2, restProps={c:3, d:4}
四、新的数据结构
1. Map 与 Object 的区别
| 特性 | Map | Object |
|---|---|---|
| 键的类型 | 任意值(函数、对象、基本类型) | String 或 Symbol |
| 键的顺序 | 键值对按插入顺序排列 | 无序(ES6后虽有顺序但不保证所有情况) |
| 大小 | 通过 size 属性获取 | 需要手动计算 |
| 性能 | 频繁增删键值对的场景下表现更好 | 未优化此场景 |
| 默认键 | 无 | 从原型链继承可能有默认键 |
常用API:new Map(), map.set(key, value), map.get(key), map.has(key), map.delete(key), map.size。
2. Set 与数组的区别
Set是值的集合,成员的值都是唯一的(自动去重)。- 常用API:
new Set(),set.add(value),set.has(value),set.delete(value),set.size。
应用场景:数组去重。
const uniqueArray = [...new Set([1, 2, 2, 3, 3])]; // [1, 2, 3]
3. WeakMap 与 WeakSet
- 弱引用:键/值是对象的弱引用,不计入垃圾回收机制。如果键/值对象没有其他引用了,它会被自动回收。
- 不可迭代:没有
size属性,无法遍历。 - 用途:用于存储一些“附属”信息,而不用担心内存泄漏。例如 DOM 元素作为键,存储与之相关的元数据。
五、面向对象与 Class
ES6 的 class 是构造函数的语法糖,更接近传统面向对象语言的写法。
1. 基本语法
class Person {
// 构造函数
constructor(name) {
this.name = name;
}
// 实例方法(挂在原型上)
sayHello() {
console.log(`Hello, I'm ${this.name}`);
}
// 静态方法(类本身的方法)
static isPerson(obj) {
return obj instanceof Person;
}
}
const alice = new Person('Alice');
alice.sayHello(); // Hello, I'm Alice
Person.isPerson(alice); // true
2. 继承
使用 extends 和 super。
super在构造函数中调用父类构造函数。super在普通方法中调用父类的方法。
class Student extends Person {
constructor(name, grade) {
super(name); // 必须在使用 this 前调用 super
this.grade = grade;
}
study() {
console.log(`${this.name} is studying.`);
}
// 重写父类方法
sayHello() {
super.sayHello(); // 调用父类的方法
console.log(`I'm in grade ${this.grade}`);
}
}
六、模块化
使用 export 和 import 来导出和导入模块。
1. 导出
- 命名导出:
// math.js export const pi = 3.14; export function add(a, b) { return a + b; } // 或者一起导出 export { pi, add }; - 默认导出(一个模块只能有一个):
// App.js export default function() { ... } // 或者 const App = ...; export default App;
2. 导入
- 导入命名导出:需要
{},且名称必须匹配。import { pi, add } from './math.js'; // 重命名 import { pi as圆周率 } from './math.js'; - 导入默认导出:不需要
{},可以任意命名。import MyApp from './App.js'; - 全部导入:
import * as math from './math.js'; // 使用 math.pi, math.add
七、其他重要特性
1. 函数参数默认值
function multiply(a, b = 1) {
return a * b;
}
multiply(5); // 5
2. 对象字面量增强
- 属性简写:
{ name }等同于{ name: name }。 - 方法简写:
{ sayHello() { ... } }等同于{ sayHello: function() { ... } }。 - 计算属性名:
{ [propKey]: value }。
3. Promise
(在JS异步编程中是核心,此处略,但面试必考)
4. 可选链操作符
?.:如果前面的值是null或undefined,则表达式短路返回undefined。const street = user?.address?.street; // 无需层层判断
5. 空值合并运算符
??:只有当左侧操作数为null或undefined时,才返回右侧操作数。const value = input ?? 'default'; // 与 `||` 不同,它不会过滤 0, '', false
掌握这些 ES6+ 特性,不仅能让你在面试中对答如流,更能极大地提升你的日常开发效率和代码质量。务必做到理解原理,并能熟练运用。
浙公网安备 33010602011771号