JavaScript性能优化4——循环添加事件实现

目录

一、需求 

二、实现方式

1.闭包和自定义属性方式

代码

分析

2.事件委托方式

代码

分析


一、需求 

现在我们的页面上有3个按钮,我们需要用循环来给按钮添加事件,实现按按钮1的时候打印出当前索引值为0,按按钮2的时候打印出当前索引值为1,按按钮3的时候打印出当前索引值为2.

二、实现方式

1.闭包和自定义属性方式

代码

看下面代码,最开始的时候写了个普通的循环,但是发现并不能满足我们的需求。

于是后面我们倚靠闭包的机制写了另外3段代码和自定义属性写了1段代码,执行过后发现都能够完成我们需要的功能。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>循环添加事件</title>
        
    </head>
    <body>
        <button>按钮1</button>
        <button>按钮2</button>
        <button>按钮3</button>
        <script>
            var aButtons = document.querySelectorAll("button")
            console.log(aButtons)
            //无论点击哪个代码,输出的结果i都是3
            /*
            for(var i = 0;i < aButtons.length;i++){
                aButtons[i].onclick = function() {
                    console.log(`当前索引值为${i}`)
                }
            }
            */
            // 我们需要的是点击第一个按钮输出的i是0,第二个是1,第三个是2
            // 完成我们的需求的话,有下面几种办法
            /*
            * 闭包
            * 自定义属性
            * 事件委托
            */
            //闭包方法1:最普通的方法,把函数改成立刻执行的
            /*
            for(var i = 0;i < aButtons.length;i++){
                (function (i) {
                    aButtons[i].onclick = function() {
                        console.log(`当前索引值为${i}`)
                    }
                })(i)
            }
            */
            //闭包方法2:
            /*
            for(var i = 0;i < aButtons.length;i++){
                aButtons[i].onclick = (function(i) {
                    return function() {
                        console.log(`当前索引值为${i}`)
                    }
                })(i)         
            }
            */
            //闭包方法3:ES6中的let关键词
            /*
            for(let i = 0;i < aButtons.length;i++){
                aButtons[i].onclick = function() {
                    console.log(`当前索引值为${i}`)
                }
            }
            */
           //自定义属性
           for(var i = 0;i < aButtons.length;i++){
                aButtons[i].myIndex = i
                aButtons[i].onclick = function() {
                    console.log(`当前索引值为${this.myIndex}`)
                    //console.log(`当前索引值为${aButtons[i].myIndex}`) 这么写会报错TypeError: Cannot read property 'myIndex' of undefined
                }
            }
        </script>
    </body>
</html>

分析

闭包方法:

自定义属性方法:

上面两个办法对比,我们会发现,其实在自定义属性方法里面,我们并没有开辟新的空间,也就是没有形成所谓的闭包,在内存使用上是比较优秀的。它做的是往已经存在的对象上面添加了属性而已。

闭包其实是个非常优秀的机制,十分方便,便于我们去实现一些高阶的编程,但是在小的细节上比如内存管理这块,是不那么友好的。如果有其他替代方案的时候,也是可以用非闭包的方案实现。

2.事件委托方式

代码

我们在button的html上添加了index属性,每次点击的时候获取按钮的index属性的值并打印

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>循环添加事件</title>
        
    </head>
    <body>
        <button index='0'>按钮1</button>
        <button index='1'>按钮2</button>
        <button index='2'>按钮3</button>
        <script>
            //事件委托
            document.body.onclick = function(ev) {
                var target = ev.target
                targetDom = target.tagName
                if(targetDom === 'BUTTON') {
                    var index = target.getAttribute('index')
                    console.log(`当前索引值为${index}`)
                }
            }
        </script>
    </body>
</html>

分析

因为这里只有一个function,我们只需要开辟一个空间存一下我们的匿名函数,这个函数在被调用的时候进栈,有一个执行上下文执行。执行完了之后发现全局也并没有对它进行引用,当前的栈空间立马被释放。

所以这种做法无论是在内存上面,还是在数据存取访问的深度上面都是最优的。

参考资料

1.拉勾网 《大前端训练营》课程

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值