深入浅出this&e.target

本文介绍了JavaScript中this的指向问题,特别是在函数、事件和箭头函数中的不同表现。详细阐述了事件委托的概念,解释了其在优化性能方面的优势,并通过实例展示了如何使用事件委托实现动态内容的交互。同时,讨论了事件委托的优缺点以及如何避免不必要的事件绑定。最后,对比了JavaScript原生事件处理与jQuery事件代理的差异。
摘要由CSDN通过智能技术生成

this与target和事件委托的相爱相杀

如何让我们写最少的代码,干最多的活呢?有的时候this&target用好了可以让我们如鱼得水。在前端初学者中,肯定有部分人对this的指向是模糊的。

首先在使用this之前我们应该搞清楚this指向的问题

1.函数中的this:指向Window。
我们肯定听过一局话this指向调用者,为什么下文的的函数是指向Window呢?

 function that() {
    console.log(this)   //输出Window
 }
 //这里明明只写了that() 为什么会指向Window呢?
 that()

其实我们完整的写法是Window.that(),作为顶级对象的Window,你只要全局声明函数&var 声明变量都会挂载到Window身上(这有点违反常理)我声明就想我自己玩跟你Window有啥关系,es6新语法let、const声明的变量&函数就不会挂载到Window身上,来我们看以下代码。

 function that() {
    console.log(this)
 }

      var a = 0
      let b = 1
      const c = 1
      console.log(window.that)
      console.log(window.a)      
      console.log(window.b)
      console.log(window.c)

输出结果:

image.png

但是现在又有新问题了,为什么同样是全局声明凭啥你们两个搞特殊呢?

在ES5中,顶层对象的属性和全局变量是等价的,var 命令和 function 命令声明的全局变量,自然也是顶层对象。

但ES6规定,var 命令和 function 命令声明的全局变量,依旧是顶层对象的属性,但 let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性

在事件当中this 指向的是注册事件的对象

<div>我是div</div>
document.querySelector('div').addEventListener('click', function () {
     console.log(this)
})
//输出内容

image.png

在箭头函数中this 指向最近作用域中对象的this,例如:

<div>我是div</div>
document.querySelector('div').addEventListener('click', () => {
        console.log(this)
 })
 //输出内容

image.png

箭头函数在事件当中要慎用,当然他也有秒用比如我们现在要做一个功能,点击按钮时按钮禁用,2秒后解除禁用

<button>发送短信</button>
document.querySelector('button').addEventListener('click', function () {
        this.disabled = true
        //第一种
        // let that = this
        // setTimeout(function () {
        //   that.disabled = false
        // }, 2000)
        //第一种

        //第二种
        // setTimeout(
        //   function () {
        //     this.disabled = false
        //   }.bind(this),
        //   2000
        // )
        //第二种

        // 第三种
        setTimeout(() => {
          this.disabled = false
        }, 2000)
      })

实现这个功能我们可以声明变量保存this,也可以使用bind方法改变this的调用者,但无疑使用箭头函数是最方便的。

事件委托

事件委托在jquery中叫事件代理

如果我们不用事件委托给ul中的里添加事件

<!-- 这里就不写样式了 -->
    <ul></ul>
    <script>
      let html = ``
      //循环
      for (let i = 0; i < 10; i++) {
        // let li = document.createElement('li')
        // li.innerHTML = `我是第${i}个li`
        // document.querySelector('ul').appendChild(li)
        //字符串的拼接的效率高一些
        html += `<li>我是第${i}个li</li>`
      }
      document.querySelector('ul').innerHTML = html
      //获取所有的li标签
      let lis = document.querySelectorAll('li')
      //循环lis 给所有的li添加事件 这里使用ES6新特性for of
      for (let item of lis) {
        item.addEventListener('click', function () {
          //点击li 之后首先要清空所有的li 里面的颜色
          for (let items of lis) {
            items.style.backgroundColor = ''
          }
          //这里的this 指向我们点击时的对象(li)
          this.style.backgroundColor = 'red'
        })
      }

想想如果我们有更多的li 标签 点击一次就要循环所有的li 太影响性能了。

事件委托给li 添加事件

      let html = ``
      for (let i = 0; i < 10; i++) {
        html += `<li>我是第${i}个li</li>`
      }
      document.querySelector('ul').innerHTML = html
      let lis = document.querySelectorAll('li')
      document.querySelector('ul').addEventListener('click', (e) => {
        //e是事件对象  这里为了让代码看起来简洁一点使用了 es6 的箭头函数
        for (let item of lis) {
          item.style.backgroundColor = ''
        }
        e.target.style.backgroundColor = 'red'
      })

事件委托的优点:

1.可以大量节省内存占用,减少事件注册。

2.可以实现当新增子对象时,无需再对其进行事件绑定,对于动态内容部分尤为适合。

事件委托的缺点:

1.事件委托的实现依靠的冒泡,因此不支持事件冒泡的事件就不适合使用事件委托。

2.不恰当使用反而可能导致不需要绑定事件的元素也被绑定上了事件。

我们可以解决让不想绑定的元素不触发,只需要一个判断就行了

     let html = ``
      for (let i = 0; i < 10; i++) {
        html += `<li>我是第${i}个li</li>`
      }
      document.querySelector('ul').innerHTML = html
      let lis = document.querySelectorAll('li')
      document.querySelector('ul').addEventListener('click', (e) => {
        //e是事件对象  这里为了让代码看起来简洁一点使用了 es6 的箭头函数
        // console.log(e)  我们打印 事件对象 找到target对象中的nodeName 或者 localName 进行判断
        //注意:不加判断点到ul身上就会出bug
        if (e.target.nodeName == 'LI') {
          for (let item of lis) {
            item.style.backgroundColor = ''
          }
          e.target.style.backgroundColor = 'red'
        }
        console.log(`你没点击li`)
      })

使用事件委托:首先我们要清楚事件委托是利用事件冒泡的机制,在我们对元素产生行为时事件冒泡就触发了(当前元素>父元素>body>html)结束,除了事件冒泡还有事件捕获,事件捕获的机制是跟事件冒泡相反的(html>body>父元素>当前元素)但我们在实际开发中大部分的情况下都是使用事件冒泡的机制,对于事件捕获我们有一个概念就行。

相比js来说jquery的事件代理就简单的多,在jQuery中我们事件排他是不用循环的,它的底层隐式迭代帮我们处理了,但jQuery还是逃不出前端技术的迭代

      let html = ``
      for (let i = 0; i < 10; i++) {
        html += `<li>我是第${i}个li</li>`
      }
      $('ul').html(html)
      $('ul').on('click', 'li', function () {
        $(this).addClass('red').siblings('.red').removeClass('red')
      })
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值