JavaScript进阶第一天【转载】【重点标注】【手动补充】


✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
✅✅✅✅✅✅✅✅黑马程序员B站视频链接❎❎❎❎❎❎❎❎
❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎❎

🈵🔞🈲博主手动补充

在这里插入图片描述
在这里插入图片描述
这里和C是反的
对于C:outer=函数名=函数地址,fun=指针,fun()=调用函数
对于JavaScript:fun是弱数据类型,outer()可以直接赋给fun,fun()=调用函数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
学这个知识点,是想补充Python知识学习的,
动态参数是函数内置的,是伪数组,arguments没有数组的对象方法,不推荐使用
剩余参数,是真数组,有数组的对象方法,推荐使用
展开运算符,和剩余参数长的一样,但是剩余参数只存在于函数中

(箭头函数重要),待补充吧,不想看了

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

数组解构这块知识建议看PPT,很详细

  1. 数组解构是为了快速批量赋给新的变量,类似于C的新定义一个变量,但是C不快速,且语法死板单一
  2. 数组解构可以结合上面学过的…剩余参数使用
  3. 数组解构可以快速用于变量交换(这里需要加个;,具体可看视频),C只能通过第三方临时变量来交换
  4. 支持定义默认值,支持多维数组,和Python太像了
  5. 数组解构的语法很宽泛,感官上觉得可以的语法,那么它就可以使用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
对象解构,对象有点像C的结构体,然后把对象里面的属性和方法快速赋值给新的变量叫做对象解构,数组对象解构,对象对象=多级对象解构
在这里插入图片描述
JavaScript语法宽泛,无限套娃,有点像C的结构体套结构体,如果实现类似的效果,只能通过结构体指针(一级或者二级就复杂了)来实现,在这里JavaScript中,使用了多级对象解构来引用了msg对象里面的data属性的值(这个值是数组对象)
在这里插入图片描述

综合案例(解释)

<!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;
    }

    .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;
    }

    .filter {
      display: flex;
      width: 990px;
      margin: 0 auto;
      padding: 50px 30px;
    }

    .filter a {
      padding: 10px 20px;
      background: #f5f5f5;
      color: #666;
      text-decoration: none;
      margin-right: 20px;
    }

    .filter a:active,
    .filter a:focus {
      background: #05943c;
      color: #fff;
    }
  </style>
</head>

<body>
  <div class="filter">
    <a data-index="1" href="javascript:;">0-100</a>
    <a data-index="2" href="javascript:;">100-300</a>
    <a data-index="3" href="javascript:;">300元以上</a>
    <a href="javascript:;">全部区间</a>
  </div>
  <div class="list">
    <!-- <div class="item">
      <img src="" alt="">
      <p class="name"></p>
      <p class="price"></p>
    </div> -->
  </div>
  <script>
    // 2. 初始化数据
    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: '100.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',
      },
    ]

    // 1. 渲染函数  封装
    function render(arr) {
      // 声明空字符串
      let str = ''
      // 遍历数组 
      arr.forEach(item => {
        // 解构
        const { name, picture, price } = item
        str += `
         <div class="item">
          <img src=${picture} alt="">
          <p class="name">${name}</p>
          <p class="price">${price}</p>
        </div> 
        `
      })
      // 追加给list 
      document.querySelector('.list').innerHTML = str
    }
    render(goodsList)  // 页面一打开就需要渲染

    // 2. 过滤筛选  
    document.querySelector('.filter').addEventListener('click', e => {
      // e.target.dataset.index   e.target.tagName
      const { tagName, dataset } = e.target
      // 判断 
      if (tagName === 'A') {
        // console.log(11) 
        // arr 返回的新数组
        let arr = goodsList
        if (dataset.index === '1') {
          arr = goodsList.filter(item => item.price > 0 && item.price <= 100)
        } else if (dataset.index === '2') {
          arr = goodsList.filter(item => item.price >= 100 && item.price <= 300)
        } else if (dataset.index === '3') {
          arr = goodsList.filter(item => item.price >= 300)
        }
        // 渲染函数
        render(arr)
      }
    })
  </script>
</body>

</html>

在这里插入图片描述

<head>中的<title>

<title>商品渲染</title>

这行代码的作用就是上图所示

类的*

    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

在CSS中,* 是一个特殊的符号,被称为通配符选择器。它的作用是选择页面上的所有元素。当你对 * 应用样式规则时,这些规则会应用到HTML文档中的每一个元素上。

类的.

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

在CSS(层叠样式表)中,. 是一个类选择器(class selector)的前缀。当你看到一个CSS规则集以 . 开头,后跟一个或多个字母、数字或连字符组成的名称时(在本例中是 .item),这意味着该规则集将应用于HTML文档中所有具有指定类名的元素。

<head>与<body>

在HTML(HyperText Markup Language,超文本标记语言)文档中,和是两个非常重要的结构标签,它们各自承担着不同的功能和角色。以下是它们之间的主要区别:

一、定义与位置

<head>标签:
定义:<head>标签用于包含文档的元数据(metadata),即关于文档的信息,这些信息不会直接显示在浏览器页面中。
位置:在HTML文档中,<head>标签通常位于<html>标签内,并紧跟在<html>标签之后,位于<body>标签之前。
<body>标签:
定义:<body>标签包含页面的可视内容,即用户在浏览器中可以看到的部分。
位置:在HTML文档中,<body>标签位于<head>标签之后,是文档的主体部分。

二、内容与作用

<head>标签中的内容:
元数据:包括文档的标题(<title>)、字符集声明、样式表链接(<link>)、脚本(<script>)、以及其他与页面相关的配置信息(如<meta>标签)。
这些信息主要用于配置页面、提供页面描述、引入外部资源等,对页面的渲染和搜索引擎优化(SEO)有重要影响。
<body>标签中的内容:
可视内容:包括所有的文本、图像、链接、表格、表单元素等,这些内容是用户在浏览器中直接看到的。
<body>标签内的内容决定了页面的布局、样式和交互性。
三、使用注意事项
<head>标签:
应尽量保持简洁,只包含必要的元数据。
避免在<head>标签中放置过多的脚本或样式表,以免影响页面加载速度。
<body>标签:
应包含页面的所有可视内容,并确保这些内容结构清晰、易于理解。
注意使用CSS和JavaScript来增强页面的样式和交互性,但要避免过度使用,以免影响页面性能。

class

  <div class="filter">
    <a data-index="1" href="javascript:;">0-100</a>
    <a data-index="2" href="javascript:;">100-300</a>
    <a data-index="3" href="javascript:;">300元以上</a>
    <a href="javascript:;">全部区间</a>
  </div>

这个filter就是定义的类名,在中可以对这个class进行参数的设置

<div>

DIV的全称是DIVision,意为“划分”或“分割”。在HTML(标准通用标记语言下的一个应用)中,DIV元素是用来为文档内大块(block-level)的内容提供结构和背景的元素,可以定义文档中的分区或节(division/section)。

标签是一个块级元素,被称为分割标签,表示一块可以显示HTML的区域,用来设置字、图片、表格等的摆放位置。在使用CSS进行页面布局和样式设计时,DIV标签是不可或缺的元素,它可以帮助构建出清晰、有序的网页结构。

<!-- 和 -->

在这个HTML代码片段中, 是HTML的注释标记。它们之间的内容不会被浏览器显示或执行,而是作为开发者留下的说明或备注。

arr.forEach和item

在这里插入图片描述
在这里插入图片描述

      arr.forEach(item => {
        // 解构
        const { name, picture, price } = item
        str += `
         <div class="item">
          <img src=${picture} alt="">
          <p class="name">${name}</p>
          <p class="price">${price}</p>
        </div> 
        `
      })

arr是个数组形参(数组都有成员),forEach方法会遍历arr每个成员,item是forEach方法的function形参函数的形参,在这里传入的实际goodsList数组的成员是不同的{}对象,因此item会获取每次的{}对象信息,
即在 forEach 循环的第一次迭代中,item 将会是
{
id: ‘4001172’,
name: ‘称心如意手摇咖啡磨豆机咖啡豆研磨机’,
price: ‘289.00’,
picture: ‘https://yanxuan-item.nosdn.127.net/84a59ff9c58a77032564e61f716846d6.jpg’,
},
在第二次迭代中,item 将会是
{
id: ‘4001594’,
name: ‘日式黑陶功夫茶组双侧把茶具礼盒装’,
price: ‘288.00’,
picture: ‘https://yanxuan-item.nosdn.127.net/3346b7b92f9563c7a7e24c7ead883f18.jpg’,
},
以此类推。
const { name, picture, price } = item // 这是对象的解构赋值
item => { }这是箭头函数,item是形参,{ }是函数本体

forEach方法

以下是 forEach 方法的基本用法和解释:

javascript
array.forEach(function(currentValue, index, array) {
  // 你的迭代器逻辑
});
array 是要遍历的数组。
function(currentValue, index, array) 是为数组中每个元素执行的函数,该函数可以接受三个参数:
currentValue:数组中正在处理的当前元素。
index(可选):当前元素的索引。
array(可选):调用 forEach 的数组本身。
在你提供的 render 函数中,forEach 方法被用来遍历一个包含商品信息的数组 arr

第二个和第三个参数是可选的,可以看出function(currentValue, index, array) 是为数组中每个元素执行的函数,这个形参只有一个就是函数名称

function render(arr) {
  // 声明空字符串
  let str = '';
  
  // 遍历数组,使用传统函数表达式作为forEach的回调
  arr.forEach(function(item) {
    // 解构
    var name = item.name;
    var picture = item.picture;
    var price = item.price;
    
    // 构建HTML字符串并累加到str中
    str += '\
     <div class="item">\
      <img src="' + picture + '" alt="">\
      <p class="name">' + name + '</p>\
      <p class="price">' + price + '</p>\
    </div> \
    ';
  });
  
  // 追加给list元素
  document.querySelector('.list').innerHTML = str;
}

这是用传统function来实现的

‘.list’

在JavaScript中,document.querySelector('.list') 是一个DOM(文档对象模型)查询方法,用于选择文档中匹配指定CSS选择器的第一个元素。在这个例子中,.list 是一个类选择器,它选择文档中第一个具有 class="list" 属性的元素。

具体来说:

document 是一个代表整个HTML文档的对象。
querySelector 是 document 对象上的一个方法,它接收一个字符串参数,该参数是一个CSS选择器。
'.list' 是一个字符串,表示一个类选择器,它匹配所有具有 class="list" 的元素。注意,类选择器前面的点(.)是CSS语法的一部分,用于指定我们正在选择的是一个类名。
因此,document.querySelector('.list') 将返回文档中第一个具有 class="list" 的元素。如果没有找到匹配的元素,它将返回 null。

接下来的 .innerHTML = str 是一个赋值操作,它将变量 str 的值设置为之前查询到的元素的 innerHTML 属性。innerHTML 属性是一个可以获取或设置元素内部HTML内容的属性。在这个例子中,它被用来将 str 变量中包含的HTML字符串插入到具有 class="list" 的元素中,从而更新页面的内容。

过滤筛选

这行代码是JavaScript代码,用于在网页上添加一个点击事件监听器到一个具有class="filter"的元素上。下面是对这行代码的逐步解释:

document.querySelector('.filter'):
document 是一个代表整个网页文档的对象。
.querySelector() 是一个方法,用于在文档中选择第一个匹配指定CSS选择器的元素。
'.filter' 是一个CSS选择器字符串,表示选择所有具有class="filter"属性的HTML元素。
因此,document.querySelector('.filter')会返回文档中第一个具有class="filter"的元素。
.addEventListener('click', e => { ... }):
.addEventListener() 是一个方法,用于向指定元素添加事件监听器。
'click' 是要监听的事件类型,在这个例子中,是鼠标的点击事件。
e => { ... } 是一个箭头函数,它是事件处理函数,当事件发生时(在这个例子中是点击事件),这个函数会被调用。e 是传递给这个函数的事件对象,包含了事件的所有相关信息(比如点击的位置、哪个元素被点击等)。
整体解释:
这行代码的整体作用是:找到文档中第一个具有class="filter"的元素,并给它添加一个点击事件监听器。当这个元素被点击时,会执行箭头函数e => { ... }中的代码。
在{ ... }中,你可以编写任何你想要在点击事件发生时执行的JavaScript代码。例如,你可能想要显示或隐藏一些元素,或者改变某些元素的样式。
示例用途:
假设你有一个按钮,用于过滤页面上的内容,你可以这样写代码:
javascript
document.querySelector('.filter').addEventListener('click', e => {
    // 假设你想要隐藏所有没有特定类的元素
    document.querySelectorAll('.not-filtered').forEach(el => el.style.display = 'none');
});
在这个例子中,当具有class="filter"的元素被点击时,页面上所有具有class="not-filtered"的元素都会被隐藏。
希望这能帮助你理解这行代码的作用!

e是箭头函数的入口参数,const { tagName, dataset } = e.target是对象解构赋值,let arr = goodsList是数组解构赋值,

解释下arr = goodsList.filter(item => item.price > 0 && item.price <= 100)这行代码吧!!!
首先filte的入口参数必须是回调函数,是个函数,
item => item.price是箭头函数,也是个函数,item是箭头函数的入口参数
filter这个方法是对goodsList数组操作的方法,因此item就是goodsList本身,所以item.price就是goodsList数组里面的price
goodsList.filter(item => item.price > 0 && item.price <= 100)这个整体的意思是,判断出数组里面所有的对象,如果是C语言则必须是for循环,而JavaScript可以看出来不需要写for循环

《JavaScript权威指南》中关于Class的理解

JavaScript 进阶 - 第1天

学习作用域、变量提升、闭包等语言特征,加深对 JavaScript 的理解,掌握变量赋值、函数声明的简洁语法,降低代码的冗余度。

  • 理解作用域对程序执行的影响
  • 能够分析程序执行的作用域范围
  • 理解闭包本质,利用闭包创建隔离作用域
  • 了解什么变量提升及函数提升
  • 掌握箭头函数、解析剩余参数等简洁语法

作用域

了解作用域对程序执行的影响及作用域链的查找机制,使用闭包函数创建隔离作用域避免全局变量污染。

作用域(scope)规定了变量能够被访问的“范围”,离开了这个“范围”变量便不能被访问,作用域分为全局作用域和局部作用域。

局部作用域

局部作用域分为函数作用域和块作用域。

函数作用域

在函数内部声明的变量只能在函数内部被访问,外部无法直接访问。

<script>
  // 声明 counter 函数
  function counter(x, y) {
    // 函数内部声明的变量
    const s = x + y
    console.log(s) // 18
  }
  // 设用 counter 函数
  counter(10, 8)
  // 访问变量 s
  console.log(s)// 报错
</script>

总结:

  1. 函数内部声明的变量,在函数外部无法被访问
  2. 函数的参数也是函数内部的局部变量
  3. 不同函数内部声明的变量无法互相访问
  4. 函数执行完毕后,函数内部的变量实际被清空了
块作用域

在 JavaScript 中使用 {} 包裹的代码称为代码块,代码块内部声明的变量外部将【有可能】无法被访问。

<script>
  {
    // age 只能在该代码块中被访问
    let age = 18;
    console.log(age); // 正常
  }
  
  // 超出了 age 的作用域
  console.log(age) // 报错
  
  let flag = true;
  if(flag) {
    // str 只能在该代码块中被访问
    let str = 'hello world!'
    console.log(str); // 正常
  }
  
  // 超出了 age 的作用域
  console.log(str); // 报错
  
  for(let t = 1; t <= 6; t++) {
    // t 只能在该代码块中被访问
    console.log(t); // 正常
  }
  
  // 超出了 t 的作用域
  console.log(t); // 报错
</script>

JavaScript 中除了变量外还有常量,常量与变量本质的区别是【常量必须要有值且不允许被重新赋值】,常量值为对象时其属性和方法允许重新赋值。

<script>
  // 必须要有值
  const version = '1.0.0';

  // 不能重新赋值
  // version = '1.0.1';

  // 常量值为对象类型
  const user = {
    name: '小明',
    age: 18
  }

  // 不能重新赋值
  user = {};

  // 属性和方法允许被修改
  user.name = '小小明';
  user.gender = '男';
</script>

总结:

  1. let 声明的变量会产生块作用域,var 不会产生块作用域
  2. const 声明的常量也会产生块作用域
  3. 不同代码块之间的变量无法互相访问
  4. 推荐使用 letconst

注:开发中 letconst 经常不加区分的使用,如果担心某个值会不小被修改时,则只能使用 const 声明成常量。

全局作用域

<script> 标签和 .js 文件的【最外层】就是所谓的全局作用域,在此声明的变量在函数内部也可以被访问。

<script>
  // 此处是全局
  
  function sayHi() {
    // 此处为局部
  }

  // 此处为全局
</script>

全局作用域中声明的变量,任何其它作用域都可以被访问,如下代码所示:

<script>
    // 全局变量 name
    const name = '小明'
  
  	// 函数作用域中访问全局
    function sayHi() {
      // 此处为局部
      console.log('你好' + name)
    }

    // 全局变量 flag 和 x
    const flag = true
    let x = 10
  
  	// 块作用域中访问全局
    if(flag) {
      let y = 5
      console.log(x + y) // x 是全局的
    }
</script>

总结:

  1. window 对象动态添加的属性默认也是全局的,不推荐!
  2. 函数中未使用任何关键字声明的变量为全局变量,不推荐!!!
  3. 尽可能少的声明全局变量,防止全局变量被污染

JavaScript 中的作用域是程序被执行时的底层机制,了解这一机制有助于规范代码书写习惯,避免因作用域导致的语法错误。

作用域链

在解释什么是作用域链前先来看一段代码:

<script>
  // 全局作用域
  let a = 1
  let b = 2
  // 局部作用域
  function f() {
    let c
    // 局部作用域
    function g() {
      let d = 'yo'
    }
  }
</script>

函数内部允许创建新的函数,f 函数内部创建的新函数 g,会产生新的函数作用域,由此可知作用域产生了嵌套的关系。

如下图所示,父子关系的作用域关联在一起形成了链状的结构,作用域链的名字也由此而来。

作用域链本质上是底层的变量查找机制,在函数被执行时,会优先查找当前函数作用域中查找变量,如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域,如下代码所示:

<script>
  // 全局作用域
  let a = 1
  let b = 2

  // 局部作用域
  function f() {
    let c
    // let a = 10;
    console.log(a) // 1 或 10
    console.log(d) // 报错
    
    // 局部作用域
    function g() {
      let d = 'yo'
      // let b = 20;
      console.log(b) // 2 或 20
    }
    
    // 调用 g 函数
    g()
  }

  console.log(c) // 报错
  console.log(d) // 报错
  
  f();
</script>

总结:

  1. 嵌套关系的作用域串联起来形成了作用域链
  2. 相同作用域链中按着从小到大的规则查找变量
  3. 子作用域能够访问父作用域,父级作用域无法访问子级作用域(对于父亲来说,儿子自己的变量是局部变量,所以父亲无法访问)

闭包

闭包是一种比较特殊和函数,使用闭包能够访问函数作用域中的变量。从代码形式上看闭包是一个做为返回值的函数,如下代码所示:

<body>
  <script>
    // 1. 闭包 : 内层函数 + 外层函数变量
    // function outer() {
    //   const a = 1
    //   function f() {
    //     console.log(a)
    //   }
    //   f()
    // }
    // outer()

    // 2. 闭包的应用: 实现数据的私有。统计函数的调用次数
    // let count = 1
    // function fn() {
    //   count++
    //   console.log(`函数被调用${count}次`)
    // }

    // 3. 闭包的写法  统计函数的调用次数
    function outer() {
      let count = 1
      function fn() {
        count++
        console.log(`函数被调用${count}`)
      }
      return fn
    }
    const re = outer()
    // const re = function fn() {
    //   count++
    //   console.log(`函数被调用${count}次`)
    // }
    re()
    re()
    // const fn = function() { }  函数表达式
    // 4. 闭包存在的问题: 可能会造成内存泄漏
  </script>
</body>

总结:

1.怎么理解闭包?

  • 闭包 = 内层函数 + 外层函数的变量
    2025年1月5日注:闭包的两个特征,1就是上面,2就是一定要有return

2.闭包的作用?

  • 封闭数据,实现数据私有,外部也可以访问函数内部的变量
  • 闭包很有用,因为它允许将函数与其所操作的某些数据(环境)关联起来

3.闭包可能引起的问题?

  • 内存泄漏
    2025年1月5日注:根本原因是,闭包的局部变量没有被释放,没有被垃圾回收

变量提升

变量提升是 JavaScript 中比较“奇怪”的现象,它允许在变量声明之前即被访问,

<script>
  // 访问变量 str
  console.log(str + 'world!');

  // 声明变量 str
  var str = 'hello ';
</script>

总结:

  1. 变量在未声明即被访问时会报语法错误
  2. 变量在声明之前即被访问,变量的值为 undefined
  3. let 声明的变量不存在变量提升,推荐使用 let
  4. 变量提升出现在相同作用域当中
  5. 实际开发中推荐先声明再访问变量

注:关于变量提升的原理分析会涉及较为复杂的词法分析等知识,而开发中使用 let 可以轻松规避变量的提升,因此在此不做过多的探讨,有兴趣可查阅资料

函数

知道函数参数默认值、动态参数、剩余参数的使用细节,提升函数应用的灵活度,知道箭头函数的语法及与普通函数的差异。

函数提升

函数提升与变量提升比较类似,是指函数在声明之前即可被调用。

<script>
  // 调用函数
  foo()
  // 声明函数
  function foo() {
    console.log('声明之前即被调用...')
  }

  // 不存在提升现象
  bar()  // 错误
  var bar = function () {
    console.log('函数表达式不存在提升现象...')
  }
</script>

总结:

  1. 函数提升能够使函数的声明调用更灵活
  2. 函数表达式不存在提升的现象
  3. 函数提升出现在相同作用域当中

函数参数

函数参数的使用细节,能够提升函数应用的灵活度。

默认值
<script>
  // 设置参数默认值
  function sayHi(name="小明", age=18) {
    document.write(`<p>大家好,我叫${name},我今年${age}岁了。</p>`);
  }
  // 调用函数
  sayHi();
  sayHi('小红');
  sayHi('小刚', 21);
</script>

总结:

  1. 声明函数时为形参赋值即为参数的默认值
  2. 如果参数未自定义默认值时,参数的默认值为 undefined
  3. 调用函数时没有传入对应实参时,参数的默认值被当做实参传入
动态参数

arguments函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参。

<script>
  // 求生函数,计算所有参数的和
  function sum() {
    // console.log(arguments)
    let s = 0
    for(let i = 0; i < arguments.length; i++) {
      s += arguments[i]
    }
    console.log(s)
  }
  // 调用求和函数
  sum(5, 10)// 两个参数
  sum(1, 2, 4) // 两个参数
</script>

总结:

  1. arguments 是一个伪数组
  2. arguments 的作用是动态获取函数的实参
剩余参数
<script>
  function config(baseURL, ...other) {
    console.log(baseURL) // 得到 'http://baidu.com'
    console.log(other)  // other  得到 ['get', 'json']
  }
  // 调用函数
  config('http://baidu.com', 'get', 'json');
</script>

总结:

  1. ... 是语法符号,置于最末函数形参之前,用于获取多余的实参
  2. 借助 ... 获取的剩余实参,是个真数组

箭头函数

箭头函数是一种声明函数的简洁语法,它与普通函数并无本质的区别,差异性更多体现在语法格式上。

<body>
  <script>
    // const fn = function () {
    //   console.log(123)
    // }
    // 1. 箭头函数 基本语法
    // const fn = () => {
    //   console.log(123)
    // }
    // fn()
    // const fn = (x) => {
    //   console.log(x)
    // }
    // fn(1)
    // 2. 只有一个形参的时候,可以省略小括号
    // const fn = x => {
    //   console.log(x)
    // }
    // fn(1)
    // // 3. 只有一行代码的时候,我们可以省略大括号
    // const fn = x => console.log(x)
    // fn(1)
    // 4. 只有一行代码的时候,可以省略return
    // const fn = x => x + x
    // console.log(fn(1))
    // 5. 箭头函数可以直接返回一个对象
    // const fn = (uname) => ({ uname: uname })
    // console.log(fn('刘德华'))

  </script>
</body>

总结:

  1. 箭头函数属于表达式函数,因此不存在函数提升
  2. 箭头函数只有一个参数时可以省略圆括号 ()
  3. 箭头函数函数体只有一行代码时可以省略花括号 {},并自动做为返回值被返回
箭头函数参数

箭头函数中没有 arguments,只能使用 ... 动态获取实参

<body>
  <script>
    // 1. 利用箭头函数来求和
    const getSum = (...arr) => {
      let sum = 0
      for (let i = 0; i < arr.length; i++) {
        sum += arr[i]
      }
      return sum
    }
    const result = getSum(2, 3, 4)
    console.log(result) // 9
  </script>

箭头函数 this

箭头函数不会创建自己的this,它只会从自己的作用域链的上一层沿用this。

 <script>
    // 以前this的指向:  谁调用的这个函数,this 就指向谁
    // console.log(this)  // window
    // // 普通函数
    // function fn() {
    //   console.log(this)  // window
    // }
    // window.fn()
    // // 对象方法里面的this
    // const obj = {
    //   name: 'andy',
    //   sayHi: function () {
    //     console.log(this)  // obj
    //   }
    // }
    // obj.sayHi()

    // 2. 箭头函数的this  是上一层作用域的this 指向
    // const fn = () => {
    //   console.log(this)  // window
    // }
    // fn()
    // 对象方法箭头函数 this
    // const obj = {
    //   uname: 'pink老师',
    //   sayHi: () => {
    //     console.log(this)  // this 指向谁? window
    //   }
    // }
    // obj.sayHi()

    const obj = {
      uname: 'pink老师',
      sayHi: function () {
        console.log(this)  // obj
        let i = 10
        const count = () => {
          console.log(this)  // obj 
        }
        count()
      }
    }
    obj.sayHi()

  </script>

解构赋值

知道解构的语法及分类,使用解构简洁语法快速为变量赋值。

解构赋值是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值,分为数组解构、对象解构两大类型。

数组解构

数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法,如下代码所示:

<script>
  // 普通的数组
  let arr = [1, 2, 3]
  // 批量声明变量 a b c 
  // 同时将数组单元值 1 2 3 依次赋值给变量 a b c
  let [a, b, c] = arr
  console.log(a); // 1
  console.log(b); // 2
  console.log(c); // 3
</script>

总结:

  1. 赋值运算符 = 左侧的 [] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量
  2. 变量的顺序对应数组单元值的位置依次进行赋值操作
  3. 变量的数量大于单元值数量时,多余的变量将被赋值为 undefined
  4. 变量的数量小于单元值数量时,可以通过 ... 获取剩余单元值,但只能置于最末位
  5. 允许初始化变量的默认值,且只有单元值为 undefined 时默认值才会生效

注:支持多维解构赋值,比较复杂后续有应用需求时再进一步分析

对象解构

对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法,如下代码所示:

<script>
  // 普通对象
  const user = {
    name: '小明',
    age: 18
  };
  // 批量声明变量 name age
  // 同时将数组单元值 小明  18 依次赋值给变量 name  age
  const {name, age} = user

  console.log(name) // 小明
  console.log(age) // 18
</script>

总结:

  1. 赋值运算符 = 左侧的 {} 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量
  2. 对象属性的值将被赋值给与属性名相同的变量
  3. 对象中找不到与变量名一致的属性时变量值为 undefined
  4. 允许初始化变量的默认值,属性不存在或单元值为 undefined 时默认值才会生效

注:支持多维解构赋值

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

      ]
    }

    // 需求1: 请将以上msg对象  采用对象解构的方式 只选出  data 方面后面使用渲染页面
    // const { data } = msg
    // console.log(data)
    // 需求2: 上面msg是后台传递过来的数据,我们需要把data选出当做参数传递给 函数
    // const { data } = msg
    // msg 虽然很多属性,但是我们利用解构只要 data值
    function render({ data }) {
      // const { data } = arr
      // 我们只要 data 数据
      // 内部处理
      console.log(data)

    }
    render(msg)

    // 需求3, 为了防止msg里面的data名字混淆,要求渲染函数里面的数据名改为 myData
    function render({ data: myData }) {
      // 要求将 获取过来的 data数据 更名为 myData
      // 内部处理
      console.log(myData)

    }
    render(msg)

  </script>

综合案例

forEach遍历数组

forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数

注意:

1.forEach 主要是遍历数组

2.参数当前数组元素是必须要写的, 索引号可选。

<body>
  <script>
    // forEach 就是遍历  加强版的for循环  适合于遍历数组对象
    const arr = ['red', 'green', 'pink']
    const result = arr.forEach(function (item, index) {
      console.log(item)  // 数组元素 red  green pink
      console.log(index) // 索引号
    })
    // console.log(result)
  </script>
</body>

filter筛选数组

filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素

主要使用场景: 筛选数组符合条件的元素,并返回筛选之后元素的新数组

<body>
  <script>
    const arr = [10, 20, 30]
    // const newArr = arr.filter(function (item, index) {
    //   // console.log(item)
    //   // console.log(index)
    //   return item >= 20
    // })
    // 返回的符合条件的新数组

    const newArr = arr.filter(item => item >= 20)
    console.log(newArr)
  </script>
</body>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值