Javastript看这篇就够了

基础介绍

书写位置

基本语法

函数使用

匿名函数--函数表达式

匿名函数--立即执行

立即执行函数的特点:立即执行,避免代码污染

再解释一下立即执行函数方式1,为什么可以这样写

(function(){      })();

前面一个括号里写的是一个具体的函数,{}里写的是函数的内容

而最后那个括号实际上是对函数的调用

值得一提的是,立即执行函数间需要加; 否则可能出现混乱

对象

对象是什么

有点像不用实例化的结构体

访问里面的元素有两种写法。

但如果是“字符串”的话就只能用第二种

对象使用

注意!k是字符串

DOM

基础介绍

根据CSS选择器来获取DOM元素

 

当然了,还有别的方法

通过DOM修改元素内容

<body>
  <div>
    <h1>一等奖:<span id="first">???</span></h1>
    <h2>二等奖:<span id="second">???</span></h2>
    <h3>三等奖:<span id="third">???</span></h3>
  </div>
  <script>
    const person = ['刘德华', '张学友', '黎明']
    for (let i = 0; i < person.length; i++) {
      if (i == 0) {
        const fi = document.querySelector('#first')
        fi.innerHTML = person[i]
      }
      else if (i == 1) {
        const se = document.querySelector('#second')
        se.innerHTML = person[i]
      }
      else {
        const th = document.querySelector('#third')
        th.innerHTML = person[i]
      }
    }
  </script>
</body>

通过DOM操作元素属性和类(style,class)

例如,想要标签div的样式变成box里的一样,如果用上一种方式就要写很多行代码。

那我们可以把想要样式封装到一个css类里面(box),然后再让div的类等于box即可。

这样的话就不用写<div class = ""box>

再按f12到网页源代码里看,div的css类就是box

但className是用新值“覆盖”旧值,如果想保留原来的css类就这么写

这个是最常用的,比className好用

补充:setInterval 函数

setInterval 是 JavaScript 中用来周期性地执行代码的方法。它接受两个参数:一个是要周期执行的函数,另一个是执行的时间间隔(以毫秒为单位)。

基本语法:

setInterval(callback, delay);
  • callback 是一个函数,它将周期性地被调用。
  • delay 是以毫秒为单位的时间间隔,表示每隔多少时间调用一次 callback 函数。

示例:

function sayHello() { console.log('Hello, world!'); } // 每隔 2 秒执行一次 sayHello 函数 setInterval(sayHello, 2000);

在这个例子中,sayHello 函数会每隔 2 秒输出一次 'Hello, world!'

停止执行:

如果想要停止 setInterval 执行,可以使用 clearInterval 方法,并传入 setInterval 返回的定时器 ID。

let intervalId = setInterval(sayHello, 2000); // 5 秒后停止执行 setInterval setTimeout(() => { clearInterval(intervalId); console.log('Interval stopped.'); }, 5000);

在这个例子中,clearInterval(intervalId) 会停止之前设定的 setInterval

注意事项:

  • setInterval 不会等待上一次 callback 函数执行完毕,如果执行时间超过 delay,则会导致多个 callback 函数同时执行。因此,在 callback 函数内部,如果需要确保一次执行完成后再执行下一次,请谨慎处理。
  • 尽量避免使用过短的时间间隔,因为过于频繁的函数调用可能会影响性能。

使用 setInterval 可以实现很多周期性执行的需求,比如定时更新页面内容、轮播图片等。

<!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>
  <div>
    <textarea name="t" id="">用户规则</textarea>
    <button class="bth" disabled>我已阅读用户协议</button>
  </div>
  <script>
    const bth = document.querySelector('.bth')
    let i = 5
    let n = setInterval(function () {
      i--
      bth.innerHTML = `我已阅读用户协议(${i})`
      if (i == 0) {
        clearInterval(n)
        bth.disable = false
        bth.innerHTML = '同意'
      }
    }, 1000)
  </script>
</body>

</html>

事件的使用

事件监听

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

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

  </style>
</head>

<body>
  <div>
    <span>你抽到的是:</span>
    <div class="qs"></div>

    <div>
      <button class="begin">开始</button>
      <button class="end">结束</button>
    </div>

  </div>
  <script>
    let arr = ["关羽", "刘备", "张飞"]
    const begin = document.querySelector('.begin')
    const end = document.querySelector('.end')
    const qs = document.querySelector('.qs')
    let random = 0
    begin.addEventListener('click', function () {

      timerId = setInterval(function () {
        random = parseInt(Math.random() * arr.length)
        qs.innerHTML = arr[random]
      }, 35)
      if (arr.length == 1) {
        begin.disabled = true
        end.disabled = true

      }
    })

    end.addEventListener('click', function () {
      clearInterval(timerId)
      arr.splice(random, 1)
    })


  </script>
</body>

</html>

事件类型

焦点指的是鼠标的光标

<body>
  <input type="text">
  <script>
    let input = document.querySelector('input')
    input.addEventListener('focus', function () {
      console.log('焦点触发')
    })
    input.addEventListener('blur', function () {
      console.log('焦点消失')
    })

  </script>
</body>

<body>
  <input type="text">
  <script>
    let input = document.querySelector('input')
    input.addEventListener('keydown', function () {
      console.log('键盘按下了')
    })
    input.addEventListener('keyup', function () {
      console.log('键盘弹起了')
    })

  </script>
</body>

 

<body>
  <input type="text">
  <script>
    let input = document.querySelector('input')
    input.addEventListener('input', function () {
      console.log(input.value)
    })


  </script>
</body>

评论案例

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    input {
      width: 200px;
      transition: all .3s;
    }

    input:focus {
      width: 300px;
    }

    .total {
      opacity: 0;
    }
  </style>
</head>

<body>
  <div>
    <textarea name="" id="tx" placeholder="请输入一条友善的评论"></textarea>
    <div>
      <span class="total">0/200字</span>
    </div>

  </div>

  <script>
    let total = document.querySelector('.total')
    let tx = document.querySelector('#tx')

    tx.addEventListener('focus', function () {
      total.style.opacity = 1
    })
    tx.addEventListener('blur', function () {
      total.style.opacity = 0
    })
    tx.addEventListener('input', function () {
      total.innerHTML = `${tx.value.length}/200字`
    })
  </script>
</body>

</html>

事件对象

什么是事件对象

事件对象,存的是时间触发时的相关信息

在 JavaScript 中,事件对象是一个特殊的对象,它包含了与特定事件相关的信息,比如事件的类型、目标元素、事件触发时鼠标或键盘的状态等。事件对象通常在事件处理函数中自动传递给该函数,使得函数可以访问这些信息。

以下是事件对象的一些常见属性和方法:

  1. type:事件的类型,比如 "click""mouseover" 等。

  2. targetsrcElement:触发事件的元素。在 DOM 级别 0 中使用 srcElement,而在 DOM 级别 2 和现代浏览器中使用 target

  3. currentTarget:事件监听器绑定的元素,与 target 不同,currentTarget 是事件处理函数实际上附着的那个元素。

  4. eventPhase:事件当前所处的阶段(捕获或冒泡)。

  5. bubbles:一个布尔值,表示事件是否冒泡。

  6. cancelable:一个布尔值,表示事件是否可以被取消。

  7. defaultPrevented:如果事件的默认行为已经被取消,则为 true

  8. isTrusted:如果事件是用户操作生成的,则为 true

  9. timeStamp:事件被创建时的时间戳。

  10. preventDefault():调用此方法可以取消事件的默认行为。

  11. stopPropagation():调用此方法可以阻止事件继续传播到其他元素。

  12. stopImmediatePropagation():调用此方法不仅阻止事件传播,还会阻止在同一元素上注册的其他事件监听器被调用。

事件对象的使用示例:

element.addEventListener('click', function(event) {
    console.log(event.type); // "click"
    console.log(event.target); // 点击的元素
    event.preventDefault(); // 阻止默认行为
    event.stopPropagation(); // 阻止事件冒泡
});

在事件处理函数中,event 参数通常被命名为 event,但你也可以使用其他任何有效的变量名。这个参数包含了所有与事件相关的信息,允许你在函数内部访问这些信息。

复制再试一次分享

获取事件对象属性

<body>
  <input type="text">

  <script>
    let input = document.querySelector('input')
    input.addEventListener('keydown', function (event) {
      console.log(event)
    })
  </script>
</body>

例如,我此时按下了s和回车键,打印出来的信息可以看到都被记录在事件对象里了 

环境对象this

<body>
  <button>按钮</button>
  <script>
    function fn() {
      console.log(this)
    }
    fn()//其实是windows.fn()
    let btn = document.querySelector('button')
    btn.addEventListener('click', function () {
      console.log(this)
    })
  </script>
</body>

回调函数

案例巩固

水果案例

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .active {
      background: gainsboro;
    }
  </style>
</head>

<body>
  <div class="table">
    <div class="table_head">
      <h3>今日特价</h3>
      <ul>
        <li><a href="javascript:void(0);" class="active">苹果</a></li>
        <li><a href="javascript:void(0);">香蕉</a></li>
        <li><a href="javascript:void(0);">梨</a></li>
        <li><a href="javascript:void(0);">火龙果</a></li>
      </ul>
    </div>
    <div class="table_content">
      <div class="item"><img src="./apple.jpg" alt="苹果"></div>
      <div class="item" style="display: none;"><img src="./banana.jpg" alt="香蕉"></div>
      <div class="item" style="display: none;"><img src="./pear.jpg" alt="梨"></div>
      <div class="item" style="display: none;"><img src="./dragon_fruit.jpg" alt="火龙果"></div>
    </div>
  </div>
  <script>
    let head = document.querySelectorAll('.table_head a');
    let content = document.querySelectorAll('.table_content .item');

    for (let i = 0; i < head.length; i++) {
      head[i].addEventListener('mouseenter', function () {
        // 移除所有链接的 'active' 类
        head.forEach(h => h.classList.remove('active'));
        this.classList.add('active');

        // 隐藏所有内容
        content.forEach(c => c.style.display = 'none');

        // 显示对应的内容区
        content[i].style.display = 'block';
      });
    }
  </script>
</body>

</html>

全选文本框案例

<!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>
  <div>
    <div><input type="checkbox" class="checkAll">全选</div>
    <div><input type="checkbox" class="option">苹果</div>
    <div><input type="checkbox" class="option">香蕉</div>
    <div><input type="checkbox" class="option">梨</div>

  </div>
  <script>
    let checkAll = document.querySelector('.checkAll')
    let option = document.querySelectorAll('.option')
    checkAll.addEventListener('click', function () {
      option.forEach(c => {
        c.checked = checkAll.checked
      });
    })
    for (let i = 0; i < option.length; i++) {
      option[i].addEventListener('click', function () {
        let cnt = document.querySelectorAll('.option:checked').length
        if (cnt == option.length) {
          checkAll.checked = true
        }
      })
    }
  </script>
</body>

</html>

事件流

事件捕获

事件捕获很少用到

事件冒泡

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .father {
      width: 400px;
      height: 400px;
      background-color: red;
    }

    .son {
      width: 200px;
      height: 200px;
      background-color: blue;
    }
  </style>
</head>

<body>
  <div class="father">
    <div class="son"></div>

  </div>
  <script>
    let father = document.querySelector('.father')
    let son = document.querySelector('.son')
    document.addEventListener('click', function () {
      alert('祖宗')
    })
    father.addEventListener('click', function () {
      alert('父亲')
    })
    son.addEventListener('click', function () {
      alert('儿子')
    })
  </script>
</body>

</html>

举个例子。

如果只点击空白,则显示祖宗

点击红色,显示父亲->祖宗

点击蓝色,显示儿子->父亲->祖宗 

一层一层由低到高,这就是事件冒泡

阻止冒泡

组织冒泡只要加上以上代码就行。

那么此时点蓝色,只会显示儿子

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .father {
      width: 400px;
      height: 400px;
      background-color: red;
    }

    .son {
      width: 200px;
      height: 200px;
      background-color: blue;
    }
  </style>
</head>

<body>
  <div class="father">
    <div class="son"></div>

  </div>
  <script>
    let father = document.querySelector('.father')
    let son = document.querySelector('.son')
    document.addEventListener('click', function () {
      alert('祖宗')
    })
    father.addEventListener('click', function () {
      alert('父亲')
    })
    son.addEventListener('click', function (e) {
      e.stopPropagation();
      alert('儿子')
    })
  </script>
</body>

</html>

解绑事件

上面这个方法比较原始。因为绑定事件一般用监听器 

事件委托

利用了事件冒泡的特性

比如说有一个表格ul,里面有很多个li,那么我们想实现触发li的时候出现某种效果。如果给每个li都添加监听器就太麻烦了。鉴于这些li的父元素是ul,触发子元素的时候会冒泡到父元素身上,那么只需要对父元素添加监听器来统一管理即可。

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

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

  </style>
</head>

<body>
  <ul>
    <li>第1个子元素</li>
    <li>第2个子元素</li>
    <li>第3个子元素</li>
    <li>第4个子元素</li>
    <li>第5个子元素</li>
    <p>这是一个p</p>
  </ul>
  <script>
    let ul = document.querySelector('ul')
    ul.addEventListener('click', function (e) {
      if (e.target.tagName === 'LI') {
        e.target.style.color = 'red'
      }
    })
  </script>
</body>

</html>

阻止冒泡(阻止默认行为)

页面加载事件

页面滚动事件

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      height: 1000px;
    }

    div {
      display: none;
      width: 300px;
      height: 300px;
      background-color: red;
    }
  </style>
</head>

<body>
  <div></div>
  <script>
    let div = document.querySelector('div')
    document.documentElement.scrollTop = 80
    //可赋值
    window.addEventListener('scroll', function () {
      let n = document.documentElement.scrollTop
      if (n >= 50) {
        div.style.display = 'block'
      } else {
        div.style.display = 'none'
      }
    })
  </script>
</body>

</html>

页面尺寸事件

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .line {
      background: red;
      height: 2px;
      width: 10px;
      position: absolute;
      top: 0;
      left: 0;
      transition: transform 0.3s ease;
    }

    .table {
      position: relative;
    }

    .list {
      display: flex;
    }

    .list a {
      padding: 10px;
      margin-right: 10px;
      text-decoration: none;
      color: black;
    }
  </style>
</head>

<body>
  <div class="table">
    <div class="list">
      <a href="#">1</a>
      <a href="#">2</a>
      <a href="#">3</a>
      <a href="#">4</a>
      <a href="#">5</a>
    </div>
    <div class="line"></div>
  </div>

  <script>
    let tab = document.querySelector('.list'); // 修正选择器为 .list
    let line = document.querySelector('.line');

    tab.addEventListener('click', function (e) {
      if (e.target.tagName === 'A') {
        let offsetLeft = e.target.offsetLeft; // 获取点击元素相对于其父元素 .list 的左偏移量
        let tableOffsetLeft = tab.offsetLeft; // 获取 .list 相对于其父元素 .table 的左偏移量
        line.style.transform = `translateX(${offsetLeft + tableOffsetLeft}px)`; // 计算实际的 transform 值
      }
    });
  </script>
</body>

</html>

日期对象

<body>
  <div></div>

  <script>
    let div = document.querySelector('div')
    setInterval(function () {
      let date = new Date()
      div.innerHTML = date
    }, 1000)

  </script>
</body>

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

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

  </style>
</head>

<body>
  <div id="goal"></div>

  <div id="count"></div>

  <script>
    let s = '2024-8-7 12:05:00'
    function getCount() {
      let goal = document.querySelector('#goal')
      let count = document.querySelector('#count')
      goal.innerHTML = '距离' + s + '还有'

      let cur = +new Date()
      let future = new Date(s)
      let span = future - cur
      span /= 1000

      let hour = parseInt(span / 60 / 60 % 24)
      hour = hour < 10 ? '0' + hour : hour
      let min = parseInt(span / 60 % 60)
      min = min < 10 ? '0' + min : min
      let second = parseInt(span % 60)
      if (second < 0) hour = '00', min = '00', second = '0'
      second = second < 10 ? '0' + second : second
      count.innerHTML = hour + ':' + min + ':' + second
    }
    getCount()
    setInterval(getCount, 1000)

  </script>
</body>

</html>

节点

查找节点

注意,一个节点可以有多个子节点,但只有一个父节点。

所以父节点查找只返回一个元素,而子节点查找是返回一个伪数组

增加节点

<body>
  <ul></ul>

  <script>
    let p1 = document.createElement('li')
    p1.innerHTML = '第一个'
    let p2 = document.createElement('li')
    p2.innerHTML = '第二个'

    let ul = document.querySelector('ul')
    ul.appendChild(p1)
    ul.append(p2, ul.children[0])
  </script>
</body>

如果这里的克隆填false,那么li里面的内容“1”就不会被克隆过来

删除节点

补充了解

所以bom是比dom大的

js同步和异步

输出结果都是132,为什么呢?

Window对象

location对象

网页直接跳转到百度 

经常用href 利用js的方法去跳转页面

<body>

  <script>
    location.href = 'http://www.baidu.com'
  </script>
</body>

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

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

  </style>
</head>

<body>
  <form action="">
    <input type="text" name="username" placeholder="请输入用户名"><br>
    <input type="password" name="pwd" placeholder="请输入密码"><br>
    <button type="submit">提交</button>
  </form>

  <script>
    console.log(location.search)
  </script>
</body>

</html>

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

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

  </style>
</head>

<body>
  <a href="#/my">我的</a>
  <a href="#/follow">关注</a>
  <a href="#/download">下载</a>

  <script>
    window.addEventListener('click', function () {
      console.log(location.hash)
    })

  </script>
</body>

</html>

navigator对象

history对象

本地存储localStorage

之前写的页面,点一下刷新页面就会全部刷新,之前在这个页面填写的信息全没了。为了解决这个问题,学习本地存储。

<body>


  <script>
    //增。本地存储只能存字符串类型!这个很重要!
    localStorage.setItem('name', 'lmm')
    //查
    console.log(localStorage.getItem('name'))
    //改。如果该键已经有值,再setItem就是改了
    localStorage.setItem('name', 'lpp')
    //删
    localStorage.removeItem('name')
  </script>
</body>

如果不用remove的情况下,再运行同样的网页,键值也不会消失,会存在用户的电脑中 

下面这个先作为了解,用法和localstorage基本一样

上面那种是一个元素一个元素存,是存储简单数据类型。

如果想存像结构体那样的信息,就是存复杂数据类型。

<body>


  <script>
    //这是复杂数据类型
    const obj = {
      name: 'lmm',
      age: '21'
    }
    localStorage.setItem('obj', obj)
    console.log(localStorage.getItem('obj'))
  </script>
</body>

如果直接这样存,就看不到obj里面存的是什么了,因为存储的信息会被 转换成字符串

因此需要数据类型转换 

取出的时候不能直接取出,因为直接取出的是字符串,应该要转换成对象才能使用

正确写法

<body>
  <script>
    //这是复杂数据类型
    const obj = {
      name: 'lmm',
      age: '21'
    }
    //存入的时候转换成复杂数据类型
    localStorage.setItem('obj', JSON.stringify(obj))
    //取出的时候转换成对象
    console.log(JSON.parse(localStorage.getItem('obj')))
  </script>
</body>

map和join方法

map方法

map重点在于有返回值,会返回一个数组!!! 

<body>
  <script>
    let arr = ['红', '蓝', '绿']
    const newArr = arr.map(function (ele, index) {
      return ele + '色'
    })
    console.log(newArr)
  </script>
</body>

join方法

map+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>
  <style>
  </style>
</head>

<body>
  <table>
    <tbody>
    </tbody>
  </table>
  <script>
    const initData = [{
      stuId: 1,
      uname: '迪丽热巴',
      age: 22,
      gender: '女',
      salary: '12000',
      city: '北京',
      time: '2099-09-09 08:08:08'
    }];

    // 确保在浏览器控制台中运行这段代码之前已经执行了下面的代码
    // localStorage.setItem('data', JSON.stringify(initData));

    const arr = JSON.parse(localStorage.getItem('data'));
    const tbody = document.querySelector('tbody');

    function render() {
      const trArr = arr.map(function (ele) {
        return `
        <tr>
          <td>${ele.stuId}</td>
          <td>${ele.uname}</td>
          <td>${ele.age}</td>
          <td>${ele.gender}</td>
          <td>${ele.salary}</td>
          <td>${ele.city}</td>
          <td>${ele.time}</td>
          <td>
            <a href="javascript:">
              <i class="iconfont icon-shanchu"></i> 删除
            </a>
          </td>
        </tr>
        `;
      });
      tbody.innerHTML = trArr.join('');
    }

    render();
  </script>
</body>

</html>

学生就业统计表案例

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 添加样式 */
  </style>
</head>

<body>
  <form class="info" action="">
    <input type="text" class="uname" placeholder="请输入姓名">
    <input type="text" class="age" placeholder="请输入年龄">
    <input type="text" class="salary" placeholder="请输入薪资">
    <select class="gender" name="gender">
      <option value="男">男</option>
      <option value="女">女</option>
    </select>

    <select class="city" name="city">
      <option value="北京">北京</option>
      <option value="上海">上海</option>
      <option value="广州">广州</option>
      <option value="深圳">深圳</option>
    </select>
    <button type="submit">添加</button>
  </form>

  <table>
    <tbody>
      <!-- 数据行将被渲染在这里 -->
    </tbody>
  </table>

  <script>
    const initData = [{
      stuId: 1,
      uname: '迪丽热巴',
      age: 22,
      gender: '女',
      salary: '12000',
      city: '北京',
      time: '2099-09-09 08:08:08'
    }];

    const tbody = document.querySelector('tbody');
    //如果没有数据,用空数组来代替
    let arr = JSON.parse(localStorage.getItem('data')) || []

    function render() {
      const trArr = arr.map(ele => `
        <tr>
          <td>${ele.stuId}</td>
          <td>${ele.uname}</td>
          <td>${ele.age}</td>
          <td>${ele.gender}</td>
          <td>${ele.salary}</td>
          <td>${ele.city}</td>
          <td>${ele.time}</td>
          <td>
            <a href="javascript:">
              <i class="iconfont icon-shanchu"></i> 删除
            </a>
          </td>
        </tr>
      `);
      tbody.innerHTML = trArr.join('');
    }

    render();

    const info = document.querySelector('.info');
    const uname = document.querySelector('.uname');
    const age = document.querySelector('.age');
    const salary = document.querySelector('.salary');
    const gender = document.querySelector('.gender');
    const city = document.querySelector('.city');

    info.addEventListener('submit', function (e) {
      e.preventDefault(); // 防止表单提交的默认行为
      if (!uname.value || !age.value || !salary.value) {
        return alert('输入内容不能为空');
      }

      // 生成新的 stuId
      const newStuId = arr.length ? arr[arr.length - 1].stuId + 1 : 1;

      // 处理表单数据
      arr.push({
        stuId: newStuId,
        uname: uname.value,
        age: age.value,
        gender: gender.value,
        salary: salary.value,
        city: city.value,
        time: new Date().toLocaleString() // 调用方法
      });

      // 更新 localStorage
      localStorage.setItem('data', JSON.stringify(arr));

      // 渲染页面
      render();

      // 重置表单
      this.reset();
    });
  </script>
</body>

</html>

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 添加样式 */
  </style>
</head>

<body>
  <form class="info" action="">
    <input type="text" class="uname" placeholder="请输入姓名">
    <input type="text" class="age" placeholder="请输入年龄">
    <input type="text" class="salary" placeholder="请输入薪资">
    <select class="gender" name="gender">
      <option value="男">男</option>
      <option value="女">女</option>
    </select>

    <select class="city" name="city">
      <option value="北京">北京</option>
      <option value="上海">上海</option>
      <option value="广州">广州</option>
      <option value="深圳">深圳</option>
    </select>
    <button type="submit">添加</button>
  </form>

  <table>
    <tbody>
      <!-- 数据行将被渲染在这里 -->
    </tbody>
  </table>

  <script>
    const initData = [{
      stuId: 1,
      uname: '迪丽热巴',
      age: 22,
      gender: '女',
      salary: '12000',
      city: '北京',
      time: '2099-09-09 08:08:08'
    }];

    const tbody = document.querySelector('tbody');
    //如果没有数据,用空数组来代替
    let arr = JSON.parse(localStorage.getItem('data')) || initData;

    function render() {
      const trArr = arr.map(ele => `
        <tr data-id="${ele.stuId}">
          <td>${ele.stuId}</td>
          <td>${ele.uname}</td>
          <td>${ele.age}</td>
          <td>${ele.gender}</td>
          <td>${ele.salary}</td>
          <td>${ele.city}</td>
          <td>${ele.time}</td>
          <td>
            <a href="javascript:" class="delete-btn">
              <i class="iconfont icon-shanchu"></i> 删除
            </a>
          </td>
        </tr>
      `);
      tbody.innerHTML = trArr.join('');

      // 绑定删除按钮事件
      const deleteButtons = document.querySelectorAll('.delete-btn');
      deleteButtons.forEach(button => {
        button.addEventListener('click', function (e) {
          const stuId = parseInt(this.closest('tr').getAttribute('data-id'));
          deleteRecord(stuId);
        });
      });
    }

    function deleteRecord(stuId) {
      // 从数组中删除对应的数据
      arr = arr.filter(ele => ele.stuId !== stuId);

      // 更新 localStorage
      localStorage.setItem('data', JSON.stringify(arr));

      // 渲染页面
      render();
    }

    render();

    const info = document.querySelector('.info');
    const uname = document.querySelector('.uname');
    const age = document.querySelector('.age');
    const salary = document.querySelector('.salary');
    const gender = document.querySelector('.gender');
    const city = document.querySelector('.city');

    info.addEventListener('submit', function (e) {
      e.preventDefault(); // 防止表单提交的默认行为
      if (!uname.value || !age.value || !salary.value) {
        return alert('输入内容不能为空');
      }

      // 生成新的 stuId
      const newStuId = arr.length ? arr[arr.length - 1].stuId + 1 : 1;

      // 处理表单数据
      arr.push({
        stuId: newStuId,
        uname: uname.value,
        age: age.value,
        gender: gender.value,
        salary: salary.value,
        city: city.value,
        time: new Date().toLocaleString() // 调用方法
      });

      // 更新 localStorage
      localStorage.setItem('data', JSON.stringify(arr));

      // 渲染页面
      render();

      // 重置表单
      this.reset();
    });
  </script>
</body>

</html>

正则表达式

 

返回true或false

返回数组

具有特殊意义的字符就是元字符。比如,可以将abcdef.....z替换成[a-z]。

 

  1. g(global):全局匹配。查找整个输入字符串中所有符合正则表达式的匹配项,而不是找到第一个匹配项就停止搜索。

  2. i(ignore case):忽略大小写。匹配时不区分字母的大小写。例如,/a/i 会匹配 'a'、'A' 等。

闭包

闭包是一种编程概念,指的是一个函数与其相关的变量环境捆绑在一起的能力。换句话说,闭包允许一个函数在其外部定义的变量范围内操作,即使这些变量在函数外部已经不再存在。这种特性使得函数能够记住并访问它们创建时的作用域。闭包常用于创建私有变量和函数,封装代码,以及实现一些函数式编程的模式。

变量提升(了解)

变量提升实际上是js的缺陷,只会用var的时候会出现。仅作了解

<script>
    console.log(num);//undefine
    var num = 10;
  </script>

<script>
    // console.log(num);//undefine
    // var num = 10;

    //变量未申明就被使用,会出现变量提升,
    //所有var变量都被提到当前作用域最前面,
    //但是只提升声明,不提升赋值,因此代码相当于
    var num
    console.log(num);
    num = 10
  </script>

函数进阶

函数提升 

函数提升和变量提升有点像。

只提升声明,不提升调用

动态参数

剩余参数

展开运算符 

这个符号就是“...”

箭头函数(重要)

<script>
    const fn1 = function () {
      console.log('普通函数');
    }
    const fn2 = () => {
      console.log('普通箭头函数')
    }
    const fn3 = (x) => {
      //带参数的箭头函数
      console.log(x)
    }
    const fn4 = x => {
      //只有一个参数的箭头函数,可以省略()
      console.log(x);
    }

    //当{}里只有一行代码时可以省略{}
    const fn5 = (x, y) => x + y

    //返回对象字面量表达式。加()是为了不会混淆
    const fn6 = uname =>({uname : uname})

  </script>

注意事项

箭头函数没有自己的this,如果非要用的话,会从自己作用域链的上一层沿用this,很不方便,因此如果用this的话一般不用箭头函数

解构

解构赋值

把数组里的元素快速地赋值给变量,使代码更简洁

必须加分号,不然会被当成数组的符号而不是解构的符号

<script>
    const pc = ['海尔', '联想', '小米', '方正']
    ;[hr, l, x, f] = pc

    const getval = () => [100, 1]
    ;[max, min] = getval()
    console.log(hr, l, x, f, max, min);

  </script>

对象解构

注意!对象解构用的符号是{},数组用的才是[]

<script>
    const obj = {
      name: 'lmm',
      age: '3'
    };

    //注意,解构定义的变量名必须与对象的名字一样
    const { name, age } = obj
    console.log(name, age);


  </script>

当然,也可以重新改名

下面是一个案例。

值得一提的是,

const { data } = msg; 的意思是:

  • 从 msg 对象中提取 data 属性的值。
  • 将提取的值赋给一个新的变量 data

这段代码的效果等同于以下代码:

const data = msg.data;

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

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    /* 添加样式 */
  </style>
</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
        }
      ]
    };

    //需求1:用对象解构的方式取出data
    const { data } = msg
    console.log(data);

    //需求2:把data当作参数传递给渲染函数

    //第一种写法
    function render(arr) {
      console.log(arr);
    }
    render(data)

    //第二种更简洁的写法
    function render2({ data }) {
      console.log(data);
    }
    render2(msg)

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

</html>

forEach方法(重点)

和map遍历一样的 。区别在于map遍历会返回一个数组

这个渲染,本质上就是把东西转换成字符串然后再拼接而已

构造函数

“上一次值” 就是上一次计算的结果,如果是第一次循环的话,上一次值就是第一个元素的值或者初始值(如果有设置的话)

<body>


  <script>
    const arr = [1, 2, 3]

    //没有初始值
    let sum1 = arr.reduce(function (pre, cur) {
      return pre + cur;
    })
    console.log(sum1);//6

    //有初始值。只是把结果加上初始值而已
    let sum2 = arr.reduce(function (pre, cur) {
      return pre + cur;
    }, 6)
    console.log(sum2);//12

    //箭头函数写法
    let sum3 = arr.reduce((pre, cur) => pre + cur, 6)
    console.log(sum3);//12
  </script>
</body>

可以看到,一个相同的函数被创造了两次,浪费内存

怎么解决内存浪费的问题?

<script>
    function star(name, age) {
      this.name = name
      this.age = age
    }
    star.prototype.sing_wrong = () => {
      //这样会错!!!
      //因为箭头函数没有自己的this
      console.log(this.name + '在唱歌');
    }
    star.prototype.sing = function () {
      console.log(this.name + '在唱歌');
    }
    const a = new star('刘德华', 40)
    const b = new star('张学友', 43)
    a.sing(); b.sing();
  </script>

利用原型来写数组的求最大值函数

<body>


  <script>
    const arr = [1, 2, 3, 4, 5]
    //其实相当于
    //const arr = new Array(1, 2, 3, 4, 5)
    Array.prototype.max = function () {
      return Math.max(...this)
    }
    console.log(arr.max());

  </script>
</body>

能让原型对象找到其构造函数

Promise对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值