我的前端笔记JS

软件

        截图软件

        放大和画笔软件

js介绍

        js是编程语音,之前学的html和css是标记语言

        百度搜索mdn官网就可以

语法

        输出、对话框、控制台日志、输入对话框

字面量

        简单理解就是看到的内容是属于什么类型,例如1232,这个是属于数字字面量

变量

        输入并保存数据

        交互两个变量

        变量本质

        变量就是在内存开辟一个空间临时存储数据

        变量命名的规则和规范

        数组长度=length+1

        常量const

        字面量和常量的区别,字面量类似于常量类型总称,常量是某个具体的值

        数据类型

       

NaN

        模板字符串

        作用: 优化书写方式

        未定义变量undefined

        空Null

null和undefined的区别

        检测数据类型

        数据转换

仔细看看案例和输出结果(注意promot输入后接收到的数据都被统一转成string)

        表格输入的案例

一元运算符

 if语句

       若里面为空字符串,则为false,有字符则为true

        三元运算符

断点

        打完断点记得要刷新才能使用

循环

continue记得要加自增,而且要在前面,可以走一下下面的流程

        for循环

        数组的增删改查

若没有带上数量则,会从起始位置删到最后,返回的也是删除的内容

        冒泡排序

        性能一般般,将值进行升序或降序排列

        一般用arr.sort()

函数

        函数作用

        函数命名

        函数调用

                函数名(),括号一定要加上

        数组的默认参数可以这样写

        若返回的值是多个可以使用数组

break结束的是循环,return结束的是函数

        全局作用域对局部作用域也是有效的,局部作用域或局部变量简单理解就是函数内的变量

注意这种未声明的变量也是属于全局变量,就算是在局部里,另外函数的参数也属于局部变量

若函数是嵌套写法,则函数内的参数是就近原则,答案为123

需要注意的是,匿名函数,在使用fn()时候,不能在函数的前面执行。而具名函数可以在任意位置使用

立即执行函数,不用调用,直接执行,其特点是不用担心变量之间的干扰,但多个立即执行,切记要用分号隔开,否则报错

这两种写法都可以

        逻辑中断

        若&&都为真返回后面的值,||为真则返回真值,若两个都为真值则返回第一个

        默认值也可以参考这种写法

对象

        对象添加方法的格式

        对象里的属性是无序的

若属性名用’‘引号框起来(一般用于user-name,因为调用时会把-当成减符号),则只能用第二种方法调用

函数在对象里面叫方法

若直接打印方法且该方法没有return则会返回undefined

        遍历对象

        遍历数组对象

除了第一行其他的都变色

        

        Math

可以做成方法

注意若title里有空格则需要加双引号包裹,否则空格后面的不会显示

引用数据类型和基本数据类型(js理论上是没有堆和栈,只是参考其他语言)

WebApi

        const使用

        对象和数组尽量用const声明为常量,因为是引用数据类型,为了防止别人调用我们地址,改了地址后,无法查询到问题(一般地址都不改,只改变里面的值,具体可以参考上面的内存图)。基本数据类型或须要改变引用数据类型的地址的可以使用let

        DOM

        如何调用

        注意:若选择带all的获取的对象都是伪数组,就算数组里只有一个对象,也须要用fori进行遍历,注意是fori,不是forin。不带all的是获取第一个匹配到的元素,若没有则返回null

        如何修改

        用innerHTML就行,能识别标签,没有带HTML的就识别不出来

        注意用inner时的格式是等号,等号右边如果是引号则为文字,可以直接接变量

        操作css样式

        通过style操作,注意这个是在行内加样式,如果要提带它须要用!important

        通过类名调用

        如果须要调用多个类名可以在box1里空格前后调用

        若有相同css属性,则看style里的位置,后面覆盖前面

        classList

        详细看看这段代码

        操作表单

        text

        checkbox属性checked,button属性disabled

        自定义属性

        

        dataSet是data对象,里面是dom对象的即标签的所有data属性,简单理解即获取的是单个标签里的所有data属性

        定时器-间歇函数

        不能用fn(),加了()代表立即执行

        执行时间是先计时1次后才开始打印输出

如果会变,需要用setinterval,如果不会变只是单纯的计时,则用setTimeout

用户注册倒计时

事件监听

        在编写代码时,如果有多个输入框,则可以用‘[属性名]’

        ipt.value可以获取用户输入的内容

        css里focus用法

        获取标签的id属性的用法,和用户输入内容的长度的获取用法tx.value.length

        事件对象

        e返回的是事件的对象,可以查看对象之后调用自己要的,例如e.key即获得焦点后按下的键盘按键。

        e.key和tx.value的区别以及trim()的用法

        e.key是获取按的是键盘的哪个键,tx.value是输入的哪些值,tx.value.length是获取输入内容的长度

        trim()是用来清除文字两侧的空格,但文字之间的空格不会清除

        注意:如果要用到清空内容,直接给它赋值个空字符串

        环境对象this

        谁调用指向谁

        回调函数

        active的调用注意事项

        复选框的案例,伪类选择器的应用

        事件流

        冒泡流和捕获流,捕获流了解即可

mouseover:当鼠标移入元素或其子元素都会触发事件,所以有一个重复触发,冒泡过程。对应的移除事件是mouseout

mouseenter:当鼠标移除元素本身(不包含元素的子元素)会触发事件,也就是不会冒泡,对应的移除事件是mouseleave

        同名事件指的是例如图片代码里的点击,非同名事件是不会影响的

        解绑事件

        事件委托

        好处:不需要从子集一个一个注册事件,直接给父级注册事件

        先console.log打印事件对象,找到target,e.target输出的是你点击的元素

        若父级里包含了多种标签,如何区分?需要获取点击的子级名称,要用console.dir(e.target),找到tagName,e.target.tagName返回的是你点击的是哪个标签,注意此处获取的是标签名,不是你点击的元素

        实际要修改的还是e.target

 案例

        document.querySelector,写在事件外面只是固定的,写在里面是事件触发了之后才会执行

阻止跳转

给form阻止是因为链接在form身上

其他事件

        页面加载事件(了解)

        元素/页面滚动事件

        

document.documentElement就是HTML元素,可以打印输出看看,赋值不需要给单位

一般用于电梯导航

        页面尺寸事件

可以通过js获取盒子宽度

        元素尺寸及位置

offsetwidth和clientwidth的区别就是一个包含border一个不包含

offsetLeft注意定位父级的特点

应用

bilibili案例

则会个是相对视口的距离,了解即可

css网页的丝滑移动

小兔先电梯导航完整案例:(有点复杂具体还得看视频)

   <!-- 其它 -->
    <div class="extra">
      <div class="wrapper">
        <!-- 口号 -->
        <div class="slogan">
          <a href="javascript:;" class="price">价格亲民</a>
          <a href="javascript:;" class="express">物流快捷</a>
          <a href="javascript:;" class="quality">品质新鲜</a>
        </div>
        <!-- 版权信息 -->
        <div class="copyright">
          <p>
            <a href="javascript:;">关于我们</a>
            <a href="javascript:;">帮助中心</a>
            <a href="javascript:;">售后服务</a>
            <a href="javascript:;">配送与验收</a>
            <a href="javascript:;">商务合作</a>
            <a href="javascript:;">搜索推荐</a>
            <a href="javascript:;">友情链接</a>
          </p>
          <p>CopyRight &copy; 小兔鲜儿</p>
        </div>
      </div>
    </div>
  </div>
  <!-- 电梯 -->
  <div class="xtx-elevator">
    <ul class="xtx-elevator-list">
      <li><a href="javascript:;" data-name="new">新鲜好物</a></li>
      <li><a href="javascript:;" data-name="popular">人气推荐</a></li>
      <li><a href="javascript:;" data-name="brand">热门品牌</a></li>
      <li><a href="javascript:;" data-name="topic">最新专题</a></li>
      <li><a href="javascript:;" id="backTop"><i class="sprites"></i>顶部</a></li>
    </ul>
  </div>

  <script>
    (function () {
      const entry = document.querySelector('.xtx_entry')

      const elevator = document.querySelector('.xtx-elevator')

      window.addEventListener('scroll', function () {
        const n = document.documentElement.scrollTop
        // console.log(document.documentElement.scrollTop);
        if (n >= entry.offsetTop) {
          elevator.style.opacity = '100'
        } else {
          elevator.style.opacity = '0'
        }
      })

      const bt = document.querySelector('#backTop')
      bt.addEventListener('click', function () {
        document.documentElement.scrollTop = 0
      })
    })();

    (function () {

      const ul = document.querySelector('.xtx-elevator-list')

      ul.addEventListener('click', function (e) {


        if (e.target.tagName === 'A' && e.target.dataset.name) {
          const old = document.querySelector('.xtx-elevator-list .active')
          if (old) {
            old.classList.remove('active')
          }
          e.target.classList.add('active')


          // console.log(e.target.dataset.name);

          const top = document.querySelector(`.xtx_goods_${e.target.dataset.name}`).offsetTop

          document.documentElement.scrollTop = top
        }
      })

      window.addEventListener('scroll', function (e) {

        const old = document.querySelector('.xtx-elevator-list .active')
        if (old) {
          old.classList.remove('active')
        }

        const news = document.querySelector('.xtx_goods_new')
        const popular = document.querySelector('.xtx_goods_popular')
        const brand = document.querySelector('.xtx_goods_brand')
        const topic = document.querySelector('.xtx_goods_topic')
        const top = document.documentElement.scrollTop

        // console.log(ul.dataset);
        if (top >= news.offsetTop && top < popular.offsetTop) {
          document.querySelector('[data-name=new]').classList.add('active')
        } else if (top >= popular.offsetTop && top < brand.offsetTop) {
          document.querySelector('[data-name=popular]').classList.add('active')
        } else if (top >= brand.offsetTop && top < topic.offsetTop) {
          document.querySelector('[data-name=brand]').classList.add('active')
        } else if (top >= topic.offsetTop) {
          document.querySelector('[data-name=topic]').classList.add('active')
        }

      })
    })();

属性选择器[]

        时间

没有要求的话,可以用这种写法

时间戳

        一般用来计算倒计时

        时间戳以毫秒来计算

星期的用法

倒计时案例

注意用的是秒数秒数

查找DOM节点

父级的父级可以多次调用parentNode

元素节点就是标签节点

新增节点

克隆节点

删除节点

M事件(手机或平板触屏的)

JS插件(M端插件)

按照说明走就行

学生表单案例

BOM

定时器-延时函数

间歇函数是会循环的,而延时函数是执行完不再执行

JS执行机制

location对象

倒计时自动跳转

        

一般获取的是用户表单提交的数据

hash一般是用于获取,页面内跳转的部分(当前页面跳转,整个页面是不会刷新的)

刷新和强制刷新

Navigator

        一般用于获取浏览器版本,然后用于切换pc和移动端界面(自动)

history

本地存储

sessionStorage是关闭浏览器后才清除数据

在本地存储对象时,需要先转成JSON字符,取的时候需要转成对象

数组中Map方法和join方法

注意map返回的是数组

学生就业统计表案例

  <script>
    // 参考数据
    const initData = [
      {
        stuId: 1,
        uname: '迪丽热巴',
        age: 22,
        salary: '12000',
        gender: '女',
        city: '北京',
        time: '2099/9/9 08:08:08'
      }
    ]

    
    // localStorage.setItem('obj', JSON.stringify(initData))

    // arr.push(JSON.parse(localStorage.getItem('obj')))

    const arr = JSON.parse(localStorage.getItem('obj')) || []

    const tbody = document.querySelector('tbody')
    const span = document.querySelector('.title span')

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

      // console.log(obj.join(''))
      tbody.innerHTML = obj.join('')

      span.innerHTML = arr.length

    }

    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('输入内容不能为空')
      }
      
      arr.push({
        stuId: arr.length ? arr[arr.length-1].stuId+1:1,
        uname: uname.value,
        age: age.value,
        salary: salary.value,
        gender: gender.value,
        city: city.value,
        time: new Date().toLocaleString()
      })

      localStorage.setItem('data',JSON.stringify(arr))
      render()

      this.reset()
    })

    
    tbody.addEventListener('click',function(e){
      if(e.target.tagName ==='A'){
       if(confirm('您确认要删除这条数据吗?')){
        arr.splice(e.target.dataset.id,1)
        render()
        localStorage.setItem('data',JSON.stringify(arr))

       }
      }
    })

正则表达式

元字符

注意^和¥在一起,内容和数量必须是一致的,首先内容要有

量词

字符类

修饰符

登录注册案例

验证码

change事件,就是输入框有变化了才会触发

判断输入是否符合要求

 // 获取验证码按钮
    const code = document.querySelector('.xtx-form-item .code')

    let flag = true

    code.addEventListener('click', function () {

      if (flag) {
        flag = false
        let i = 5
        code.innerHTML = `${i}秒后重新获取`
        code.style.color = '#B6B6B6'
        code.style.cursor = 'default'

        const timer = setInterval(function () {
          i--

          if (i > 0) {
            code.innerHTML = `${i}秒后重新获取`
            code.style.color = '#B6B6B6'
            code.style.cursor = 'default'

          } else {
            clearInterval(timer)
            code.innerHTML = `发送验证码`
            code.style.color = '#27BA9B'
            code.style.cursor = 'pointer'
            flag = true
          }

        }, 1000)
      }
    })


    // 输入用户名
    const username = document.querySelector('[name=username]')


    username.addEventListener('change', verifyName)

    function verifyName() {
      const span = username.nextElementSibling
      if (/^\d{6,10}$/.test(username.value)) {
        span.innerHTML = ''
        return true
      } else {
        span.innerHTML = '输入不合法,请输入6~10位数字'
        return false
      }
    }

    // 输入手机号码
    const phone = document.querySelector('[name=phone]')


    phone.addEventListener('change', verityPhone)

    function verityPhone() {
      const span = phone.nextElementSibling
      if (/^1(3\d|4[5-9]|5[0-35-9]|6[567]|7[0-8]|8\d|9[0-35-9])\d{8}$/.test(phone.value)) {
        span.innerHTML = ''
        return true
      } else {
        span.innerHTML = '输入不合法,请输入11位手机号'
        return false
      }
    }

    // 输入验证码
    const codeInput = document.querySelector('[name=code]')


    codeInput.addEventListener('change', verityCode)

    function verityCode() {
      const span = codeInput.nextElementSibling
      if (/^\d{6}$/.test(codeInput.value)) {
        span.innerHTML = ''
        return true
      } else {
        span.innerHTML = '输入不合法,请输入6位数字'
        return false
      }
    }


    //输入密码
    const password = document.querySelector('[name=password]')


    password.addEventListener('change', verifyPwd)

    function verifyPwd() {
      const span = password.nextElementSibling
      if (/^\d{6,20}$/.test(password.value)) {
        span.innerHTML = ''
        return true
      } else {
        span.innerHTML = '输入不合法,请输入6~20位数字字母符号组成'
        return false
      }
    }


    //确认密码
    const confirm = document.querySelector('[name=confirm]')


    confirm.addEventListener('change', verifyConfirm)

    function verifyConfirm() {
      const span = confirm.nextElementSibling
      if (password.value === confirm.value) {
        span.innerHTML = ''
        return true
      } else {
        span.innerHTML = '两次密码输入不一致'
        return false
      }
    }

    // 勾选协议
    const queren = document.querySelector('.icon-queren')
    queren.addEventListener('click', function () {
      this.classList.toggle('icon-queren2')
    })

    // 提交模块
    const form = document.querySelector('form')
    form.addEventListener("submit", function (e) {
      // 判断某个标签是否包含某个属性
      if (!queren.classList.contains('icon-queren2')) {
        alert('请勾选同意协议')
        e.preventDefault()

      }

      if (!verifyName()) e.preventDefault()
      if (!verityPhone()) e.preventDefault()
      if (!verityCode()) e.preventDefault()
      if (!verifyPwd()) e.preventDefault()
      if (!verifyConfirm()) e.preventDefault()
    })

required可以直接让输入框不能非空提交

表单里的autocomplete关闭掉后作用是关闭拉框记录

如果存本地数据,为对象才需要转json,否则可以直接存

 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 agree = document.querySelector('[name=agree]')
    const username = document.querySelector('[name=username]')

    form.addEventListener("submit", function (e) {
      e.preventDefault()
      if (!agree.checked) {
        return alert('请同意协议后登录')
      }

      localStorage.setItem('xtx-uname', username.value)
      // 跳转网页
      location.href = './index.html'

    })

 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>'
      }
    }

    render()

    li2.addEventListener('click', function () {
      localStorage.removeItem('xtx-uname')
      render()
    })

        图片切换案例

js高级

        闭包的用法:一般用于访问函数内的变量

        闭包的形成条件,函数内层函数+内层函数调用外层函数的变量

闭包的作用可以防止被外部修改变量

动态参数

剩余参数

展开运算符

箭头函数(重要)

只能用于函数

箭头函数只能用剩余参数

箭头函数没有this,只会往上一级找

数组解构

多维数组

对象解构

注意解构名必须和对象属性一致,另外对象名不能被其他变量使用

如果要改名可以用这种方式

数组对象的解构

 <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选出当做参数传递给 函数

    function render({ data }) {
      // 我们只要 data 数据
      // 内部处理
      console.log(data);

    }
    render(msg)

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

    }
    render(msg)

  </script>

foreach

一般用于遍历对象数组

fliter

遍历过滤器

注意:

格式都一样

map是有返回值,且一般用于赋值操作,例如+-

filter,也有返回值,但一般使用筛选操作,例如<>

forEach没有返回值,只是用于遍历,一般用于对象数组遍历

//css可以直接写点击事件
    .filter a:active,
    .filter a:focus {
      background: #05943c;
      color: #fff;
    }


js

function render(arr) {
      let str = ''

      arr.forEach(list => {
        const { name, price, picture } = list
        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)


    document.querySelector('.filter').addEventListener('click', e => {
      const { tagName, dataset } = e.target

      if (tagName === 'A') {
        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)
      }
    })

构造函数(自定义函数)

结构是静态对象,里面有静态成员,包含静态属性和静态方法

new对象是实例对象,里面是实例成员,包含实例属性,和实例方法

内置构造函数

Object静态方法

Array

对象累加

查找符合要求的对象

join

伪数组转为真数组

String

字符串截取

以指定字符开头和包含

Number

原型

为了减少在构造函数时相同的方法产生内存浪费

constroctor指回原来的函数


    //公共的属性写在构造函数里
    function Person(uname, age) {
      this.uname = uname
      this.age = age
    }
    //公共的方法写在原型对象上
    Person.prototype.sing = function () {
      console.log('唱歌')
    }
    const r1 = new Person('来1', 12)
    const r2 = new Person('来2', 22)

    r1.sing()
    r2.sing()

    //这种构造出来的方法可以公用
    Array.prototype.max = function () {
      return Math.max(...this)
    }

    console.log([1, 2, 3, 4].max())

    Array.prototype.sum = function () {
      return this.reduce((prev, item) => prev + item, 0)
    }
    console.log([1, 2, 3, 4].sum())

    console.log('-----------prototype原型对象--------------')
    function Star() {
    }

    console.log(Star.prototype)

    //一次性给赋值多个
    Star.prototype = {
      //每次必须指回构造函数否则找不到父级
      constructor: Star,

      sing: function () {
        console.log('唱歌')
      },
      dance: function () {
        console.log('跳舞')
      }
    }


    const ldh = new Star()
    console.log(Star.prototype)
    console.log(Star.prototype.constructor === Star)

    ldh.sing()
    ldh.dance()

    console.log('-----------__proto__对象原型--------------')
    //一边两个下横杠,一共四个下横杠
    console.log(ldh.__proto__)
    console.log(ldh.__proto__ === Star.prototype)







    console.log('-----------原型继承--------------')
    //如果用对象,原型指向的是同一个对象
    // const Person1 = {
    //   eays: 2,
    //   head: 1
    // }


    function Person1() {
      this.eays = 2
      this.head = 1
    }

    function Woman() {

    }

    Woman.prototype = new Person1()
    Woman.prototype.constructor = Woman
    Woman.prototype.baby = function () {
      console.log('宝贝')
    }

    const red = new Woman()
    console.log(red)
    console.log(red.__proto__)

    function Man() {

    }
    Man.prototype = new Person1()
    Man.prototype.constructor = Man
    const red1 = new Man()
    console.log(red1)
    console.log(red1.constructor)
    console.log(Object.constructor)

    //判断两个对象是否在同一条原型链上
    console.log(red1 instanceof Person1) //true
    console.log(red1 instanceof Array) //false

 function Modal(title = '', message = '') {
      this.modalBox = document.createElement('div')
      this.modalBox.className = 'modal'
      this.modalBox.innerHTML = `
        <div class="header">${title} <i>x</i ></div>
        <div class="body">${message}</div>
      `
      console.log(this.modalBox);
    }

    // new Modal('温馨提示', '您没有删除权限操作')
    // new Modal('温馨提示2', '您没有删除权限操作2')


    //注意若用this,千万不能用箭头函数
    Modal.prototype.open = function () {
      // 只显示一个显示框
      const box = document.querySelector('.modal')
      box && box.remove()


      document.body.append(this.modalBox)
      // 要等盒子出现再绑定事件
      //要用箭头函数,使用箭头函数就会跳过原本调用自己的对象,向上找一级,若使用普通函数,则this调用的是当前调用者,不用this可以随意使用箭头函数
      this.modalBox.querySelector('i').addEventListener('click', () => {
        this.close()//this.modalBox
      })
    }

    Modal.prototype.close = function () {
      this.modalBox.remove()
    }

    document.querySelector('#delete').addEventListener('click', () => {
      const del = new Modal('温馨提示', '您没有删除权限操作')
      del.open()
    })

    document.querySelector('#login').addEventListener('click', () => {
      const del = new Modal('友情提示', '您没有登录权限')
      del.open()
    })

    document.querySelector('#add').addEventListener('click', () => {
      const del = new Modal('强烈提示', '新增成功')
      del.open()
    })

深拷贝

json最简单

//深拷贝和浅拷贝区别:地址对象里是否含有地址对象,若含有则为深拷贝
    //深拷贝需要用到函数递归,普通拷贝直接赋值即可
    //先Array再Object,Object一定要放最后
    const obj = {
      uname: 'pink',
      age: 18,
      hobby: ['乒乓球', '足球'],
      family: {
        baby: '小pink',
        hobby1: ['乒乓球', '足球']
      }
    }
    const o = {}

    function deepCopy(newObj, oldObj) {
      for (let k in oldObj) {
        if (oldObj[k] instanceof Array) {
          newObj[k] = []
          deepCopy(newObj[k], oldObj[k])
        } else if (oldObj[k] instanceof Object) {//注意Object要放后面判断,因为所有对象都属于Object
          newObj[k] = {}
          deepCopy(newObj[k], oldObj[k])
        } else { newObj[k] = oldObj[k] }

      }
    }

    deepCopy(o, obj)

    console.log(o);
    obj.hobby[0] = 20
    obj.family.hobby1[0] = 11
    console.log(obj)



-------------------------------------------------lodash


  <script src="./lodash.min.js"></script>
  <script>


    const obj = {
      uname: 'pink',
      age: 18,
      hobby: ['乒乓球', '足球'],
      family: {
        baby: '小pink',
        hobby1: ['乒乓球', '足球']
      }
    }
    const o = _.cloneDeep(obj)

    console.log(o);
    obj.hobby[0] = 20
    obj.family.hobby1[0] = 11
    console.log(obj)


-----------------------------------------JSON
const obj = {
      uname: 'pink',
      age: 18,
      hobby: ['乒乓球', '足球'],
      family: {
        baby: '小pink',
        hobby1: ['乒乓球', '足球']
      }
    }
    const o = JSON.parse(JSON.stringify(obj))

    console.log(o);
    obj.hobby[0] = 20
    obj.family.hobby1[0] = 11
    console.log(obj)

快速debugger

this注意

防抖和节流

  <style>
    .box {
      width: 500px;
      height: 500px;
      background-color: #ccc;
      color: #fff;
      text-align: center;
      font-size: 100px;
    }
  </style>
</head>

<body>
  <div class="box"></div>

  <script src="./lodash.min.js"></script>
  <script>
    const box = document.querySelector('.box')
    let i = 1
    function mouseMove() {
      box.innerHTML = i++
    }
    //防抖语句(每停止操作后执行一次)
    box.addEventListener('mousemove', _.debounce(mouseMove, 1000))
    //节流语句(必须等待执行完才能执行其他操作)
    //box.addEventListener('mousemove', _.throttle(mouseMove, 1000))
  </script>

定时器里不能清除定时器,只能用变量赋值为null

视频节流案例(上次视频播放进度记录)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值