为了账号安全,请及时绑定邮箱和手机立即绑定

这两个for循环可以简化吗?

这两个for循环可以简化吗?

芜湖不芜 2019-03-14 18:15:44
可以合并吗for(i=0;i<oBtn1.length;i++){      oBtn1[i].onclick=function(){          alert('a');      }}for(i=0;i<oSp1.length;i++){      oSp1[i].onclick=function(){          alert('a');      }}
查看完整描述

8 回答

?
阿晨1998

TA贡献2037条经验 获得超6个赞

别人问的是可不可以合并,楼上一大坨说的啥,好像恨不得把几十年学的js全抖出来,万一楼主有不可告人的原因而无法使用dom123456789级还有代理呢?


var len = Math.max(oBtn1.length,oSp1.length)

for(i=0;i<len;i++){

    if(oBtn1[i]){

        oBtn1[i].onclick=function(){

           alert('a');

        }

    }

    if(oSp1[i]){

       oSp1[i].onclick=function(){

          alert('a');

      }

    }

      

}


查看完整回答
反对 回复 2019-03-30
?
茅侃侃

TA贡献1842条经验 获得超21个赞

从代码中初步断定为楼主循环目的为多元素绑定事件并且采用的是DOM 0级事件绑定方式,我这边先对1楼说的不推荐事件这么注册补充一些说明,然后在针对代码简化提一些建议。


首先,0级的事件绑定一大优势就在于有着较好的向后兼容性,因为最早标准没出来的时候主流浏览器厂商做的事件绑定都这么绑,标准出来后之后总得兼顾以前的代码吧,因此这种绑定方式也被留了下来。这种绑定方式的最大缺点在于无法为同一个元素同一个事件绑定多个处理函数,而且通过w3c事件绑定即x.addEventListener能指定事件的处理阶段是在捕获阶段还是在冒泡阶段。综上所述,因为0级事件存在无法对事件触发阶段进行更精细的控制并且不在w3c标准内,因此在使用上要加以斟酌。


针对代码部分,我理解为楼主合并两个循环的目的为简化代码量并提升性能,在提升算法性能思路上可以考虑将两个循环合并为一个循环,当oBtn1的集合长度与oSp1的长度相等时,此时单层循环就能解决合并问题。


// 我不知道楼主这边查询到的DOM节点集合是nodeList还是什么类型

// 如果是nodeList类型集合会存在与DOM树实时同步的特点,建议遍历时

// 把长度值先另存下来

for(let i=0, len = oBtn1.length; i<len;i++){

  oBtn1[i].onclick = function(){

  alert('a');

}


oSp1[i].onclick = function(){

  alert('b');

}

}


当两集合长度不一样的时,一层循环的一个思路在于使用较长的那个长度作为遍历次数,

在内部根据当前长度值判断为哪个元素进行事件绑定。


let lenOfoBtn = oBtns.length;

let lenOfoSp1 = oSp1.length;

let len = Math.max(lenOfBtn, lenOfoSp1);

// 假设是Sp1长度比较短

for(let i=0; i<len;i++){

 oBtn1[i].onclick = function(){

 alert('a');

}


 if( i < lenBtnOfSp1 ){

   oSp1[i].onclick = function(){

      alert('b');

    }

 }

}

鉴于个人算法功底较差,此时如果想再一步优化算法性能,个人暂时没有可行的思路,或许能递归?


当然,在DOM中当然还能使用一楼提出的事件委托进行代码及性能层面上的优化。


// 伪代码

parentOfObtn = Obtn.parentNode;

parentOfoSp1 = oSp1.parentNode

parentOfbtn.addEventListener("click", function( e ){

// 识别事件触发对象是谁的条件语句,可能用类名或其他标识

if( e.target == xxx ){

  alert("a")

}

}, false)

parentOfoSp1 .addEventListener("click", function( e ){

// 识别事件触发对象是谁的条件语句,可能用类名或其他标识

if( e.target == xxx ){

  alert("b")

}

}, false)

更一步就是把事件委托到sp1与oBtn共有的祖先节点上,小透明第一次答题,

希望能对你有帮助。


查看完整回答
反对 回复 2019-03-30
?
白板的微信

TA贡献1883条经验 获得超3个赞

还有另一种方式「合并」


function bindF(a) {

  for (var i = 0; i < a.length; ++i) {

    a[i].onclick = function () {

      alert('a');

    };

  }

}


bindF(oBtn1, i);

bindF(oSp1, i);


你知道 loop fusion 吗


题主的两个循环相互之间没有依赖关系


如果循环次数一样,是可以合成一个的


即便循环次数不一样


也可以强行合并(虽然理论上会被编译器再用 loop fission 拆成两个循环)


const { max } = Math;


var n = max(oBtn1.length, oSp1.length);

var i = 0;


function set(a, i) {

  if (i < a.length) {

    a[i].onclick = function () {

      alert('a');

    };

  }

}


for (; i < n; ++i) {

  set(oBtn1, i);

  set(oSp1, i);

}


查看完整回答
反对 回复 2019-03-30
?
慕码人8056858

TA贡献1803条经验 获得超6个赞

var clickFunc = function(){

    alert('a');

};

for(i=0;i<oBtn1.length;i++){

      oBtn1[i].onclick=clickFunc;

}

for(i=0;i<oSp1.length;i++){

      oSp1[i].onclick=clickFunc;

}


查看完整回答
反对 回复 2019-03-30
  • 8 回答
  • 0 关注
  • 808 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信