【问题标题】:Primer/library loop function only executes once引物/库循环函数只执行一次
【发布时间】:2018-06-17 13:37:13
【问题描述】:

我经历了所有“循环触发一次”的问题,但找不到我的问题的解决方案。

我正在做一个需要大量循环函数的项目,以元素为主题。我想我会创建一个库函数(我认为'primer function'是一个更好的术语),以后每次只需一行代码就可以调用它。所以我尝试了,但它的行为不像我预期的那样,因为它只触发一次。这是我的实验代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <span class="demo">See me.</span>
    <span class="demo">See me.</span>
    <span class="demo">See me.</span>
    <span class="demo">See me.</span>
    <script>
        var forAll = function(elems) {
            for (var i=0, n=elems.length; i<n; i++) {
                console.log('The elems[i] == ' + elems[i]);
                return elems[i];
            }
        }
        var demos = document.querySelectorAll('.demo');
        forAll(demos).style.color = 'red';
        console.log('The forAll(demos) ==' + forAll(demos));
    </script>
</body>
</html>

从结果和控制台可以看出,primer 函数只触发一次。我究竟做错了什么?我完全自学了 Javascript,所以如果我缺少基本的东西,请放轻松。

补充:在这种情况下,IE11 是一个常用的浏览器,所以forEach 不是一个选项。

【问题讨论】:

  • 您希望该函数能做什么?您调用它的方式似乎应该返回单个 DOM 元素引用,因为您取消引用返回值的“样式”属性。在这种情况下,循环实际上并没有任何意义,正如所写的那样。如果意图以某种方式过滤元素列表以找到特定的元素,这可能是有意义的。
  • 我希望该函数将所有跨度文本变为红色。

标签: javascript html loops foreach


【解决方案1】:

这个函数中的for循环只会迭代一次:

var forAll = function(elems) {
        for (var i=0, n=elems.length; i<n; i++) {
            console.log('The elems[i] == ' + elems[i]);
            return elems[i];
        }
    }

return 停止 for 循环并返回函数的执行。

编辑:这是一个代码 sn-p 可能会按照@AndroidNoobie 的建议执行您所期望的操作

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <span class="demo">See me.</span>
    <span class="demo">See me.</span>
    <span class="demo">See me.</span>
    <span class="demo">See me.</span>
    <script>
        var forAll = function(elems) {
            for (var i=0, n=elems.length; i<n; i++) {
                elems[i].style.color = 'red';
            }
            
            return elems;
        }
        var demos = document.querySelectorAll('.demo');           
        console.log('The forAll(demos) ==' + forAll(demos));
    </script>
</body>
</html>

【讨论】:

  • 你可能是对的,但console.log('The elems[i] == ' + elems[i]); 也只给出了第一个跨度。
  • @FrankConijn return 语句肯定会立即退出其包含函数。这就是return 的全部意义所在。
  • @FrankConijn 它给出了所有 4 个跨度。删除return 语句并将其替换为elems[i].style.color = 'red';,您应该会看到所有四个跨度都变为红色。
  • @AndroidNoobie -- 这会引发错误:“'elems' is not defined'。
  • @FrankConijn 不,它没有——代码 sn-p 工作正常。点击蓝色的“运行”按钮并查看。
【解决方案2】:

我认为您的实际问题是“如何在不支持 forEach 的浏览器中实现类似 forEach 的行为?”

在这种情况下,您可以这样做:

if (!Array.prototype.forEach) {
    Array.prototype.forEach = function(fn, scope) {
        for(var i = 0, len = this.length; i < len; ++i) {
            fn.call(scope, this[i], i, this);
        }
    }
}

然后你可以在你的数组上调用forEach(虽然,一般来说,修改数组等内置对象的原型并不是一个好主意)。

但是@facundo 和@Pointy 已经回答了您提出的问题(为什么循环只迭代一次)。

编辑:添加了代码 sn-p。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <span class="demo">See me.</span>
    <span class="demo">See me.</span>
    <span class="demo">See me.</span>
    <span class="demo">See me.</span>
    <script>
    
        if (!Array.prototype.forEach) {
          Array.prototype.forEach = function(fn, scope) {
              for(var i = 0, len = this.length; i < len; ++i) {
                  fn.call(scope, this[i], i, this);
              }
          }
        }
        var demos = document.querySelectorAll('.demo');
        demos.forEach(function(item){
            item.style.color = 'red';
        })
        console.log('The forAll(demos) ==' + demos);
    </script>
</body>
</html>

【讨论】:

  • 听起来很有趣,但是整个代码会是什么样子呢?因为不是IE也不支持forEach函数中需要的箭头函数吗?
  • @FrankConijn 代码块看起来像这样 jsfiddle.net/74jubnc9
  • 非常感谢您投入的时间和精力。但不幸的是,IE11 中的积分代码抛出了错误:“Object doesn't support property or method 'forEach'。”
  • @FrankConijn 你是对的。我已经要求编辑代码 sn-p。 This 是调用正确 forEach 的方式。 jsfiddle.net/74jubnc9/12
  • @facundo -- 宾果游戏!太精彩了。我知道 IE 只能在 array 内使用 forEach,但我不会很快想出那个代码。当然也不是没有错误的。非常感谢!我将由您和 AndroidNoobie 决定哪个答案将完整包含该代码,我会将其标记为已接受的答案。另外,那我会升级另一个,因为你们都帮忙了。 :-)
【解决方案3】:

使用 NodeLists 使 Internet Explorer (IE) 支持 forEach 最终看起来很容易。通过http://tips.tutorialhorizon.com/2017/01/06/object-doesnt-support-property-or-method-foreach/ 上的一个微小的 polyfill:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <span class="demo">See me.</span>
    <span class="demo">See me.</span>
    <span class="demo">See me.</span>
    <span class="demo">See me.</span>
    <script>
        // Polyfill to make IE9+ support forEach w/ NodeLists:
        (function () {
            if (typeof NodeList.prototype.forEach === "function")
                return false;
            else 
                NodeList.prototype.forEach = Array.prototype.forEach;
        })();

        // Works with NodeLists (i.e. HTMLcollections):
        var demos = document.querySelectorAll('.demo');
        demos.forEach(function(item) {
                item.style.color = 'red';
        })

        // As well as with Arrays:
        var gurkins = ['gur1', 'gur2', 'gur3'];
        gurkins.forEach(function(item) {
            console.log(item);
        });
    </script>
</body>
</html>

在 IE11 中测试,根据它的仿真功能,它也可以在 10 和 9 中工作(不是 8)。

感谢您的时间和精力,facundo 和 AndroidNoobie,但您可能会明白这是最好的解决方案。

【讨论】:

  • 很高兴你能成功!请记住,您的实际问题询问为什么循环只执行一次。 @facundo 回答了这个问题。我只提到这一点是因为如果其他用户将来搜索类似的问题,他们可能不明白为什么选择的答案与forEach 函数有关。 :-) 对@facundo 的回答提交编辑以添加您的解决方案可能会更好,这样可以涵盖两种情况。但是感谢您的赞誉,我很高兴您成功了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多