1. 变量声明

let 和 const

// let - 块级作用域,可重新赋值
let name = 'John'
name = 'Jane' // 可以
 
// const - 块级作用域,不可重新赋值
const age = 25
// age = 26 // 报错
 
// 块级作用域
{
  let x = 1
  const y = 2
}
// console.log(x) // 报错,x 不存在

2. 模板字符串

const name = 'World'
const greeting = `Hello, ${name}!`
 
// 多行字符串
const html = `
  <div>
    <h1>${title}</h1>
    <p>${content}</p>
  </div>
`
 
// 标签模板
function highlight(strings, ...values) {
  return strings.reduce((result, string, i) => {
    return result + string + (values[i] ? `<mark>${values[i]}</mark>` : '')
  }, '')
}

3. 箭头函数

// 基本语法
const add = (a, b) => a + b
const square = x => x * x
const greet = () => 'Hello'
 
// this 绑定的区别
function Timer() {
  this.seconds = 0
  
  // 箭头函数继承外层 this
  setInterval(() => {
    this.seconds++
  }, 1000)
}
 
// 不能作为构造函数
const Person = (name) => {
  this.name = name
}
// new Person() // 报错

4. 解构赋值

数组解构

const [a, b, c] = [1, 2, 3]
const [first, , third] = [1, 2, 3] // 跳过元素
const [x, y, ...rest] = [1, 2, 3, 4, 5] // rest: [3, 4, 5]
 
// 默认值
const [name = 'Anonymous'] = []

对象解构

const { name, age } = { name: 'John', age: 25, city: 'NYC' }
 
// 重命名
const { name: userName, age: userAge } = user
 
// 嵌套解构
const { address: { street, city } } = user
 
// 函数参数解构
function greet({ name, age = 18 }) {
  return `Hello ${name}, you are ${age}`
}

5. 默认参数

function greet(name = 'World', punctuation = '!') {
  return `Hello, ${name}${punctuation}`
}
 
// 可以使用表达式
function createUser(name, id = Date.now()) {
  return { name, id }
}
 
// 参数可以引用前面的参数
function multiply(a, b = a) {
  return a * b
}

6. 展开运算符(Spread)

// 数组展开
const arr1 = [1, 2, 3]
const arr2 = [...arr1, 4, 5] // [1, 2, 3, 4, 5]
 
// 对象展开
const obj1 = { a: 1, b: 2 }
const obj2 = { ...obj1, c: 3 } // { a: 1, b: 2, c: 3 }
 
// 函数调用
function sum(a, b, c) {
  return a + b + c
}
const numbers = [1, 2, 3]
sum(...numbers) // 等同于 sum(1, 2, 3)
 
// 复制数组/对象
const newArr = [...oldArr]
const newObj = { ...oldObj }

7. 剩余参数(Rest)

function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0)
}
 
sum(1, 2, 3, 4) // 10
 
// 与普通参数结合
function greet(greeting, ...names) {
  return `${greeting} ${names.join(', ')}`
}
 
greet('Hello', 'John', 'Jane', 'Bob')

8. 类(Class)

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  
  // 方法
  greet() {
    return `Hello, I'm ${this.name}`
  }
  
  // 静态方法
  static species() {
    return 'Homo sapiens'
  }
  
  // getter/setter
  get info() {
    return `${this.name} (${this.age})`
  }
  
  set age(value) {
    if (value < 0) throw new Error('Age cannot be negative')
    this._age = value
  }
}
 
// 继承
class Student extends Person {
  constructor(name, age, grade) {
    super(name, age) // 调用父类构造函数
    this.grade = grade
  }
  
  study() {
    return `${this.name} is studying`
  }
}

9. 模块系统

// 导出 (export)
export const PI = 3.14159
export function add(a, b) {
  return a + b
}
 
export default class Calculator {
  // ...
}
 
// 导入 (import)
import Calculator, { PI, add } from './calculator.js'
import * as math from './math.js'
import { add as sum } from './calculator.js'
 
// 动态导入
import('./module.js').then(module => {
  // 使用模块
})

10. Promise

// 创建 Promise
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (Math.random() > 0.5) {
      resolve('Success!')
    } else {
      reject(new Error('Failed!'))
    }
  }, 1000)
})
 
// 使用 Promise
promise
  .then(result => console.log(result))
  .catch(error => console.error(error))
  .finally(() => console.log('Done'))
 
// Promise 静态方法
Promise.all([promise1, promise2, promise3])
Promise.race([promise1, promise2])
Promise.resolve(value)
Promise.reject(error)

11. Symbol

// 创建 Symbol
const sym1 = Symbol()
const sym2 = Symbol('description')
const sym3 = Symbol.for('global-symbol')
 
// 作为对象属性
const obj = {
  [sym1]: 'value1',
  [Symbol.iterator]: function* () {
    yield 1
    yield 2
    yield 3
  }
}
 
// 内置 Symbol
Symbol.iterator // 迭代器
Symbol.hasInstance // instanceof
Symbol.toPrimitive // 类型转换

12. 迭代器和生成器

迭代器

const iterable = {
  [Symbol.iterator]() {
    let step = 0
    return {
      next() {
        if (step < 3) {
          return { value: step++, done: false }
        }
        return { done: true }
      }
    }
  }
}
 
for (const value of iterable) {
  console.log(value) // 0, 1, 2
}

生成器

function* numberGenerator() {
  yield 1
  yield 2
  yield 3
  return 'done'
}
 
const gen = numberGenerator()
console.log(gen.next()) // { value: 1, done: false }
console.log(gen.next()) // { value: 2, done: false }
 
// 无限序列
function* fibonacci() {
  let [a, b] = [0, 1]
  while (true) {
    yield a
    ;[a, b] = [b, a + b]
  }
}

13. 新的数据结构

Set

const set = new Set([1, 2, 3, 3]) // {1, 2, 3}
set.add(4)
set.has(2) // true
set.delete(1)
set.size // 3
 
// 数组去重
const unique = [...new Set(array)]

Map

const map = new Map()
map.set('key1', 'value1')
map.set(42, 'number key')
map.set({}, 'object key')
 
map.get('key1') // 'value1'
map.has(42) // true
map.size // 3
 
// 遍历
for (const [key, value] of map) {
  console.log(key, value)
}

WeakSet 和 WeakMap

// WeakSet - 只能存储对象,弱引用
const weakSet = new WeakSet()
const obj = {}
weakSet.add(obj)
 
// WeakMap - 键只能是对象,弱引用
const weakMap = new WeakMap()
weakMap.set(obj, 'some value')

14. 增强的对象字面量

const name = 'John'
const age = 25
 
// 属性简写
const person = { name, age }
 
// 方法简写
const obj = {
  greet() {
    return 'Hello'
  },
  
  // 计算属性名
  [name + '_info']: 'some info',
  
  // 可以使用表达式
  ['prop_' + (() => 42)()]: true
}

15. 新的数组方法

// Array.from - 类数组转数组
Array.from('hello') // ['h', 'e', 'l', 'l', 'o']
Array.from([1, 2, 3], x => x * 2) // [2, 4, 6]
 
// Array.of - 创建数组
Array.of(1, 2, 3) // [1, 2, 3]
 
// find/findIndex
[1, 2, 3, 4].find(x => x > 2) // 3
[1, 2, 3, 4].findIndex(x => x > 2) // 2
 
// fill
new Array(3).fill(0) // [0, 0, 0]
 
// includes
[1, 2, 3].includes(2) // true

16. 新的字符串方法

// includes, startsWith, endsWith
'hello world'.includes('world') // true
'hello world'.startsWith('hello') // true
'hello world'.endsWith('world') // true
 
// repeat
'abc'.repeat(3) // 'abcabcabc'
 
// padStart, padEnd
'5'.padStart(3, '0') // '005'
'5'.padEnd(3, '0') // '500'

面试重点

在面试中,重点关注这些内容:

  1. let/const - 块级作用域,暂时性死区
  2. 箭头函数 - this 绑定,不能作为构造函数
  3. 解构赋值 - 提高代码简洁性
  4. Promise - 异步编程的重要改进
  5. Class - 面向对象编程的语法糖
  6. 模块系统 - 现代 JavaScript 开发的基础
  7. 模板字符串 - 字符串处理的改进

这些特性大大提升了 JavaScript 的开发体验和代码质量!