JavaScript性能优化4——循环添加事件实现
Posted JIZQAQ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript性能优化4——循环添加事件实现相关的知识,希望对你有一定的参考价值。
目录
一、需求
现在我们的页面上有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,我们只需要开辟一个空间存一下我们的匿名函数,这个函数在被调用的时候进栈,有一个执行上下文执行。执行完了之后发现全局也并没有对它进行引用,当前的栈空间立马被释放。
所以这种做法无论是在内存上面,还是在数据存取访问的深度上面都是最优的。
以上是关于JavaScript性能优化4——循环添加事件实现的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript性能优化9——减少判断层级减少循环体活动