Skip to content

ES6+ 新特性面试题

1. let 和 const

问题:let 和 const 与 var 有什么区别?

答案

主要区别

特性varletconst
作用域函数作用域块级作用域块级作用域
变量提升否(暂时性死区)否(暂时性死区)
重复声明允许不允许不允许
重新赋值允许允许不允许

示例

javascript
// var - 函数作用域
function testVar() {
  if (true) {
    var x = 10;
  }
  console.log(x);  // 10
}

// let - 块级作用域
function testLet() {
  if (true) {
    let y = 20;
  }
  console.log(y);  // ReferenceError
}

// const - 不可重新赋值
const PI = 3.14159;
PI = 3.14;  // TypeError

// const 对象属性可以修改
const obj = { name: 'John' };
obj.name = 'Jane';  // 可以
obj.age = 30;      // 可以

暂时性死区

javascript
console.log(x);  // undefined
var x = 10;

console.log(y);  // ReferenceError(暂时性死区)
let y = 20;

2. 解构赋值

问题:如何使用解构赋值?

答案

数组解构

javascript
// 基本解构
const [a, b, c] = [1, 2, 3];
console.log(a, b, c);  // 1 2 3

// 跳过元素
const [first, , third] = [1, 2, 3];
console.log(first, third);  // 1 3

// 剩余元素
const [head, ...tail] = [1, 2, 3, 4];
console.log(head);  // 1
console.log(tail);  // [2, 3, 4]

// 默认值
const [x = 1, y = 2] = [3];
console.log(x, y);  // 3 2

// 交换变量
let m = 1, n = 2;
[m, n] = [n, m];
console.log(m, n);  // 2 1

对象解构

javascript
// 基本解构
const { name, age } = { name: 'John', age: 30 };
console.log(name, age);  // John 30

// 重命名
const { name: userName, age: userAge } = { name: 'John', age: 30 };
console.log(userName, userAge);  // John 30

// 默认值
const { x = 1, y = 2 } = { x: 3 };
console.log(x, y);  // 3 2

// 嵌套解构
const user = {
  name: 'John',
  address: {
    city: 'New York',
    country: 'USA'
  }
};
const { address: { city } } = user;
console.log(city);  // New York

// 函数参数解构
function greet({ name, age = 25 }) {
  console.log(`Hello, ${name}. You are ${age} years old.`);
}
greet({ name: 'John' });  // Hello, John. You are 25 years old.

3. 模板字符串

问题:模板字符串有哪些特性?

答案

javascript
// 基本使用
const name = 'John';
const greeting = `Hello, ${name}!`;
console.log(greeting);  // Hello, John!

// 多行字符串
const multiLine = `
  Line 1
  Line 2
  Line 3
`;

// 表达式
const a = 10, b = 20;
const sum = `Sum: ${a + b}`;  // Sum: 30

// 函数调用
const result = `Uppercase: ${name.toUpperCase()}`;  // Uppercase: JOHN

// 标签模板
function tag(strings, ...values) {
  console.log(strings);  // ['Hello ', '!']
  console.log(values);   // ['John']
  return strings[0] + values[0] + strings[1];
}

const tagged = tag`Hello ${name}!`;
console.log(tagged);  // Hello John!

// HTML 转义
function html(strings, ...values) {
  return strings.reduce((result, str, i) => {
    const value = values[i] || '';
    return result + str + value.replace(/&/g, '&');
  }, '');
}

const userInput = '<script>alert("XSS")</script>';
const safeHtml = html`<div>${userInput}</div>`;

4. 箭头函数

问题:箭头函数有什么特点?

答案

特点

javascript
// 简洁语法
const add = (a, b) => a + b;
const square = x => x * x;
const greet = () => console.log('Hello');

// 单行返回
const multiply = (a, b) => a * b;

// 多行返回
const calculate = (a, b) => {
  const sum = a + b;
  const product = a * b;
  return { sum, product };
};

// 没有 this 绑定
const obj = {
  name: 'John',
  sayName: function() {
    const arrow = () => {
      console.log(this.name);  // 'John'(继承外层 this)
    };
    arrow();
  }
};

// 没有 arguments 对象
const test = () => {
  console.log(arguments);  // ReferenceError
};

// 不能作为构造函数
const Person = (name) => {
  this.name = name;
};
const person = new Person('John');  // TypeError

this 绑定

javascript
// 普通函数
const obj = {
  name: 'John',
  regular: function() {
    setTimeout(function() {
      console.log(this.name);  // undefined
    }, 100);
  }
};

// 箭头函数
const obj2 = {
  name: 'John',
  arrow: function() {
    setTimeout(() => {
      console.log(this.name);  // 'John'
    }, 100);
  }
};

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

问题:如何使用扩展运算符和剩余参数?

答案

扩展运算符

javascript
// 数组扩展
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];  // [1, 2, 3, 4, 5, 6]

// 数组复制
const copy = [...arr1];  // [1, 2, 3]

// 对象扩展
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const merged = { ...obj1, ...obj2 };  // { a: 1, b: 2, c: 3, d: 4 }

// 对象复制
const objCopy = { ...obj1 };  // { a: 1, b: 2 }

// 函数参数
function sum(a, b, c) {
  return a + b + c;
}
const numbers = [1, 2, 3];
sum(...numbers);  // 6

// 数组去重
const arr = [1, 2, 2, 3, 3, 4];
const unique = [...new Set(arr)];  // [1, 2, 3, 4]

剩余参数

javascript
// 收集剩余参数
function sum(...numbers) {
  return numbers.reduce((acc, num) => acc + num, 0);
}
sum(1, 2, 3, 4);  // 10

// 部分参数 + 剩余参数
function greet(greeting, ...names) {
  names.forEach(name => {
    console.log(`${greeting}, ${name}!`);
  });
}
greet('Hello', 'John', 'Jane', 'Bob');

6. 类(Class)

问题:ES6 的 Class 语法如何使用?

答案

基本语法

javascript
class Person {
  // 构造函数
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  
  // 实例方法
  sayHello() {
    console.log(`Hello, I'm ${this.name}`);
  }
  
  // 静态方法
  static createAnonymous() {
    return new Person('Anonymous', 0);
  }
}

const person = new Person('John', 30);
person.sayHello();  // Hello, I'm John
const anonymous = Person.createAnonymous();

继承

javascript
class Animal {
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(`${this.name} makes a sound`);
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name);  // 调用父类构造函数
    this.breed = breed;
  }
  
  speak() {
    console.log(`${this.name} barks`);
  }
  
  fetch() {
    console.log(`${this.name} fetches the ball`);
  }
}

const dog = new Dog('Buddy', 'Golden Retriever');
dog.speak();  // Buddy barks
dog.fetch();  // Buddy fetches the ball

Getter 和 Setter

javascript
class Circle {
  constructor(radius) {
    this._radius = radius;
  }
  
  get radius() {
    return this._radius;
  }
  
  set radius(value) {
    if (value < 0) {
      throw new Error('Radius cannot be negative');
    }
    this._radius = value;
  }
  
  get area() {
    return Math.PI * this._radius ** 2;
  }
}

const circle = new Circle(5);
console.log(circle.area);  // 78.5398...
circle.radius = 10;
console.log(circle.area);  // 314.159...

7. 模块化

问题:ES6 模块如何使用?

答案

导出

javascript
// 命名导出
export const PI = 3.14159;
export function add(a, b) {
  return a + b;
}
export class Calculator {
  add(a, b) {
    return a + b;
  }
}

// 默认导出
export default function greet(name) {
  console.log(`Hello, ${name}!`);
}

// 混合导出
export const greeting = 'Hello';
export default function sayHello() {
  console.log(greeting);
}

导入

javascript
// 导入默认导出
import greet from './greet.js';
greet('John');

// 导入命名导出
import { PI, add, Calculator } from './math.js';
console.log(PI);
console.log(add(1, 2));
const calc = new Calculator();

// 导入所有
import * as math from './math.js';
console.log(math.PI);
console.log(math.add(1, 2));

// 重命名导入
import { add as sum } from './math.js';
console.log(sum(1, 2));

// 只导入模块(执行副作用)
import './styles.css';

8. Promise

问题:Promise 如何使用?

答案

基本用法

javascript
// 创建 Promise
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = true;
    if (success) {
      resolve('Success!');
    } else {
      reject('Failed!');
    }
  }, 1000);
});

// 使用 Promise
promise
  .then(result => {
    console.log(result);  // Success!
  })
  .catch(error => {
    console.error(error);  // Failed!
  })
  .finally(() => {
    console.log('Promise completed');
  });

链式调用

javascript
fetch('/api/user')
  .then(response => response.json())
  .then(user => {
    console.log(user);
    return fetch(`/api/posts/${user.id}`);
  })
  .then(response => response.json())
  .then(posts => {
    console.log(posts);
  })
  .catch(error => {
    console.error('Error:', error);
  });

Promise 静态方法

javascript
// Promise.all - 所有成功
Promise.all([
  fetch('/api/users'),
  fetch('/api/posts'),
  fetch('/api/comments')
])
  .then(responses => {
    console.log('All requests completed');
  })
  .catch(error => {
    console.error('One request failed');
  });

// Promise.race - 第一个完成
Promise.race([
  fetch('/api/fast'),
  fetch('/api/slow')
])
  .then(response => {
    console.log('First request completed');
  });

// Promise.allSettled - 所有完成
Promise.allSettled([
  Promise.resolve('Success'),
  Promise.reject('Error')
])
  .then(results => {
    results.forEach(result => {
      if (result.status === 'fulfilled') {
        console.log(result.value);
      } else {
        console.error(result.reason);
      }
    });
  });

// Promise.any - 第一个成功
Promise.any([
  Promise.reject('Error 1'),
  Promise.reject('Error 2'),
  Promise.resolve('Success')
])
  .then(result => {
    console.log(result);  // Success
  });

9. async/await

问题:async/await 如何使用?

答案

基本用法

javascript
// async 函数
async function fetchData() {
  try {
    const response = await fetch('/api/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error:', error);
    throw error;
  }
}

// 使用
fetchData()
  .then(data => console.log(data))
  .catch(error => console.error(error));

并行执行

javascript
// 串行执行
async function sequential() {
  const user = await fetch('/api/user');
  const posts = await fetch('/api/posts');
  const comments = await fetch('/api/comments');
  return { user, posts, comments };
}

// 并行执行
async function parallel() {
  const [user, posts, comments] = await Promise.all([
    fetch('/api/user'),
    fetch('/api/posts'),
    fetch('/api/comments')
  ]);
  return { user, posts, comments };
}

错误处理

javascript
// try-catch
async function withTryCatch() {
  try {
    const data = await fetchData();
    return data;
  } catch (error) {
    console.error('Error:', error);
    return null;
  }
}

// .catch()
async function withCatch() {
  const data = await fetchData().catch(error => {
    console.error('Error:', error);
    return null;
  });
  return data;
}

10. 新特性(ES7-ES12)

问题:ES7-ES12 有哪些新特性?

答案

ES7 (2016)

javascript
// 指数运算符
2 ** 3;  // 8

// Array.prototype.includes
[1, 2, 3].includes(2);  // true

ES8 (2017)

javascript
// async/await
// Object.values()
Object.values({ a: 1, b: 2 });  // [1, 2]

// Object.entries()
Object.entries({ a: 1, b: 2 });  // [['a', 1], ['b', 2]]

// String.prototype.padStart/padEnd
'hello'.padStart(10, 'x');  // 'xxxxxhello'
'hello'.padEnd(10, 'x');    // 'helloxxxxx'

// Object.getOwnPropertyDescriptors
const obj = { a: 1 };
Object.getOwnPropertyDescriptors(obj);

ES9 (2018)

javascript
// 异步迭代
async function asyncIterate() {
  const asyncIterable = createAsyncIterable();
  for await (const item of asyncIterable) {
    console.log(item);
  }
}

// Promise.prototype.finally
fetch('/api/data')
  .then(response => response.json())
  .catch(error => console.error(error))
  .finally(() => console.log('Cleanup'));

// Object rest/spread
const { a, b, ...rest } = { a: 1, b: 2, c: 3, d: 4 };
console.log(rest);  // { c: 3, d: 4 }

ES10 (2019)

javascript
// Array.prototype.flat
[1, [2, [3]]].flat(2);  // [1, 2, 3]

// Array.prototype.flatMap
[1, 2, 3].flatMap(x => [x, x * 2]);  // [1, 2, 2, 4, 3, 6]

// Object.fromEntries
Object.fromEntries([['a', 1], ['b', 2]]);  // { a: 1, b: 2 }

// String.prototype.trimStart/trimEnd
'  hello  '.trimStart();  // 'hello  '
'  hello  '.trimEnd();    // '  hello'

ES11 (2020)

javascript
// 可选链
const user = { name: 'John', address: { city: 'New York' } };
const city = user?.address?.city;  // 'New York'

// 空值合并
const name = user.name ?? 'Anonymous';  // 'John'
const age = user.age ?? 0;            // 0

// BigInt
const bigNumber = 9007199254740991n;
bigNumber + 1n;  // 9007199254740992n

// Promise.allSettled
// 动态 import()
const module = await import('./module.js');

ES12 (2021)

javascript
// String.prototype.replaceAll
'hello world'.replaceAll('l', 'L');  // 'heLLo worLd'

// Promise.any
// 数字分隔符
const billion = 1_000_000_000;

// 逻辑赋值运算符
a ||= b;  // a = a || b
a &&= b;  // a = a && b
a ??= b;  // a = a ?? b