七、箭头函数及简写、arguments、剩余参数、展开运算符、解构数组与对象、数组常见方法(forEach、map、join、reduce)

1. 箭头函数

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- 
    箭头函数比函数表达式更简洁的一种写法
    箭头函数更适用于那些本来需要匿名函数的地方,写法更简单
  -->
  <script>
    // 普通函数
    const fn = function () {
      console.log('普通函数')
    }
    fn()

    // 箭头函数
    const fm = () => {
      console.log('箭头函数')
    }
    fm()
    const sum = (x, y) => {
      console.log(x + y)
    }
    sum(1, 2)
  </script>
</body>

</html>

2. 箭头函数简写

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- 
    有且仅有一个形参,可以省略小括号不写
    函数体只有一句代码,可以省略 { } 和 return
    函数体返回对象,需要使用小括号包裹对象
  -->
  <script>
    /* 当箭头函数只有一个参数时,可以省略参数的小括号,
    其余个数不能省略(没有参数也需要写小括号) */
    const fn1 = (x) => {
      console.log(x)
    }
    fn1(1) // 1

    const fn2 = x => {
      console.log(x)
    }
    fn2(2) // 2

    /* 当箭头函数的函数体只有一句代码 可以省略函数体大括号,
    这句代码就是返回值(可以不用写return) */
    const fn3 = (x, y) => {
      return x + y
    }
    console.log(fn3(1, 2)) // 3

    const fn4 = (x, y) => x + y
    console.log(fn4(1, 2)) // 3

    /* 如果返回的是个对象,则需要把对象用小括号包裹 */
    const fn5 = () => {
      return { age: 18 }
    }
    console.log(fn5()) // {age: 18}
    // 未用小括号,返回值为undefined
    const fn6 = () => { age: 18 }
    console.log(fn6()) // undefined
    // 正确写法
    const fn7 = () => ({ age: 18 })
    console.log(fn7()) // {age: 18}

  </script>
</body>

</html>

3. arguments

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- 
    arguments对象(了解)
    arguments 只存在于函数中(但不能在箭头函数中使用)
    arguments 的作用是动态获取函数的实参
    可以通过for循环依次得到传递过来的实参
  -->
  <!-- 
    arguments 是一个伪数组,有长度有索引号
    但是没有 pop() push() 等数组方法
  -->
  <script>
    // 普通函数
    function fn1() {
      console.log(arguments)
      for (let i = 0; i < arguments.length; i++) {
        console.log(arguments[i])
      }
    }
    fn1(1, 4, 6, 7, 23, 35)

    // 箭头函数
    const fn2 = () => {
      console.log(arguments) // 控制台报错 arguments未定义
    }
    fn2()
  </script>
</body>

</html>

4. 剩余参数

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- 
    剩余参数(重点) :用于获取多余的实参,并形成一个真数组(arguments 是伪数组)
    也可以解决形参和实参个数不匹配的问题
  -->
  <!-- 
    ... 是语法符号,置于最末函数形参之前,用于获取多余的实参
    借助 ... 获取的剩余实参,是个真数组
    普通函数和箭头函数中都可以使用
  -->
  <script>
    // 普通函数
    function fn1(x, y, ...other) {
      console.log(x, y)
      console.log(other)
    }
    fn1(1, 4, 6, 7, 23, 35)

    // 箭头函数
    const fn2 = (x, y, ...nums) => {
      console.log(x, y)
      console.log(nums)
    }
    fn2(1, 4, 6, 7, 23, 35)
  </script>
</body>

</html>

5. 展开运算符

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- 
    展开运算符(…),将一个数组/对象进行展开,不会修改原数组
    典型运用场景: 求数组最大值(最小值)、合并数组等
  -->
  <!-- 
    展开运算符 or 剩余参数
    剩余参数:函数参数使用,把多个元素收集起来生成一个真数组 (凝聚)
    展开运算符:将数组展开成各个元素(拆散)
  -->
  <script>
    const arr1 = [1, 4, 6, 5, 23, 46, 67, 56]
    console.log(...arr1) // 1 4 6 5 23 46 67 56
    console.log(Math.max(...arr1)) // 67
    console.log(Math.min(...arr1)) // 1

    const arr2 = [1, 20, 30, 5, 6]

    // 展开运算符 合并数组arr1和arr2
    const arr3 = [...arr1, ...arr2]
    console.log(arr3) // [1, 4, 6, 5, 23, 46, 67, 56, 1, 20, 30, 5, 6]

    // concat 合并数组arr1和arr2
    const arr4 = arr1.concat(arr2)
    console.log(arr4) // [1, 4, 6, 5, 23, 46, 67, 56, 1, 20, 30, 5, 6]
  </script>
</body>

</html>

6. 解构数组

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- 
    解构赋值:
      可以将数组中的值或对象的属性取出,赋值给其他变量
      把一个事物的结构进行拆解
  -->
  <script>
    // 数组解构 右侧数组的值将被赋值给左侧的变量
    const [a, b, c] = [1, 2, 3]
    console.log(a) // 1
    console.log(b) // 2
    console.log(c) // 3

    // 交换两个变量
    // JS中小括号()和中括号[]开头时,括号前需加分号(或加到上行末尾)
    let x = 1
    let y = 2
    console.log(x, y); // 1 2 (此行末尾需加分号)
    [y, x] = [x, y]
    console.log(x, y) // 2 1
  </script>
</body>

</html>

7. 案例1_数组解构

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <script>
    function getValue() {
      // 函数返回值可为多个数据 需用[ , ]包裹
      return [12, 23]
    }
    let arr = getValue()
    const [a, b] = arr
    console.log(a, b) // 12 23

  </script>
</body>

</html>

8. 解构数组_变量和值不匹配时

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- 数组解构:变量和值不匹配的情况 -->
  <script>
    // 1. 变量多值少 多余的变量将被赋值为undefined
    const [a1, b1, c1] = [1, 2]
    console.log(a1, b1, c1) // 1 2 undefined

    // 2. 变量多值少 防止有undefined传递值的情况,可以设置默认值
    const [a2, b2, c2 = 0] = [1, 2]
    console.log(a2, b2, c2) // 1 2 0

    // 3. 变量少值多 多出的值直接忽略
    const [a3, b3] = [1, 2, 3, 4, 5]
    console.log(a3, b3) // 1 2

    // 4. 变量少值多 利用剩余参数(返回为数组)
    const [a4, b4, ...nums] = [1, 2, 3, 4, 5]
    console.log(a4, b4) // 1 2
    console.log(nums) // [3, 4, 5]

    // 5. 按需导入,忽略某些值
    const [a5, b5, , d5] = [1, 2, 3, 4]
    console.log(a5, b5, d5) // 1 2 4

    // 6. 多维数组的解构
    const [a6, [b6, c6]] = [1, [2, 3]]
    console.log(a6, b6, c6) // 1 2 3
  </script>
</body>

</html>

9. 解构对象

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- 对象解构赋值:可以将对象的属性取出,赋值给其他变量 -->
  <!-- 
    注意:
    ➢ 对象的属性名一定要和变量名相同
    ➢ 变量名如果没有和对象属性名相同的则默认是 undefined
    ➢ 注意解构的变量名不要和外面的变量名冲突,否则报错
  -->
  <script>
    const ym = { name: '杨幂', age: 18 }
    const { name, age } = ym
    console.log(name, age) // 杨幂 18
    // name是JS保留字 起名时尽量避开
    // 原名是name,改名后使用旧名name,输出为空

    const pig = { pName: '佩奇', pAge: 6 }
    const { pName: pigName, pAge } = pig
    console.log(pigName, pAge) // 佩奇 6
    console.log(pName) // 报错 pName未定义

  </script>
</body>

</html>

10. 解构对象数组

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <script>
    // 对象数组基本解构方法,后期数组内多个对象时配合遍历解构
    const student = [
      { stuName: 'Tom', age: 18 }
    ]
    const [{ stuName, age }] = student
    console.log(stuName, age) // Tom 18

  </script>
</body>

</html>

11. 解构多级对象

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <script>
    const monkey = {
      mkName: '孙悟空',
      family: {
        teacher: '唐僧',
        brother1: '猪八戒',
        brother2: '沙僧'
      }
    }

    // const { mkName, family } = monkey
    // console.log(mkName, family)
    // 孙悟空 {teacher: '唐僧', brother1: '猪八戒', brother2: '沙僧'}

    const { mkName, family: { brother1, brother2 } } = monkey
    console.log(mkName, brother1, brother2) // 孙悟空 猪八戒 沙僧

  </script>
</body>

</html>

12. 案例2_多级对象解构

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <script>
    const msg = {
      "code": 200,
      "msg": "获取新闻列表成功",
      "data": [
        {
          "id": 1,
          "title": "5G商用自己,三大运用商收入下降",
          "count": 58
        },
        {
          "id": 2,
          "title": "国际媒体头条速览",
          "count": 56
        },
        {
          "id": 3,
          "title": "乌克兰和俄罗斯持续冲突",
          "count": 1669
        },
      ]
    }

    // 传参时,形参也可以解构对象
    function render1({ data }) {
      console.log(data)
    }
    render1(msg)

    // 防止msg里面的data名字混淆,要求渲染函数里面的数据名改为myData
    function render2({ data: myData }) {
      console.log(myData)
    }
    render2(msg)
  </script>
</body>

</html>

13. 案例3_渲染页面(解构)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>商品渲染</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    .list {
      width: 990px;
      margin: 0 auto;
      display: flex;
      flex-wrap: wrap;
      padding-top: 100px;
    }

    .item {
      width: 240px;
      margin-left: 10px;
      padding: 20px 30px;
      transition: all .5s;
      margin-bottom: 20px;
    }

    .item:nth-child(4n) {
      margin-left: 0;
    }

    .item:hover {
      box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
      transform: translate3d(0, -4px, 0);
      cursor: pointer;
    }

    .item img {
      width: 100%;
    }

    .item .name {
      font-size: 18px;
      margin-bottom: 10px;
      color: #666;
    }

    .item .price {
      font-size: 22px;
      color: firebrick;
    }

    .item .price::before {
      content: "¥";
      font-size: 14px;
    }
  </style>
</head>

<body>
  <div class="list">
    <!-- 
      <div class="item">
      <img src="" alt="">
      <p class="name"></p>
      <p class="price"></p>
      </div> 
    -->
  </div>
  <script>
    const goodsList = [
      {
        id: '4001172',
        name: '称心如意手摇咖啡磨豆机咖啡豆研磨机',
        price: '289.00',
        picture: 'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',
      },
      {
        id: '4001594',
        name: '日式黑陶功夫茶组双侧把茶具礼盒装',
        price: '288.00',
        picture: 'https://yanxuan-item.nosdn.127.net/3346b7b92f9563c7a7e24c7ead883f18.jpg',
      },
      {
        id: '4001009',
        name: '竹制干泡茶盘正方形沥水茶台品茶盘',
        price: '109.00',
        picture: 'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',
      },
      {
        id: '4001874',
        name: '古法温酒汝瓷酒具套装白酒杯莲花温酒器',
        price: '488.00',
        picture: 'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',
      },
      {
        id: '4001649',
        name: '大师监制龙泉青瓷茶叶罐',
        price: '139.00',
        picture: 'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',
      },
      {
        id: '3997185',
        name: '与众不同的口感汝瓷白酒杯套组1壶4杯',
        price: '108.00',
        picture: 'https://yanxuan-item.nosdn.127.net/8e21c794dfd3a4e8573273ddae50bce2.jpg',
      },
      {
        id: '3997403',
        name: '手工吹制更厚实白酒杯壶套装6壶6杯',
        price: '99.00',
        picture: 'https://yanxuan-item.nosdn.127.net/af2371a65f60bce152a61fc22745ff3f.jpg',
      },
      {
        id: '3998274',
        name: '德国百年工艺高端水晶玻璃红酒杯2支装',
        price: '139.00',
        picture: 'https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg',
      },
    ]

    let str = ''
    /* for (let i = 0; i < goodsList.length; i++) {
      str += `
          <div class="item">
          <img src="${goodsList[i].picture}" alt="">
          <p class="name">${goodsList[i].name}</p>
          <p class="price">${goodsList[i].price}</p>
          </div>
        `
    } */
    for (let i = 0; i < goodsList.length; i++) {
      // 解构对象
      const { name, price, picture } = goodsList[i]
      str += `
          <div class="item">
          <img src="${picture}" alt="">
          <p class="name">${name}</p>
          <p class="price">${price}</p>
          </div>
        `
    }
    document.querySelector('.list').innerHTML = str
  </script>
</body>

</html>

14. forEach遍历数组

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- forEach遍历数组元素 不返回数组 -->
  <script>
    const names = ['Tom', 'Jerry', 'Taylor']
    names.forEach((el, index) => {
      /* 
        element是数组元素,简写为el
        index是数组元素的索引号
      */
      console.log(el, index)
    })
    /*
      Tom 0
      Jerry 1
      Taylor 2
    */
  </script>
</body>

</html>

15. map迭代数组

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- map迭代数组 遍历数组处理数据,并且返回新的数 -->
  <!-- 
    map 也称为映射。映射指两个元素的集之间元素相互“对应”的关系。
    map重点在于有返回值,forEach没有返回值(undefined)
  -->
  <script>
    const myColor1 = ['红', '绿', '蓝']
    console.log(myColor1) // ['红', '绿', '蓝']

    const myColor2 = myColor1.map((el, index) => {
      return el + '色'
    })
    console.log(myColor2) // ['红色', '绿色', '蓝色']

  </script>
</body>

</html>

16. join拼接数组元素

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- join拼接数组元素 用于把数组中的所有元素连接成一个字符串 -->
  <script>
    const myColor = ['红色', '绿色', '蓝色']
    console.log(myColor.join('')) // 红色绿色蓝色
    console.log(myColor.join('--')) // 红色--绿色--蓝色
  </script>
</body>

</html>

17. 案例4_渲染页面(map+join)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>商品渲染</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    .list {
      width: 990px;
      margin: 0 auto;
      display: flex;
      flex-wrap: wrap;
      padding-top: 100px;
    }

    .item {
      width: 240px;
      margin-left: 10px;
      padding: 20px 30px;
      transition: all .5s;
      margin-bottom: 20px;
    }

    .item:nth-child(4n) {
      margin-left: 0;
    }

    .item:hover {
      box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
      transform: translate3d(0, -4px, 0);
      cursor: pointer;
    }

    .item img {
      width: 100%;
    }

    .item .name {
      font-size: 18px;
      margin-bottom: 10px;
      color: #666;
    }

    .item .price {
      font-size: 22px;
      color: firebrick;
    }

    .item .price::before {
      content: "¥";
      font-size: 14px;
    }
  </style>
</head>

<body>
  <div class="list">
    <!-- 
      <div class="item">
      <img src="" alt="">
      <p class="name"></p>
      <p class="price"></p>
      </div> 
    -->
  </div>
  <script>
    const goodsList = [
      {
        id: '4001172',
        name: '称心如意手摇咖啡磨豆机咖啡豆研磨机',
        price: '289.00',
        picture: 'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',
      },
      {
        id: '4001594',
        name: '日式黑陶功夫茶组双侧把茶具礼盒装',
        price: '288.00',
        picture: 'https://yanxuan-item.nosdn.127.net/3346b7b92f9563c7a7e24c7ead883f18.jpg',
      },
      {
        id: '4001009',
        name: '竹制干泡茶盘正方形沥水茶台品茶盘',
        price: '109.00',
        picture: 'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',
      },
      {
        id: '4001874',
        name: '古法温酒汝瓷酒具套装白酒杯莲花温酒器',
        price: '488.00',
        picture: 'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',
      },
      {
        id: '4001649',
        name: '大师监制龙泉青瓷茶叶罐',
        price: '139.00',
        picture: 'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',
      },
      {
        id: '3997185',
        name: '与众不同的口感汝瓷白酒杯套组1壶4杯',
        price: '108.00',
        picture: 'https://yanxuan-item.nosdn.127.net/8e21c794dfd3a4e8573273ddae50bce2.jpg',
      },
      {
        id: '3997403',
        name: '手工吹制更厚实白酒杯壶套装6壶6杯',
        price: '99.00',
        picture: 'https://yanxuan-item.nosdn.127.net/af2371a65f60bce152a61fc22745ff3f.jpg',
      },
      {
        id: '3998274',
        name: '德国百年工艺高端水晶玻璃红酒杯2支装',
        price: '139.00',
        picture: 'https://yanxuan-item.nosdn.127.net/8896b897b3ec6639bbd1134d66b9715c.jpg',
      },
    ]

    const goodsList1 = goodsList.map((el, index) => {
      const { picture, name, price } = el
      return `
        <div div class="item" >
          <img src="${picture}" alt="">
          <p class="name">${name}</p>
          <p class="price">${price}</p>
        </div>
      `
    })
    console.log(goodsList1) // goodsList1现为字符串数组
    // console.log(goodsList1.join(''))

    document.querySelector('.list').innerHTML = goodsList1.join('')

  </script>
</body>

</html>

18. reduce累计器

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <!-- reduce累计器 返回累计处理的结果,经常用于求和等 -->
  <!-- arr.reduce(function(上一次值,当前值){},初始值) -->
  <!-- 
    reduce 执行过程:
      1.如果有起始值,则把初始值累加到里面;
        如果没有起始值, 则上一次值以数组的第一个数组元素的值
      2.每一次循环,把返回值给做为 下一次循环的上一次值
      3.如果有起始值,则 起始值做为上一次值
  -->
  <script>
    // 1. 数组
    const arr = [10, 20, 30]
    const sum1 = arr.reduce((prev, current) => {
      return prev + current
    })
    console.log(sum1) // 60

    const sum2 = arr.reduce((prev, current) => {
      return prev + current
    }, 100)
    console.log(sum2) // 160

    // 2. 对象数组(对象数组.reduce 必须写初始值)
    const Peason = [
      {
        name: '张三',
        salary: 10000
      }, {
        name: '李四',
        salary: 15000
      }, {
        name: '王五',
        salary: 20000
      }
    ]
    // 未设初始值(错误)
    const salary1 = Peason.reduce((prev, current) => {
      return prev + current.salary
    })
    console.log(salary1) // [object Object]1500020000
    // 设置初始值
    const salary2 = Peason.reduce((prev, current) => {
      return prev + current.salary
    }, 0)
    console.log(salary2) // 45000
  </script>
</body>

</html>

19. 案例5_购物车

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    .list {
      width: 990px;
      margin: 100px auto 0;
    }

    .item {
      padding: 15px;
      transition: all 0.5s;
      display: flex;
      border-top: 1px solid #e4e4e4;
    }

    .item:nth-child(4n) {
      margin-left: 0;
    }

    .item:hover {
      cursor: pointer;
      background-color: #f5f5f5;
    }

    .item img {
      width: 80px;
      height: 80px;
      margin-right: 10px;
    }

    .item .name {
      font-size: 18px;
      margin-right: 10px;
      color: #333;
      flex: 2;
    }

    .item .name .tag {
      display: block;
      padding: 2px;
      font-size: 12px;
      color: #999;
    }

    .item .price,
    .item .sub-total {
      font-size: 18px;
      color: firebrick;
      flex: 1;
    }

    .item .price::before,
    .item .sub-total::before,
    .amount::before {
      content: '¥';
      font-size: 12px;
    }

    .item .spec {
      flex: 2;
      color: #888;
      font-size: 14px;
    }

    .item .count {
      flex: 1;
      color: #aaa;
    }

    .total {
      width: 990px;
      margin: 0 auto;
      display: flex;
      justify-content: flex-end;
      border-top: 1px solid #e4e4e4;
      padding: 20px;
    }

    .total .amount {
      font-size: 18px;
      color: firebrick;
      font-weight: bold;
      margin-right: 50px;
    }
  </style>
</head>

<body>
  <div class="list">
    <!-- <div class="item">
      <img src="https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg" alt="">
      <p class="name">称心如意手摇咖啡磨豆机咖啡豆研磨机 </p>
      <p class="price">289.90</p>
      <p class="count">x2</p>
      <p class="sub-total">579.80</p>
    </div> -->
  </div>
  <div class="total">
    <div>
      合计:
      <span class="amount">1000.00</span>
    </div>
  </div>
  <script>
    const goodsList = [
      {
        id: '4001172',
        name: '称心如意手摇咖啡磨豆机咖啡豆研磨机',
        price: 289.9,
        picture:
          'https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg',
        count: 2,
        spec: { color: '白色' },
      },
      {
        id: '4001009',
        name: '竹制干泡茶盘正方形沥水茶台品茶盘',
        price: 109.8,
        picture:
          'https://yanxuan-item.nosdn.127.net/2d942d6bc94f1e230763e1a5a3b379e1.png',
        count: 3,
        spec: { size: '40cm*40cm', color: '黑色' },
      },
      {
        id: '4001874',
        name: '古法温酒汝瓷酒具套装白酒杯莲花温酒器',
        price: 488,
        picture:
          'https://yanxuan-item.nosdn.127.net/44e51622800e4fceb6bee8e616da85fd.png',
        count: 1,
        spec: { color: '青色', sum: '一大四小' },
        gift: '500g茶叶,羽毛球',
      },
      {
        id: '4001649',
        name: '大师监制龙泉青瓷茶叶罐',
        price: 139,
        picture:
          'https://yanxuan-item.nosdn.127.net/4356c9fc150753775fe56b465314f1eb.png',
        count: 2,
        spec: { size: '小号', color: '紫色' },
        gift: '50g茶叶,清洗球',
      },
    ]

    // 数字转字符串 toFixed(保留小数位数) 默认不保留 四舍五入
    let str = goodsList.map((el, index) => {
      const { name, price, picture, count } = el
      return `
        <div class="item">
          <img src="${picture}" alt="">
          <p class="name">${name}</p>
          <p class="price">${price.toFixed(2)}</p>
          <p class="count">x${count}</p>
          <p class="sub-total">${(price * count).toFixed(2)}</p>
        </div>
      `
    }).join('')
    document.querySelector('.list').innerHTML = str

    let amount = goodsList.reduce((prev, current) => {
      return prev + current.count * current.price
    }, 0)
    document.querySelector('.amount').innerHTML = amount.toFixed(2)
  </script>
</body>

</html>

20. 作业

20.1 确认订单页面

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Document</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    a {
      text-decoration: none;
    }

    .xtx-cart-page .container {
      width: 1200px;
      margin: 50px auto;
      border: 3px solid #ccc;
    }

    .xtx-cart-page h3 {
      text-align: center;
      font-size: 30px;
      margin: 20px 0;
    }

    .tc {
      text-align: center;
    }

    .tc .xtx-numbox {
      margin: 0 auto;
      width: 120px;
    }

    .red {
      color: #db2828;
    }

    .green {
      color: #32aa66;
    }

    .f16 {
      font-size: 16px;
    }

    .goods {
      display: flex;
      align-items: center;
    }

    .goods img {
      width: 100px;
      height: 100px;
    }

    .goods>div {
      width: 280px;
      font-size: 16px;
      padding-left: 10px;
    }

    .goods>div .attr {
      font-size: 14px;
      color: #999;
    }

    .action {
      display: flex;
      background: #fff;
      margin-top: 20px;
      height: 80px;
      align-items: center;
      font-size: 16px;
      justify-content: space-between;
      padding: 0 30px;
    }

    .action .xtx-checkbox {
      color: #999;
    }

    .action .batch a {
      margin-left: 20px;
    }

    .action .red {
      font-size: 18px;
      margin-right: 20px;
      font-weight: bold;
    }

    .tit {
      color: #666;
      font-size: 16px;
      font-weight: normal;
      line-height: 50px;
    }

    .xtx-cart-page .cart {
      background: #fff;
      color: #666;
    }

    .xtx-cart-page .cart table {
      border-spacing: 0;
      border-collapse: collapse;
      line-height: 24px;
    }

    .xtx-cart-page .cart table th,
    .xtx-cart-page .cart table td {
      padding: 10px;
      border-bottom: 1px solid #f5f5f5;
    }

    .xtx-cart-page .cart table th:first-child,
    .xtx-cart-page .cart table td:first-child {
      text-align: left;
      padding-left: 30px;
      color: #999;
    }

    .xtx-cart-page .cart table th {
      font-size: 16px;
      font-weight: normal;
      line-height: 50px;
    }

    .box {
      width: 1200px;
      margin: 0 auto;
    }

    .box p {
      height: 30px;
      line-height: 30px;
    }
  </style>
</head>

<body>
  <!-- ---------------------- 题目区域 --------------------------- -->
  <div class="box">
    <p>题目说明:</p>
    <p>1. 基于 arr(代码中已准备) 渲染下面购物车列表</p>
    <p>2. 基于 arr 计算 底部总价 和 总数量</p>
    <p>3. 实现 删除功能</p>
  </div>

  <!-- ---------------------- 代码区域 ---------------------------- -->
  <div class="xtx-cart-page">
    <div class="container">
      <div class="cart">
        <h3>确认订单</h3>
        <table>
          <thead>
            <tr>
              <th width="120">序号</th>
              <th width="400">商品信息</th>
              <th width="220">单价</th>
              <th width="180">数量</th>
              <th width="180">小计</th>
              <th width="140">操作</th>
            </tr>
          </thead>
          <!-- 商品列表 -->
          <tbody>
            <tr>
              <td>1</td>
              <td>
                <div class="goods">
                  <a href="#/"><img src="https://yanxuan-item.nosdn.127.net/6aaff130c1d97c60f9931e00734bbad6.png"
                      alt=""></a>
                  <div>
                    <p class="name ellipsis">
                      共享品茶乐趣公道杯闻香杯手工吹制
                    </p>
                    <p class="attr">规格:公道杯230ml/手工吹制</p>
                  </div>
                </div>
              </td>
              <td class="tc">
                <p>¥89.00</p>
              </td>
              <td class="tc">10</td>
              <td class="tc">
                <p class="f16 red">¥890.00</p>
              </td>
              <td class="tc">
                <p><a class="green" href="javascript:;" onclick="del()">删除</a></p>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
      <!-- 操作栏 -->
      <div class="action">
        <div class="batch"></div>
        <div class="total">
          共 9 件商品,商品合计:
          <span class="red">¥1800</span>
        </div>
      </div>
    </div>
  </div>

  <script>
    const arr = [
      {
        id: '1652038',
        attrsText: '规格:公道杯230ml/手工吹制',
        name: '共享品茶乐趣公道杯闻香杯手工吹制',
        price: '89.00',
        picture:
          'https://yanxuan-item.nosdn.127.net/6aaff130c1d97c60f9931e00734bbad6.png',
        count: 10,
      },
      {
        id: '1096001',
        attrsText: '规格:不锈钢除味皂',
        name: '祛味除腥神器,不锈钢除味皂',
        price: '9.90',
        picture:
          'https://yanxuan-item.nosdn.127.net/b38f9ac476ec494235f4aa80fc8e198c.png',
        count: 1,
      },
      {
        id: '3446012',
        attrsText: '颜色:芭比粉-老款',
        name: '一锅包揽煎烤蒸煮日本爱丽思多功能料理锅',
        price: '299.00',
        picture:
          'https://yanxuan-item.nosdn.127.net/667dbc276e46e31b5a00869b9b1b8ef3.png',
        count: 2,
      },
      {
        id: '1652037',
        attrsText: '规格:黑白对杯',
        name: '茶水分离杯耐热隔热玻璃杯',
        price: '188.00',
        picture:
          'https://yanxuan-item.nosdn.127.net/a09de222ed32efa8ffe359b1d5780574.jpg',
        count: 5,
      },
      {
        id: '3504000',
        name: '儿童防污/防蚊T恤110cm',
        attrsText: '颜色:白色草莓(防污) 尺码:160cm',
        price: '89.00',
        picture:
          'https://yanxuan-item.nosdn.127.net/f899c55f36cb74232abb349234d9e676.png',
        count: 4,
      },
    ]

    function render() {
      const tbody = document.querySelector('.cart tbody')
      const action = document.querySelector('.action')

      // 利用map+join渲染数据到页面上
      const str = arr.map((el, index) => {
        const { name, attrsText, price, picture, count } = el
        return `
          <tr>
            <td>${index + 1}</td>
            <td>
              <div class="goods">
                <a href="#/"><img src="${picture}"
                    alt=""></a>
                <div>
                  <p class="name ellipsis">
                  ${name}}
                  </p>
                  <p class="attr">${attrsText}</p>
                </div>
              </div>
            </td>
            <td class="tc">
              <p>¥${price}</p>
            </td>
            <td class="tc">${count}</td>
            <td class="tc">
              <p class="f16 red">¥${(price * count).toFixed(2)}</p>
            </td>
            <td class="tc">
              <p><a class="green" href="javascript:;" onclick="del(${index})">删除</a></p>
            </td>
          </tr>
        `
      }).join('')
      // document.querySelector('.cart tbody').innerHTML = str
      tbody.innerHTML = str

      // 利用reduce来求和
      // 箭头函数 省略大括号和return
      const totalCount = arr.reduce((prev, current) => prev + current.count, 0)
      const totalPrice = arr.reduce((prev, current) => prev + current.count * current.price, 0)
      /* const totalCount = arr.reduce((prev, current) => {
        return prev + current.count
      }, 0)
      const totalPrice = arr.reduce((prev, current) => {
        return prev + current.count * current.price
      }, 0).toFixed(2) */

      action.innerHTML = `
        <div class="batch"></div>
        <div class="total">
          共 ${totalCount} 件商品,商品合计:
        <span class="red">¥${totalPrice.toFixed(2)}</span>
        </div>
      `
      /* document.querySelector('.total').innerHTML = `
        共 ${totalCount} 件商品,商品合计:
        <span class="red">¥${totalPrice.toFixed(2)}</span>
      ` */
    }
    render()

    // 利用splice来删除数据
    function del(index) {
      arr.splice(index, 1)
      render()
    }

  </script>
</body>

</html>

20.2 水果列表_二次开发题

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link rel="stylesheet" href="./css/inputnumber.css" />
  <link rel="stylesheet" href="./css/index.css" />
  <title>购物车</title>
</head>

<body>
  <div class="app-container" id="app">
    <!-- 顶部banner -->
    <div class="banner-box"><img src="./img/fruit.jpg" alt="" /></div>
    <!-- 面包屑 -->
    <div class="breadcrumb">
      <span>🏠</span>
      /
      <span>购物车</span>
    </div>
    <!-- 购物车主体 -->
    <div class="main">
      <div class="table">
        <!-- 头部 -->
        <div class="thead">
          <div class="tr">
            <div class="th">选中</div>
            <div class="th th-pic">图片</div>
            <div class="th">单价</div>
            <div class="th num-th">个数</div>
            <div class="th">小计</div>
            <div class="th">操作</div>
          </div>
        </div>
        <!-- 身体 -->
        <div class="tbody">
          <div class="tr active">
            <div class="td"><input type="checkbox" checked /></div>
            <div class="td"><img src="./img/火龙果.png" alt="" /></div>
            <div class="td">6</div>
            <div class="td">
              <div class="my-input-number">
                <button class="decrease"> - </button>
                <span class="my-input__inner">2</span>
                <button class="increase"> + </button>
              </div>
            </div>
            <div class="td">12</div>
            <div class="td"><a href="javascript:;" onclick="del(0)">删除</a></div>
          </div>
          <!-- 需要渲染的列表 核心代码区域 -->
          <div class="tr">
            <div class="td"><input type="checkbox" /></div>
            <div class="td"><img src="./img/荔枝.png" alt="" /></div>
            <div class="td">7</div>
            <div class="td">
              <div class="my-input-number">
                <button disabled class="decrease"> - </button>
                <span class="my-input__inner">1</span>
                <button class="increase"> + </button>
              </div>
            </div>
            <div class="td">14</div>
            <div class="td"><a href="javascript:;" onclick="del(0)">删除</a></div>
          </div>
        </div>
      </div>
      <!-- 底部 -->
      <div class="bottom">
        <!-- 全选 -->
        <label class="check-all">
          <input type="checkbox" />
          全选
        </label>
        <div class="right-box">
          <!-- 所有商品总价 -->
          <span class="price-box">总价&nbsp;&nbsp;:&nbsp;&nbsp;¥&nbsp;<span class="price">24</span></span>
          <!-- 结算按钮 -->
          <button class="pay">结算( 6 )</button>
        </div>
      </div>
    </div>
    <!-- 空车 -->
    <div class="empty">🛒空空如也</div>
  </div>
  <script>
    const fruit = [
      {
        icon: './img/火龙果.png',
        num: 2,
        price: 6,
      },
      {
        icon: './img/荔枝.png',
        num: 7,
        price: 20,
      },
      {
        icon: './img/榴莲.png',
        num: 3,
        price: 40,
      },
      {
        icon: './img/鸭梨.png',
        num: 10,
        price: 3,
      },
      {
        icon: './img/樱桃.png',
        num: 20,
        price: 34,
      }
    ]

    function render() {
      // 渲染购物车列表数据,使用map+join配合实现
      /* const str = fruit.map((el, index) => {
        const { icon, num, price } = el */
      const str = fruit.map(({ icon, num, price }, index) => {
        return `
          <div class="tr">
            <div class="td"><input type="checkbox" /></div>
            <div class="td"><img src="${icon}" alt="" /></div>
            <div class="td">${price}</div>
            <div class="td">
              <div class="my-input-number">
                <button disabled class="decrease"> - </button>
                <span class="my-input__inner">${num}</span>
                <button class="increase"> + </button>
              </div>
            </div>
            <div class="td">${(price * num)}</div>
            <div class="td"><a href="javascript:;" onclick="del(${index})">删除</a></div>
          </div>
        `
      }).join('')
      document.querySelector('.tbody').innerHTML = str

      // 求和功能用reduce实现
      /* const Price = fruit.reduce((prev, current) => {
        return prev + current.price * current.num
      }, 0)
      const Count = fruit.reduce((prev, current) => {
        return prev + current.num
      }, 0) */
      const Price = fruit.reduce((prev, current) => prev + current.price * current.num, 0)
      const Count = fruit.reduce((prev, current) => prev + current.num, 0)
      document.querySelector('.right-box').innerHTML = `
        <span class="price-box">总价&nbsp;&nbsp;:&nbsp;&nbsp;¥&nbsp;<span class="price">${Price}</span></span>
        <button class="pay">结算( ${Count} )</button>
      `
    }
    render()

    function del(index) {
      fruit.splice(index, 1)
      render()
    }
  </script>
</body>

</html>

20.3 暂时性锁区

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <!-- 暂时性死区 -->
  <!-- 在代码块内,使用let命令声明变量之前,该变量都是不可用的。
    这在语法上,称为“暂时性死区” -->
  <script>
    let tmp = 123

    if (true) {
      tmp = 'abc'
      console.log(tmp) // 报错:在初始化之前无法访问'tmp'
      let tmp
    }
  </script>
</body>

</html>
<think>嗯,用户现在问的是JavaScript中的动态参数arguments,以及它只在函数中存在,而且箭头函数里没有这个特性。首先,我需要确认自己对这个知识点的理解是否正确。arguments对象确实是一个在普通函数内部自动可用的伪数组,它包含了调用函数时传入的所有参数。而箭头函数没有自己的arguments对象,这点需要明确。 接下来,用户可能是在学习函数相关的内容,遇到了arguments的使用问题,或者在使用箭头函数时发现无法访问arguments。需要解释清楚两者的区别,可能还需要举例子说明。此外,用户可能想知道为什么箭头函数没有arguments,是否有替代方案,比如剩余参数语法。 要确保回答结构清晰,分点说明。先介绍arguments的定义和特点,然后对比箭头函数的情况,再给出示例代码,帮助用户理解差异。同时,提醒用户在使用箭头函数时应该用剩余参数来代替arguments,这样可以避免混淆和错误。 另外,用户之前的问题是关于函数声明和表达式的执行顺序,现在转向arguments,可能是在深入学习函数的不同特性。需要保持回答的连贯性,可能的话,将两者联系起来,比如在讨论函数内部变量时提到arguments的存在。 还要注意用户可能对伪数组的概念不太清楚,需要解释arguments虽然类似数组,但没有数组方法,比如push或pop,但可以通过转换变成真正的数组,比如使用Array.from或者展开运算符。 最后,检查是否有常见的误区,比如在箭头函数中误用arguments,导致引用外层的arguments,这种情况需要举例说明,避免用户犯错。确保回答准确,并且覆盖用户可能存在的疑问点。</think>### 一、`arguments` 的核心特性 #### 1. **定义基本行为** - **伪数组对象**:`arguments` 是 JavaScript 函数内部自动创建的 **类数组对象**(非真正数组),存储了调用函数时传入的所有参数。 - **仅存在于普通函数**:仅在 `function` 定义的函数中可用,**箭头函数中没有**。 - **索引属性**: ```javascript function sum(a, b) { console.log(arguments[0]); // 输出第一个参数(a的值) console.log(arguments[1]); // 输出第二个参数(b的值) console.log(arguments.length); // 输出参数总数 } sum(3, 5); ``` #### 2. **关键特性对比** | 特性 | 普通函数(`function`) | 箭头函数 | |---------------------|-------------------------------------|----------------------------| | **`arguments`存在性** | ✅ 自动创建 | ❌ 无 | | **参数绑定关系** | 形参**动态关联**(修改相互影响) | 无此机制 | | **作用域来源** | 自身函数的参数 | 引用外层普通函数的`arguments`(若存在) | --- ### 二、`arguments` 的典型使用场景 #### 1. **获取所有参数(无视形参数量)** ```javascript function logArgs() { for (let i = 0; i < arguments.length; i++) { console.log(`参数 ${i}: ${arguments[i]}`); } } logArgs("a", 100, true); // 输出全部参数 ``` #### 2. **动态参数处理(如参数数量不定)** ```javascript function dynamicMultiply() { let result = 1; for (const num of arguments) { result *= num; } return result; } console.log(dynamicMultiply(2, 3, 4)); // 输出24 ``` #### 3. **形参`arguments`的关联性** ```javascript function updateParam(x) { arguments[0] = 100; // 修改arguments会影响形参x console.log(x); // 输出100(非原始传入值) } updateParam(5); ``` --- ### 三、箭头函数中`arguments`的缺失替代方案 #### 1. **箭头函数直接访问`arguments`会报错** ```javascript const arrowFn = () => { console.log(arguments); // ReferenceError: arguments is not defined }; arrowFn(); ``` #### 2. **间接获取外层`arguments`(需谨慎)** ```javascript function outer() { const inner = () => { console.log(arguments); // 输出outer函数的arguments }; inner(); } outer(10, 20); // 输出Arguments对象 { 0:10, 1:20 } ``` #### 3. **正确替代方案:剩余参数(Rest Parameters)** ```javascript const arrowSum = (...args) => { // 使用剩余参数语法 return args.reduce((acc, val) => acc + val, 0); }; console.log(arrowSum(1, 2, 3)); // 输出6 ``` --- ### 四、`arguments` 的局限性及优化 #### 1. **伪数组的缺陷** - **无法直接使用数组方法**: ```javascript function checkArgs() { arguments.push(4); // TypeError: arguments.push is not a function } checkArgs(1, 2, 3); ``` - **转换方法**: ```javascript function convertToArray() { const arr = Array.from(arguments); // 方法1:Array.from转换 // 或 const arr2 = [...arguments]; // 方法2:展开运算符 arr.push(4); // 正常操作 } ``` #### 2. **现代JavaScript的替代建议** | 场景 | `arguments` 方案 | 更优方案(ES6+) | |--------------------|----------------------------------|----------------------------------| | **获取所有参数** | `function fn() { arguments }` | `const fn = (...args) => { ... }` | | **参数数量不定** | 遍历`arguments` | 直接操作剩余参数数组`args` | | **参数类型检查** | `typeof arguments[0]` | 使用解构赋值+类型校验 | --- ### 五、关键问题详解 #### 1. **为什么箭头函数没有`arguments`?** - 箭头函数设计目标为 **简洁的语法** 和 **词法作用域绑定**,移除`arguments`可避免以下问题: - **隐式依赖外部作用域**(如意外引用外层`arguments`) - **内存占用优化**(无需为每个箭头函数创建`arguments`对象) #### 2. **如何判断代码是否误用`arguments`?** - **ESLint规则**:启用 [`prefer-rest-params`](https://eslint.org/docs/rules/prefer-rest-params) 规则,强制使用剩余参数替代`arguments`: ```javascript /* eslint prefer-rest-params: "error" */ function oldStyle() { console.log(arguments); // ESLint报错提示 } ``` #### 3. **`arguments`剩余参数的对比** | 对比维度 | `arguments` | 剩余参数(`...args`) | |---------------|-------------------------|----------------------------| | **类型** | 类数组对象 | 真正数组 | | **形参关联** | 动态绑定形参 | 独立存储参数 | | **箭头函数** | 不可用 | 可用 | | **可读性** | 较低(隐式特性) | 更高(显式声明) | --- ### 总结 - **普通函数**:合理使用 `arguments` 处理动态参数,但需注意其伪数组特性和作用域限制。 - **箭头函数**:**禁止使用 `arguments`**,改用剩余参数(`...args`)实现相同功能。 - **迁移建议**:在新项目中优先使用剩余参数,旧代码逐步替换以提升可维护性。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值