JavaScript2.0

2024.5.27

正则表达式

用于匹配字符串中字符组合的模式

作用

  • 表单验证
  • 过滤敏感词
  • 字符串中提取我们想要的部分

test() 检验是否有匹配项

exec() 返回数组

元字符

一些具有特殊含义的字符,可以极大提高了灵活性和强大的匹配功能

^ 以谁开始

$ 以谁结束

/^哈$/ 以ha开头 ha结尾

量词 用来规定某个模式出现得次数

  • *重复0次或更多次
  • +重复1次或更多次
  • ?重复零次或一次
  • {4}只能出现4次
  • {4,}出现次数大于等于4
  • {4,6}重复n到m次
  • [] 匹配字符集合 包含里面的任意一个字符
  • [a-zA-Z]
  • [^a-z] 取反 匹配除了小写字母以外的字符

. 除了换行符之外的任何符号

字符类 预定义

  • \d 相当于[0-9]
  • \D 相当于[^0-9]
  • \w 相当于[a-zA-Z0-9_]
  • \W 相当于[^a-zA-Z0-9_]
  • \s 匹配空格相当于[\t\r\n\v\f]
  • \S 相当于[^\t\r\n\v\f]
  • i  不区分大小写 eg/^java$/i
  • g 匹配所有满足正则表达式的结果

replace

replace(/正则表达式/,'被替换的文本')

str.replace(/java/ig,'前端')

change事件 内容发了变化

classList.contain() //判断是否包括……属性

今日案例

案例一:用户验证案例 考察reg+className+blur事件

  <script>
    const input = document.querySelector('input')
    const span = document.querySelector('span')
    //正则表达式
    const reg = /^[a-zA-Z0-9-_]{6,16}$/
    //当聚焦离开后触发
    input.addEventListener('blur', function () {
      if (reg.test(this.value)) {
        span.innerHTML = '输入正确'
        //增添right类
        span.className('right')
      } else {
        span.innerHTML = '输入错误'
        //增添error类
        span.className('error')
      }
    })
</script>

案例二:过滤敏感词 考察replace+reg

<script>
    const input = document.querySelector('textarea')
    const button = document.querySelector('button')
    const div = document.querySelector('div')
    const reg = /fuck|shit/ig
    //拿到textarea里面的value
    button.addEventListener('click', function () {
      div.innerHTML = input.value.replace(reg, '**')
    })
</script>

案例三:综合案例

register.html 考察reg+setInterval

1.短信验证码部分

//1,发送短信验证码
    const code = document.querySelector('.code')
    let flag = true
    code.addEventListener('click', function () {
      if (flag) {
        flag = false
        let i = 5
        code.innerHTML = `0${i}秒后重新获取`
        let timeid = setInterval(function () {
          i--
          code.innerHTML = `0${i}秒后重新获取`
          if (i === 0) {
            clearInterval(timeid)
            code.innerHTML = `重新获取`
            flag = true
          }
        }, 1000)
      }
    })

2.表单验证(ps 后续手机号、密码等验证相似)考察change事件 当内容发生改变时触发

//表单验证
    const username = document.querySelector('[name=username]')
    username.addEventListener('change', verifyName)
    function verifyName() {
      const span = username.nextElementSibling
      const reg = /^[a-zA-Z0-9-_]{6,10}$/
      if (!reg.test(username.value)) {
        span.innerHTML = '输入不合法,请输入6~10位'
        return false
      }
      span.innerHTML = ''
      return true
    }

3.我同意模块 考察点:toggle

const agree = document.querySelector('.icon-queren')
    agree.addEventListener('click', function () {
      this.classList.toggle('icon-queren2')
})

4.提交模块 考察点:submit contains preventDefault

const form = document.querySelector('form')
    form.addEventListener('submit', function (e) {
      //我同意是否勾选
      if (!agree.classList.contains('icon-queren2')) {
        alert('请勾选同意协议')
        e.preventDefault()}
      if (!verifyName()) e.preventDefault()
      if (!verifyCode()) e.preventDefault()
      if (!verifyConfirm()) e.preventDefault()
      if (!verifyPassword()) e.preventDefault()
      if (!verifyPhone()) e.preventDefault()
})

login.html localStorage.setItem

  <script>
    //tab栏切换
    const tab_nav = document.querySelector('.tab-nav')
    const pane = document.querySelectorAll('.tab-pane')
    tab_nav.addEventListener('click', function (e) {
      if (e.target.tagName === 'A') {
        tab_nav.querySelector('.active').classList.remove('active')
        e.target.classList.add('active')
        for (let i = 0; i < pane.length; i++) {
          pane[i].style.display = 'none'
        }
        pane[e.target.dataset.id].style.display = 'block'
      }
    })
    //点击提交模块
    const form = document.querySelector('form')
    const username = document.querySelector('[name=username]')
    const agree = document.querySelector('[name=agree]')
    form.addEventListener('submit', function (e) {
      e.preventDefault()
      if (!agree.checked) {
        return alert('请勾选同意协议')
      }
      //记录用户名
      localStorage.setItem('xtx-uname', username.value)
      location.href = './index.html'
    })
  </script>

index.html

<script>
    const li1 = document.querySelector('.xtx_navs li:first-child')
    const li2 = li1.nextElementSibling
    //做个渲染函数
    function render() {
      const uname = localStorage.getItem('xtx-uname')
      if (uname) {
        li1.innerHTML = `<a href="javascript:;"><i class="iconfont icon-user">${uname}</i></a>`
        li2.innerHTML = `<a href="javascript:;">退出登录</a>`
      } else {
        li1.innerHTML = `<a href="./login.html">请先登录</a>`
        li2.innerHTML = `<a href="./register.html">免费注册</a></a>`
      }
    }
    render()
    li2.addEventListener('click', function () {
      localStorage.removeItem('xtx-uname')
      //重新渲染
      render()
    })
</script>

2024.5.28

综合案例:图片切换模块

<script>
    //获得三个盒子
    const small = document.querySelector('.small')
    const middle = document.querySelector('.middle')
    const large = document.querySelector('.large')

    small.addEventListener('mouseover', function (e) {
      if (e.target.tagName === 'IMG') {
        this.querySelector('.active').classList.remove('active')
        e.target.parentNode.classList.add('active')
        middle.querySelector('img').src = e.target.src
        large.style.backgroundImage = `url(${e.target.src})`
      }
    })
    //3.鼠标经过中等盒子,显示隐藏大盒子
    middle.addEventListener('mouseover', show)
    middle.addEventListener('mouseleave', hide)
    let timeId = null //0
    function show() {
      clearInterval(timeId)
      large.style.display = 'block'
    }
    function hide() {
      timeId = setInterval(function () {
        large.style.display = 'none'
      }, 200)
    }
    large.addEventListener('mouseover', show)
    large.addEventListener('mouseleave', hide)
    //黑色遮罩
    //找到黑色盒子得坐标 变化
    //鼠标经过中等盒子,显示遮罩
    const layer = document.querySelector('.layer')
    middle.addEventListener('mouseenter', function () {
      layer.style.display = 'block'
    })
    middle.addEventListener('mouseleave', function () {
      layer.style.display = 'none'
    })
    //移动黑色遮罩盒子
    middle.addEventListener('mousemove', function (e) {
      //e.pageX 
      //middle.getBoundingClientRect().left
      let x = e.pageX - middle.getBoundingClientRect().left
      let y = e.pageY - middle.getBoundingClientRect().top - document.documentElement.scrollTop
      if (x >= 0 && x <= 400 && y >= 0 && y <= 400) {
        //黑色盒子移动变量
        let mx = 0, my = 0
        if (x < 100) mx = 0
        if (x >= 100 && x <= 300) mx = x - 100
        if (x > 300) mx = 200
        if (y < 100) my = 0
        if (y >= 100 && y <= 300) my = y - 100
        if (y > 300) my = 200
        layer.style.left = mx + 'px'
        layer.style.top = my + 'px'
        //大盒子背景图片跟随中等移动
        large.style.backgroundPositionX = -2 * mx + 'px'
        large.style.backgroundPositionY = -2 * my + 'px'
      }
    })
</script>

2024.5.29

作用域

局部作用域
  • 函数作用域:在函数内部声明的变量,只能在函数内部被访问
  • 块作用域:在js种使用{}包裹的代码,代码块内部声明的变量外部将【有可能】无法被访问(这里指的var声明的可以被访问)
全局作用域

script内部声明+.js文件

作用域链

优先查找当前函数作用域,查找不到就依次逐级查找父级作用域直到全局作用域

本质上是最底层的变量查找机

嵌套关系的作用域串联起来形成了作用域链

相同作用域链中按着从小到大的规则查找变量

子作用域能够访问父作用域 反之不行

垃圾回收机制(garbage collection GC)

js种内存的分配和回收都是自动完成的,内存在不使用时会被垃圾回收器自动回收

生命周期:内存分配-内存使用-内存回收

全局变量一般不回收,一般情况下局部变量的值不用了会被自动回收

内存泄漏:程序种分配的内存由于某种原因未释放或无法释放

算法说明:

  • 1 栈:由操作系统自动分配释放函数的参数值、局部变量等,基本数据类型放到栈中
  • 2 堆:一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。复杂数据类型放在堆里
引用计数法

跟踪记录被引用的次数

被引用一次就++ 没被引用就--

致命问题:嵌套使用 两个对象互相引用,尽管都不使用,GC不会回收 导致内存泄漏

标记清除法

优先使用

将不再使用的对象定义为无法到达的对象

从根部扫描对象,能查找到的就是使用的,查找不到的就是要回收的

闭包 closure(关闭的)

一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域

但可能会存在内存泄漏

作用:封装数据,实现数据私有,外部也可以访问函数内部的变量

很有用,因为它允许将函数与其所操作的某些数据关联起来

怎么理解闭包:内层函数+外部函数的变量

变量提升

仅存在于var声明变量,是js中比较奇怪的现象,它允许在变量声明之前被访问

函数提升

能够使函数的声明调用更灵活

函数参数

动态参数

arguments使函数内部内置的伪数组变量

arguments是一个数组

剩余参数

...arr

更加灵活

展开运算符

将一个数组进行展开:求数组最大最小值,合并数组

eg: consolo.log(Math.max(...arr))

箭头函数

基本语法

const fun = () =>{}

只有一个形参时,可以省略小括号

只有一行代码的时候,可以省略大括号

eg: const fun = x => consolo.log(x)

箭头函数里面没有arguments 但是有...args

解构赋值

数组解构 将数组的单元值快速批量赋值给一系列变量的简洁语法

const [max,min,avg] = [100,60,80]

必须添加分号:①立即执行函数 ②数组解构

对象解构

const {uname,age} = {uname:'pink',age:18}

改名字 const {uname:username,age}

forEach方法

遍历数组的每个元素

不返回数组,map会返回数组

fliter筛选

筛选数值

今日案例:价格筛选

<script>
//1.渲染函数
    function render(arr) {
      let str = ''
      arr.forEach(item => {
        const { name, price, picture } = item
        str += `
        <div class="item">
        <img src="${picture}" alt="">
        <p class="name">${name}</p>
        <p class="price">${price}</p>
        </div>
        `
        document.querySelector('.list').innerHTML = str
      })
    }
    render(goodsList)
    //2.过滤筛选
    document.querySelector('.filter').addEventListener('click', e => {
      if (e.target.tagName === 'A') {
        let newarr = goodsList
        if (e.target.dataset.index === '1') {
          newarr = goodsList.filter(item => item.price > 0 && item.price <= 100)
        } else if (e.target.dataset.index === '2') {
          newarr = goodsList.filter(item => item.price > 100 && item.price <= 300)
        } else if (e.target.dataset.index === '3') {
          newarr = goodsList.filter(item => item.price > 300)
        }
        render(newarr)
      }
    })
</script>

2024.5.30

Array

  • join 返回字符串 ,数组元素拼接
  • find 查找元素
  • every 检验数组所有元素是否都符合指定条件
  • some 检验数组中的元素是否满足
  • concat 合并数组
  • sort 排序
  • splice 删除元素
  • reverse 反转
  • fondIndex 查找元素的索引值
  • map 返回数组
  • filter 过滤数组
  • fill 填充

把伪数组转换成真数组

  • Array.from(lis)
  • [...list]也可以

String

  • length string长度
  • split 分割字符串为数组
  • substring 截取字符串
  • startsWith 判断是不是以某个字符开头
  • includes 是否包含
  • toUpperCase 转换为大写
  • toLowerCase 转换为小写
  • indexOf
  • endWith 判断是不是以某个字符结束
  • replace 替代
  • match 匹配

今日案例:购物车模块

<script> 
const list = document.querySelector('.list')
    const amount = document.querySelector('.amount')
    //1.渲染页面
    list.innerHTML = goodsList.map(item => {
      const { picture, name, spec, price, count, gift } = item
    //二元选择器
      const str = gift ? gift.split(',').map(function (item) {
        return `
          <span class="tag">【赠品】 ${item}</span>`
      }).join('') : ''
      return `  
      <div class="item">
      <img src="${picture}" alt="">
      <p class="name">${name} ${str}</p>
      <p class="spec">${Object.values(spec).join('/')}</p>
      <p class="price">${price.toFixed(2)}</p>
      <p class="count">${count}</p>
      <p class="sub-total">${((price * 100 * count) / 100).toFixed(2)}</p>
    </div>
      `
    }).join('')
    acount.innerHTML = goodsList.reduce(function (prev, current) {
      return prev + current.count * current.price
    }, 0).toFixed(2)
</script>

2024.5.31

两种编程思想

面向过程编程

分析出解决问题所需要的步骤,然后利用函数把这些步骤一步步实现,使用的时候再依次调用

性能更高

面向对象编程OOP

把事物分解成 一个个对象,由对象之间分工与合作

更加灵活,适合多人合作的大型软件项目

特性:继承、封装、多态

构造函数体现了封装的特性、很好用但是存在浪费内存的问题

原型 prototype

本质上也是个对象,用于解决构造函数浪费内存的问题

可以把不变的方法,直接定义在prototype对象上面,这样所有对象的实例就可以共享这些方法

构造函数和原型对象

constructor属性

每个原型对象里面都有个constructor属性

该属性指向该原型对象的构造函数,就是指向我的爸爸

对象原型

在实例对象里面指向原型对象

对象都会有一个属性__proto__指向构造函数prototype的原型对象,之所以我们对象可以构造函数prototype原型对象的属性和方法,就是因为对象有__proto__

原型继承

原型链

Person.prototype.__proto__===Object.prototype (true)

基于原型对象的继承使得不同构造函数的原型对象关联在一起,

是一个查找规则 先查找当前身上有没有该属性,没有就依次往上查找指到找到object对象为止

intanceof

用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上

深浅拷贝

浅拷贝

拷贝的是地址 不会影响原来的

  • 1.拷贝对象 object.assign()
  • 2.拷贝数组 array.prototype.concat or [...arr]

直接赋值 赋值的是地址 只要是对象都会互相影响

浅拷贝 如果是一层对象,不相互影响,如果出现多层对象拷贝还会互相影响

深拷贝

拷贝的是对象不是地址

  • 通过递归 利用递归函数实现setTimeout模拟setInterval效果
  • lodash/cloneDeep
  • JSON.stringify()
深拷贝

1.新对象不会影响旧对象,用到函数递归

2.遇到普通元素直接拷贝就行

3.遇到数组元素再次运行这个拷贝函数就行了

4.遇到对象形式,再次利用递归解决 先array后对象

lodash
  • 先引入lodash
  • 在调用 _.cloneDeep(obj)
JSON.stringify()

异常处理

可以提高代码的健壮性

throw抛异常

会终止程序

throw new error ''

try/catch 捕获错误信息

try{}

catch(err){

consolo.log(err.message)

}

finally {

//不管怎么样都会执行的代码

}

debugger

this

箭头函数没有this

在开发中使用箭头函数前需要考虑函数中this的值,因此DOM事件回调函数如果里面需要DOM对象的this,则不推荐使用箭头函数

原型对象也不推荐使用箭头函数

适用于需要使用上层this的地方

改变this

call()

fun.call(thisArg,arg1,arg2) thisArg是指的fun的this指向,后面是参数传递

apply()

fun.apply(thisArg,[argsArray])

参数必须以数组形式传递进入

可以用与求最大值

const max = Math.max.apply(Math,[1,2,3])

bind()

fun.bind(thisArg,arg1,arg2)

bind() 不会调用函数

防抖 debounce

单位时间内,频繁触发事件 只执行最后一次

-.debounce(func,wait=0,options=)

手写防抖函数

核心是利用setTimeout定时器实现的

1.声明定时器变量

2.每次鼠标移动的时候都要先判断是否有定时器,如果有就先清楚以前的定时器

3.如果没有定时器,就开启定时器,存入到定时器变量里面

4.定时器里面写函数调用

节流 throttle

在单位时间内,频繁触发事件,只执行一次

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值