JavaScript中的数组越界问题

文章介绍了JavaScript中数组越界的概念,并通过一个案例展示了如何通过添加自定义属性和使用ES6的`let`关键字来避免数组越界问题。此外,还探讨了事件委托作为另一种解决数组越界的有效方法,通过将事件处理委托给父元素,简化代码并提高可维护性。
摘要由CSDN通过智能技术生成

JavaScript中数组越界问题

1、了解数组越界

要解决数组越界问题,我们就要先了解到底什么是数组越界:

含义:

1、数组越界就是数组超过了边界。数组索引是从0开始的,你定义的数组长度为5,那么你的脚标就只能是0、1、2、3、4 。向上或向下超过了超过了都是越界。

2、数组越界就是指在进行数组操作时访问了本不属于你的位置。

3、数组越界指的是数组下标变量的取值超过了初始定义时的大小,导致对数组元素的访问出现在数组的范围之外。

2、解决数组越界

接下来通过一个案例理解一下吧!

1、案例中html代码,创建三个<li></li>标签

<ul class="header">           //首先创建三个
        <li  class="active "  >正在热映</li>
        <li  >即将上映</li>
        <li >付费电影</li>
    </ul>

2、css中的渲染代码

 *{
        margin: 0;
        padding: 0;
       }
      ul{
        list-style: none;
        display: flex;
        width: 100%;
      }
.header li{
        /* width: 50%;  */
        flex: 1;
        height: 50px;
        line-height: 50px;
        text-align: center;

      }
.header .active{
        color:blue;
        background-color: red;
        border-bottom: 1px solid red;
      }

运行结果:

在这里插入图片描述

要求:在点击每个标签时,会发生对应的渲染效果,且其他标签不显示。

我们运用css中的知识可以轻松做到,只需给标签属性加上:visited:hover即可,但是这样做的缺点就是,把代码写死,后期更改代码会加大工作量且不易维护。

3、JavaScript核心代码

1、利用自定义属性解决

var res = document.querySelectorAll(".header li")  //利用dom节点获取ul里的各个li标签(返回值是一个伪数组)
for(let i=0;i<res.length;i++){         //给li标签遍历三次点击事件    
      res[i].dataset.index = i      //利用for循环给每一个li标签加上一个自定义属性index=i;
        res[i].onclick=function(){     //创建点击事件,鼠标在点击标签时触发
  
            for(var a=0;a<res.length;a++){
              res[a].classList.remove("active")
            }
         //此时for循环的意义时,在每次点击时,把每一个标签的渲染效果都删除掉,然后通过特殊方法给要点击的找个标签加上渲染效果
            //res[i].classList.add("active")
               /* 此时for循环已经执行完毕啦, 此时i=res.length已经属于索引越界(数组越界)如果使用res[i]会报错未被定义。那么我们前面添加的自定义属性就生效啦 */
            res[this.dataset.index].classList.add("active")  //this用法。此时this指向我们所点击的li标签

          }
        
    }

利用自定义的属性的方法:重在理解如何利用循环给每个标签都加上自定义属性,并熟悉如何获取自定义属性值。

2、利用es6中的知识let解决。

let是我们在es6学习中,又一定义变量的方法,且很容易解决上述问题。

let和var的区别

1、var。

我们在es5中定义变量使用var定义。此时var定义的是全局变量。

例:

for(var i=0;i<5;i++){
    console.log(i);
   }
   console.log(i);

运行结果:

在这里插入图片描述

通过上述代码我们可以两个问题:

第一:我们在for循环中定义的i值,为什么可以在for循环外还可以被使用?

​ 答:此时我们用var定义的变量为全局变量,在for循环外也可以使用。

第二:为什么我们定义的是i<5,为什么i最后打印出来会是i=5呢?

​ 答:这就是for循环的运行机制,先判断,后++。当运行到i=5时,判断i不小于5,此时循环结束,

i=5被打印出来。所以说for循环和数组、鼠标点击事件在一起使用时极易发生报错。

2.let

let是es6中学习的定义变量的另一方法。let定义局部变量。通俗讲就是只在当前定义的{}内生效。

例:

for(let i=0;i<5;i++){   //用let定义变量
    console.log(i);
   }
   console.log(i);

运行结果:

在这里插入图片描述

我们可以轻松看到,在for循环中用let定义的i值,在循环外不可以调用。

所以说,我们要解决上述的数组越界问题,非常简单的解决。

 var res = document.querySelectorAll(".header li")
    
    for(let i=0;i<res.length;i++){             
     
        res[i].onclick=function(){      //而let是局部变量,只在本次循环中生效。
            
            for(var a=0;a<res.length;a++){
              res[a].classList.remove("active")
            }
          /*  1、 使用自定义属性解决方案: */
            // res[this.dataset.index].classList.add("active")

            // /* 2、使用let定义解决方案: */
            console.log(i); //此时打印i值,和上面res[i].οnclick=function()中的i值相同
            res[i].classList.add("active")
           
          }
        
    }

通过let定义变量的方法,我们可以轻易解决问题。后续会有更简便的方法可以解决此问题。

3、利用事件委托解决

事件委托
  • 就是把我要做的事情委托给别人来做
  • 因为我们的冒泡机制,点击子元素的时候,也会同步触发父元素的相同事件
  • 所以我们就可以把子元素的事件委托给父元素来做
事件触发
  • 点击子元素的时候,不管子元素有没有点击事件,只要父元素有点击事件,那么就可以触发父元素的点击事件

    <body>
      <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
      </ul>
      <script>
      	var oUl = docuemnt.querySelector('ul')
        
        oUl.addEventListener('click', function (e) {
          console.log('我是 ul 的点击事件,我被触发了')
        })
      </script>
    </body>
    
    • 像上面一段代码,当你点击 ul 的时候肯定会触发
    • 但是当你点击 li 的时候,其实也会触发
target
  • target 这个属性是事件对象里面的属性,表示你点击的目标

  • 当你触发点击事件的时候,你点击在哪个元素上,target 就是哪个元素

  • 这个 target 也不兼容,在 IE 下要使用 srcElement

    <body>
      <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
      </ul>
      <script>
      	var oUl = docuemnt.querySelector('ul')
        
        oUl.addEventListener('click', function (e) {
          e = e || window.event
          var target = e.target || e.srcElement
          console.log(target)
        })
      </script>
    </body>
    
    • 上面的代码,当你点击 ul 的时候,target 就是 ul
    • 当你点击在 li 上面的时候,target 就是 li
委托
  • 这个时候,当我们点击 li 的时候,也可以触发 ul 的点事件

  • 并且在事件内不,我们也可以拿到你点击的到底是 ul 还是 li

  • 这个时候,我们就可以把 li 的事件委托给 ul 来做

    <body>
      <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
      </ul>
      <script>
      	var oUl = docuemnt.querySelector('ul')
        
        oUl.addEventListener('click', function (e) {
          e = e || window.event
          var target = e.target || e.srcElement
         
          // 判断你点击的是 li
          if (target.nodeName.toUpperCase === 'LI') {
          	// 确定点击的是 li
            // 因为当你点击在 ul 上面的时候,nodeName 应该是 'UL'
            // 去做点击 li 的时候该做的事情了
            console.log('我是 li,我被点击了')
          }
        })
      </script>
    </body>
    
    • 上面的代码,我们就可以把 li 要做的事情委托给 ul 来做

解决上述数组越界问题的核心JavaScrpt代码:

 var res = document.querySelectorAll(".header li")
    
    for(var i=0;i<res.length;i++){             
     
        res[i].onclick=function(evt){      //在创建点击事件时传入形参
            
            for(var a=0;a<res.length;a++){
              res[a].classList.remove("active")
            }
         evt.target.classList.add("active")
              // console.log(evt.target);  //打印的是click事件触发的节点
          }
        
    }

通过事件委托的方法解决也是比较方便的。综合上述:事件委托和let定义变量是比较方便理解的!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值