ES6高频面试题(30题) 副本

查看飞书原文 ↗8,169 字符
1. 什么是ES6?它的主要特性有哪些?​
​
参考答案:​
ES6(ECMAScript 2015)是JavaScript的第六个版本,是JavaScript语言的重大更新。主要特性包括:​
•
let和const关键字​
•
箭头函数​
•
模板字符串​
•
解构赋值​
•
默认参数​
•
扩展运算符​
•
Promise​
•
类(Class)​
•
模块化(import/export)​
•
Symbol数据类型​
•
Map和Set数据结构​
•
生成器函数(Generator)​
​
2. let、const和var的区别是什么?​
​
参考答案:​
•
作用域:var是函数作用域,let和const是块级作用域​
•
变量提升:var存在变量提升,let和const存在暂时性死区​
•
重复声明:var允许重复声明,let和const不允许​
•
赋值:var和let可以重新赋值,const不能重新赋值(但对象内容可修改)​
•
初始化:var和let可以不初始化,const必须初始化​
​
3. 什么是箭头函数?它与普通函数有什么区别?​
​
参考答案:​
箭头函数是ES6新增的函数定义方式,语法更简洁。主要区别:​
•
this指向:箭头函数没有自己的this,继承外层作用域的this​
•
arguments对象:箭头函数没有arguments对象​
•
构造函数:箭头函数不能作为构造函数使用​
•
原型:箭头函数没有prototype属性​
•
变量提升:箭头函数不存在变量提升​
​
4. 什么是模板字符串?它有什么优势?​
​
参考答案:​
模板字符串使用反引号(`)包围,可以包含占位符(${expression})。优势:​
•
支持多行字符串​
•
支持变量插值​
•
支持表达式计算​
•
更直观的字符串拼接​
•
支持标签模板功能​
​
5. 解构赋值是什么?请举例说明数组和对象的解构。​
​
参考答案:​
解构赋值是一种从数组或对象中提取值并赋给变量的语法。​
// 数组解构
const [a, b, c] = [1, 2, 3];
const [x, , z] = [1, 2, 3]; // 跳过中间元素

// 对象解构
const {name, age} = {name: 'John', age: 30};
const {name: userName, age: userAge} = obj; // 重命名
​
6. 什么是扩展运算符(...)?它有哪些用途?​
​
参考答案:​
扩展运算符(...)可以将可迭代对象展开。用途包括:​
•
数组展开:[...arr1, ...arr2]​
•
对象展开:{...obj1, ...obj2}​
•
函数参数展开:func(...args)​
•
复制数组/对象:[...arr]、{...obj}​
•
将类数组对象转为数组:[...nodeList]​
​
7. 什么是剩余参数(rest parameters)?​
​
参考答案:​
剩余参数使用...语法,将多个参数收集到一个数组中:​
function sum(...numbers) {
  return numbers.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4); // numbers = [1, 2, 3, 4]
剩余参数必须是最后一个参数,一个函数只能有一个剩余参数。​
​
8. ES6中的默认参数是如何工作的?​
​
参考答案:​
ES6允许为函数参数设置默认值:​
function greet(name = 'World') {
  return `Hello, ${name}!`;
}
•
只有当参数为undefined时才使用默认值​
•
默认参数可以是表达式或函数调用​
•
默认参数可以引用前面的参数​
•
有默认值的参数应该放在后面​
​
9. 什么是Promise?它解决了什么问题?​
​
参考答案:​
Promise是处理异步操作的对象,有三种状态:pending、fulfilled、rejected。​
解决的问题:​
•
回调地狱问题​
•
错误处理困难​
•
异步操作的组合和串联​
•
提供了更好的异步编程模式​
​
基本用法:​
const promise = new Promise((resolve, reject) => {
  // 异步操作
});
promise.then(result => {}).catch(error => {});
​
10. ES6的类(Class)是如何工作的?​
​
参考答案:​
ES6的类是基于原型的语法糖:​
class Person {
  constructor(name) {
    this.name = name;
  }
  
  sayHello() {
    return `Hello, I'm ${this.name}`;
  }
  
  static getSpecies() {
    return 'Homo sapiens';
  }
}
•
constructor定义构造函数​
•
方法定义在原型上​
•
支持静态方法​
•
支持继承(extends)​
​
11. ES6模块化(import/export)是如何工作的?​
​
参考答案:​
ES6提供了原生的模块化支持:​
// 导出
export const name = 'John';
export function greet() {}
export default class Person {}

// 导入
import Person, { name, greet } from './module.js';
import * as utils from './utils.js';
•
静态导入导出​
•
编译时确定依赖关系​
•
支持默认导出和命名导出​
•
自动严格模式​
​
12. Symbol数据类型有什么特点和用途?​
​
参考答案:​
Symbol是ES6新增的原始数据类型,表示独一无二的值。特点:​
•
每个Symbol值都是唯一的​
•
不能与其他值进行运算​
•
可以作为对象属性名​
•
不会被常规方法遍历到​
​
用途:​
•
创建对象的私有属性​
•
定义对象的元数据​
•
避免属性名冲突​
•
实现迭代器接口​
​
13. Map和Set数据结构有什么特点?​
​
参考答案:​
Map特点:​
•
键值对集合,键可以是任意类型​
•
有序,按插入顺序遍历​
•
size属性获取大小​
•
方法:set、get、has、delete、clear​
​
Set特点:​
•
值的集合,值唯一​
•
有序,按插入顺序遍历​
•
size属性获取大小​
•
方法:add、has、delete、clear​
•
可用于数组去重​
​
14. 什么是生成器函数(Generator)?​
​
参考答案:​
生成器函数是可以暂停和恢复执行的函数,使用function*定义:​
function* generator() {
  yield 1;
  yield 2;
  return 3;
}

const gen = generator();
gen.next(); // {value: 1, done: false}
gen.next(); // {value: 2, done: false}
gen.next(); // {value: 3, done: true}
特点:​
•
返回迭代器对象​
•
可以暂停和恢复执行​
•
用于实现异步编程​
•
可以双向通信​
​
15. 什么是迭代器(Iterator)和可迭代对象?​
​
参考答案:​
迭代器:实现了next()方法的对象,返回{value, done}格式的结果。​
​
可迭代对象:实现了Symbol.iterator方法的对象。​
​
内置可迭代对象:Array、String、Map、Set、arguments等。​
​
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator]();
iterator.next(); // {value: 1, done: false}
​
16. for...of和for...in的区别是什么?​
​
参考答案:​
•
for...in:遍历对象的可枚举属性名(包括继承的)​
•
for...of:遍历可迭代对象的值​
​
const arr = [1, 2, 3];
arr.name = 'array';

for (let key in arr) {
  console.log(key); // 0, 1, 2, name
}

for (let value of arr) {
  console.log(value); // 1, 2, 3
}
​
17. 什么是Proxy?它有什么用途?​
​
参考答案:​
Proxy用于定义基本操作的自定义行为(如属性查找、赋值等):​
const proxy = new Proxy(target, handler);
​
用途:​
•
属性访问拦截​
•
函数调用拦截​
•
数据验证​
•
属性默认值​
•
实现观察者模式​
•
Vue3的响应式原理​
​
常用handler方法:get、set、has、deleteProperty等。​
​
18. 什么是Reflect?它与Proxy有什么关系?​
​
参考答案:​
Reflect是一个内置对象,提供了拦截JavaScript操作的方法。​
​
特点:​
•
方法与Proxy handler方法一一对应​
•
提供了默认的对象操作行为​
•
返回值更合理(布尔值而不是抛出异常)​
​
// 传统方式
delete obj.prop;

// Reflect方式
Reflect.deleteProperty(obj, 'prop'); // 返回boolean
​
与Proxy配合使用可以实现更好的元编程。​
​
19. 什么是WeakMap和WeakSet?它们与Map、Set有什么区别?​
​
参考答案:​
WeakMap和WeakSet的特点:​
•
键/值必须是对象​
•
弱引用,不阻止垃圾回收​
•
不可遍历,没有size属性​
•
没有clear方法​
​
与Map、Set的区别:​
•
引用类型:弱引用 vs 强引用​
•
垃圾回收:不阻止 vs 阻止​
•
遍历性:不可遍历 vs 可遍历​
•
用途:存储私有数据 vs 一般数据存储​
​
20. 什么是暂时性死区(Temporal Dead Zone)?​
​
参考答案:​
暂时性死区是指let和const声明的变量在声明之前不能被访问的区域。​
​
console.log(a); // ReferenceError
let a = 1;

function func() {
  console.log(b); // ReferenceError
  let b = 2;
}
​
特点:​
•
从块级作用域开始到变量声明之前​
•
访问会抛出ReferenceError​
•
typeof操作符也会报错​
•
确保变量先声明后使用​
​
21. ES6中的对象字面量有哪些增强?​
​
参考答案:​
ES6对象字面量增强包括:​
​
1.
属性简写:{name, age} 等价于 {name: name, age: age}​
2.
方法简写:{method() {}} 等价于 {method: function() {}}​
3.
计算属性名:{[key]: value}​
4.
可以使用表达式作为属性名​
5.
super关键字:在方法中调用原型方法​
​
const name = 'John';
const obj = {
  name,                    // 属性简写
  greet() {},             // 方法简写
  [name + 'Key']: 'value' // 计算属性名
};
​
22. 什么是数组的新方法?请列举几个ES6新增的数组方法。​
​
参考答案:​
ES6为数组新增了多个方法:​
​
•
Array.from():将类数组对象转为数组​
•
Array.of():创建数组,避免Array构造函数的怪异行为​
•
find():找到第一个满足条件的元素​
•
findIndex():找到第一个满足条件的元素索引​
•
includes():判断数组是否包含某个值​
•
fill():用指定值填充数组​
•
keys()、values()、entries():返回迭代器​
​
23. 什么是字符串的新方法?ES6为字符串添加了哪些方法?​
​
参考答案:​
ES6为字符串新增的方法:​
​
•
includes():判断是否包含子字符串​
•
startsWith():判断是否以指定字符串开头​
•
endsWith():判断是否以指定字符串结尾​
•
repeat():重复字符串指定次数​
•
padStart():在开头填充字符串到指定长度​
•
padEnd():在末尾填充字符串到指定长度​
​
'hello'.includes('ell'); // true
'hello'.startsWith('he'); // true
'hello'.repeat(2); // 'hellohello'
​
24. 什么是参数解构?请举例说明。​
​
参考答案:​
参数解构是在函数参数中直接解构传入的对象或数组:​
​
// 对象参数解构
function greet({name, age = 18}) {
  console.log(`Hello ${name}, age ${age}`);
}
greet({name: 'John', age: 25});

// 数组参数解构
function sum([a, b]) {
  return a + b;
}
sum([1, 2]);

// 嵌套解构
function process({user: {name, email}}) {
  console.log(name, email);
}
​
25. 什么是尾调用优化?ES6如何支持尾调用优化?​
​
参考答案:​
尾调用是指函数的最后一步调用另一个函数。尾调用优化是指在尾调用时不增加新的栈帧,而是复用当前栈帧。​
​
ES6在严格模式下支持尾调用优化:​
'use strict';
function factorial(n, acc = 1) {
  if (n <= 1) return acc;
  return factorial(n - 1, n * acc); // 尾调用
}
​
条件:​
•
严格模式​
•
尾调用不访问当前栈帧的变量​
•
尾调用是函数的最后一个操作​
​
26. 什么是标签模板?它有什么用途?​
​
参考答案:​
标签模板是模板字符串的高级形式,允许用函数解析模板字符串:​
​
function highlight(strings, ...values) {
  return strings.reduce((result, string, i) => {
    return result + string + (values[i] ? `<mark>${values[i]}</mark>` : '');
  }, '');
}

const name = 'John';
const age = 25;
const result = highlight`Hello ${name}, you are ${age} years old`;
​
用途:​
•
字符串处理和转换​
•
模板引擎​
•
国际化​
•
防止XSS攻击​
​
27. ES6中的正则表达式有哪些新特性?​
​
参考答案:​
ES6为正则表达式添加了新特性:​
​
1.
u标志:Unicode模式,正确处理大于\uFFFF的Unicode字符​
2.
y标志:粘连模式,从lastIndex位置开始匹配​
3.
RegExp构造函数增强:可以接受正则表达式作为参数​
4.
新方法:flags属性获取修饰符​
​
const regex = /\u{1D306}/u; // Unicode模式
const sticky = /hello/y;    // 粘连模式
regex.flags; // 'u'
​
28. 什么是二进制和八进制字面量?​
​
参考答案:​
ES6提供了二进制和八进制数值的新写法:​
​
// 二进制(0b或0B开头)
const binary = 0b1010; // 10
const binary2 = 0B1010; // 10

// 八进制(0o或0O开头)
const octal = 0o755; // 493
const octal2 = 0O755; // 493

// 检测方法
Number.isFinite(binary); // true
Number.isInteger(octal); // true
​
注意:严格模式下不支持0开头的八进制写法。​
​
29. ES6中的Number对象有哪些新方法?​
​
参考答案:​
ES6为Number对象新增了多个方法:​
​
•
Number.isFinite():检测数值是否有限​
•
Number.isNaN():检测是否为NaN​
•
Number.parseInt():解析整数​
•
Number.parseFloat():解析浮点数​
•
Number.isInteger():判断是否为整数​
•
Number.isSafeInteger():判断是否在安全整数范围内​
•
Number.EPSILON:最小精度常量​
•
Number.MAX_SAFE_INTEGER/MIN_SAFE_INTEGER:安全整数范围​
​
30. 什么是Object.assign()?它有什么特点和用途?​
​
参考答案:​
Object.assign()用于将源对象的可枚举属性复制到目标对象:​
​
const target = {a: 1};
const source = {b: 2, c: 3};
Object.assign(target, source); // {a: 1, b: 2, c: 3}
​
特点:​
•
浅拷贝,不会拷贝继承属性和不可枚举属性​
•
同名属性会被覆盖​
•
返回目标对象​
•
可以接受多个源对象​
​
用途:​
•
对象合并​
•
对象克隆​
•
为对象添加属性​
•
为对象添加方法​
​
本文暂未被其它文档引用