Skip to content

ECMAScript 2016(ES7)

Exponentiation Operator (**)

指数运算符,用于计算数字的幂运算,是 Math.pow() 的语法糖。

javascript
{
  // 传统方法:自定义函数
  function pow(x, y) {
    let result = 1
    for (let i = 0; i < y; i++) {
      result *= x
    }
    return result
  }
  console.log(pow(2, 5)) // 32

  // 传统方法:Math.pow()
  console.log(Math.pow(2, 5)) // 32
  console.log(Math.pow(3, 3)) // 27
  console.log(Math.pow(10, -2)) // 0.01

  // ES7 新语法:指数运算符
  console.log(2 ** 5)    // 32
  console.log(3 ** 3)    // 27
  console.log(10 ** -2)  // 0.01

  // 运算符优先级
  console.log(2 ** 3 ** 2)   // 512 (等同于 2 ** (3 ** 2))
  console.log((2 ** 3) ** 2) // 64

  // 与其他运算符结合
  console.log(2 ** 3 * 4)    // 32 (等同于 (2 ** 3) * 4)
  console.log(2 * 3 ** 2)    // 18 (等同于 2 * (3 ** 2))

  // 赋值运算符形式
  let num = 2
  num **= 3
  console.log(num) // 8

  // 实际应用:数学计算
  function calculateCompoundInterest(principal, rate, time) {
    return principal * (1 + rate) ** time
  }

  const investment = calculateCompoundInterest(1000, 0.05, 10)
  console.log(investment.toFixed(2)) // 1628.89

  // 计算圆的面积
  function circleArea(radius) {
    return Math.PI * radius ** 2
  }
  console.log(circleArea(5).toFixed(2)) // 78.54

  // 计算立方体体积
  function cubeVolume(side) {
    return side ** 3
  }
  console.log(cubeVolume(4)) // 64

  // 科学计算:计算距离
  function distance3D(x1, y1, z1, x2, y2, z2) {
    return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2 + (z2 - z1) ** 2)
  }
  console.log(distance3D(0, 0, 0, 3, 4, 5).toFixed(2)) // 7.07

  // 二进制运算
  function powerOfTwo(n) {
    return 2 ** n
  }
  console.log([0, 1, 2, 3, 4, 5].map(powerOfTwo)) // [1, 2, 4, 8, 16, 32]

  // 处理大数
  console.log(10 ** 6)   // 1000000
  console.log(2 ** 53)   // 9007199254740992 (Number.MAX_SAFE_INTEGER + 1)
  console.log(2 ** 10)   // 1024 (1KB)
  console.log(2 ** 20)   // 1048576 (1MB)

  // 分数指数(开方)
  console.log(9 ** 0.5)   // 3 (平方根)
  console.log(8 ** (1/3)) // 2 (立方根)
  console.log(16 ** 0.25) // 2 (四次方根)

  // 与 BigInt 结合使用
  console.log(2n ** 100n) // 1267650600228229401496703205376n

  // 性能比较
  function performanceTest() {
    const start1 = performance.now()
    for (let i = 0; i < 1000000; i++) {
      Math.pow(2, 10)
    }
    const end1 = performance.now()

    const start2 = performance.now()
    for (let i = 0; i < 1000000; i++) {
      2 ** 10
    }
    const end2 = performance.now()

    console.log(`Math.pow(): ${end1 - start1}ms`)
    console.log(`** operator: ${end2 - start2}ms`)
  }
  // performanceTest() // ** 运算符通常更快
}

Array.prototype.includes()

判断数组是否包含指定值,返回布尔值,比 indexOf() 更语义化。

javascript
{
  const numbers = [1, 2, 3, 4, 5, NaN]
  const fruits = ['apple', 'banana', 'orange']

  // 基本用法
  console.log(numbers.includes(3))     // true
  console.log(numbers.includes(6))     // false
  console.log(fruits.includes('apple')) // true

  // 与 indexOf() 的比较
  console.log(numbers.indexOf(3) !== -1)  // true (传统方法)
  console.log(numbers.includes(3))        // true (ES7 方法,更直观)

  // 处理 NaN
  console.log(numbers.indexOf(NaN))    // -1 (indexOf 无法正确处理 NaN)
  console.log(numbers.includes(NaN))   // true (includes 可以正确处理 NaN)

  // 使用 fromIndex 参数
  const array = [1, 2, 3, 4, 5, 3, 2, 1]
  
  console.log(array.includes(3))      // true
  console.log(array.includes(3, 3))   // true (从索引 3 开始查找)
  console.log(array.includes(3, 6))   // false (从索引 6 开始查找)

  // 负数索引
  console.log(array.includes(2, -3))  // true (从倒数第3个位置开始)
  console.log(array.includes(1, -1))  // true (从最后一个位置开始)

  // 实际应用:条件判断
  const userRoles = ['admin', 'editor', 'viewer']
  const currentUser = { role: 'editor' }

  if (userRoles.includes(currentUser.role)) {
    console.log('User has valid role')
  }

  // 表单验证
  function validateEmail(email) {
    const validDomains = ['gmail.com', 'yahoo.com', 'hotmail.com']
    const domain = email.split('@')[1]
    return validDomains.includes(domain)
  }

  console.log(validateEmail('user@gmail.com'))    // true
  console.log(validateEmail('user@unknown.com'))  // false

  // 过滤数组
  const allUsers = [
    { name: 'Alice', status: 'active' },
    { name: 'Bob', status: 'inactive' },
    { name: 'Charlie', status: 'pending' },
    { name: 'Diana', status: 'active' }
  ]

  const activeStatuses = ['active', 'pending']
  const filteredUsers = allUsers.filter(user => 
    activeStatuses.includes(user.status)
  )
  console.log(filteredUsers) 
  // [{ name: 'Alice', status: 'active' }, { name: 'Charlie', status: 'pending' }, { name: 'Diana', status: 'active' }]

  // 权限检查
  class PermissionManager {
    constructor(userPermissions) {
      this.permissions = userPermissions
    }

    hasPermission(permission) {
      return this.permissions.includes(permission)
    }

    hasAnyPermission(permissions) {
      return permissions.some(permission => this.permissions.includes(permission))
    }

    hasAllPermissions(permissions) {
      return permissions.every(permission => this.permissions.includes(permission))
    }
  }

  const pm = new PermissionManager(['read', 'write', 'delete'])
  
  console.log(pm.hasPermission('read'))              // true
  console.log(pm.hasPermission('admin'))             // false
  console.log(pm.hasAnyPermission(['admin', 'read'])) // true
  console.log(pm.hasAllPermissions(['read', 'write'])) // true

  // 黑名单检查
  function isValidUrl(url) {
    const blockedDomains = ['spam.com', 'malware.net', 'phishing.org']
    const domain = new URL(url).hostname
    return !blockedDomains.includes(domain)
  }

  console.log(isValidUrl('https://google.com'))    // true
  console.log(isValidUrl('https://spam.com'))      // false

  // 菜单项激活状态
  function getActiveMenuItems(currentPath, menuItems) {
    return menuItems.map(item => ({
      ...item,
      active: item.paths.includes(currentPath)
    }))
  }

  const menuItems = [
    { name: 'Home', paths: ['/', '/home'] },
    { name: 'About', paths: ['/about', '/about-us'] },
    { name: 'Contact', paths: ['/contact', '/contact-us'] }
  ]

  const activeItems = getActiveMenuItems('/about', menuItems)
  console.log(activeItems)

  // 搜索功能
  function searchUsers(query, users) {
    const keywords = query.toLowerCase().split(' ')
    return users.filter(user => 
      keywords.every(keyword => 
        user.name.toLowerCase().includes(keyword) ||
        user.tags.some(tag => tag.toLowerCase().includes(keyword))
      )
    )
  }

  const users = [
    { name: 'John Doe', tags: ['developer', 'javascript'] },
    { name: 'Jane Smith', tags: ['designer', 'ui/ux'] },
    { name: 'Bob Johnson', tags: ['developer', 'python'] }
  ]

  const searchResults = searchUsers('john developer', users)
  console.log(searchResults) // [{ name: 'John Doe', tags: ['developer', 'javascript'] }]

  // 限制:只能检测简单类型
  const complexArray = [
    { id: 1, name: 'Alice' },
    { id: 2, name: 'Bob' },
    [1, 2, 3]
  ]

  console.log(complexArray.includes({ id: 1, name: 'Alice' })) // false (对象引用不同)
  console.log(complexArray.includes([1, 2, 3]))               // false (数组引用不同)

  // 解决复杂类型的检查
  function includesObject(array, target, key) {
    return array.some(item => item[key] === target[key])
  }

  console.log(includesObject(complexArray, { id: 1, name: 'Alice' }, 'id')) // true

  function includesArray(array, target) {
    return array.some(item => 
      Array.isArray(item) && 
      Array.isArray(target) && 
      item.length === target.length &&
      item.every((val, index) => val === target[index])
    )
  }

  console.log(includesArray(complexArray, [1, 2, 3])) // true
}