为什么在使用 return 语句时 forEach 返回 undefined

IT技术 javascript
2021-02-24 14:50:59
Object.prototype.e = function() {
    [].forEach.call(this, function(e) {
        return e;
    });
}; 
var w = [1,2];

w.e(); // undefined

但是如果我改用警报,这会起作用

// ...
[].forEach.call(this, function(e) {
    alert(e);
});
// ...

w.e(); // 1, 2
4个回答

我意识到这是一个老问题,但是当您搜索此主题时,这是 google 上出现的第一件事,我会提到您可能正在寻找的是 javascript 的 for.. in 循环,它的行为更接近于许多其他语言中的 for-each,如 C#、C++ 等......

for(var x in enumerable) { /*code here*/ }

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/for...in

http://jsfiddle.net/danShumway/e4AUK/1/

需要记住的几件事:

  • for..in 不保证您的数据将按任何特定顺序返回。
  • 您的变量仍将引用索引,而不是存储在该索引处的实际值。
  • 另请参阅以下有关将其与数组一起使用的评论。

编辑: for..in 将(至少)返回添加到对象原型的属性。如果这是不希望的,您可以通过将您的逻辑包装在额外的检查中来纠正此行为:

for(var x in object) {
    if(object.hasOwnProperty(x)) {
        console.log(x + ": " + object[x]);   
    }
}
一个很好的区别是 (for.. in) 可以在数组(和类似的数据类型)上被误用,但在用于其他用户定义的对象(特别是在涉及 JSON 等数据类型的情况下)时,在很大程度上不被认为是不好的做法),至少不是在我经常使用的编码圈中。使用 (for...in) 时最重要的事情是跟踪谁在接触你的对象,以及他们是否在上面附加了任何额外的属性。除此之外,唯一真正的缺点是可能让你大吃一惊的 JS 怪癖。
2021-04-27 14:50:59
也许不是一个好主意:stackoverflow.com/questions/500504/...
2021-05-18 14:50:59

该函数e()没有返回任何东西;内部匿名函数正在返回 e值,但该返回值被调用者忽略(调用者是function e()(并且“e”的多次使用会变得更加混乱吗?))

你的例子有点奇怪,但随着这个问题正在成为规范的“从forEach”问题,让我们用更简单的东西来演示这个问题:

在这里,我们有一个函数来检查数组中的条目是否someProp匹配value,如果匹配,则增加count条目上的 并返回条目:

function updateAndReturnMatch(array, value) {
    array.forEach(function(entry) {
        if (entry.someProp == value) {
           ++entry.count;
           return entry;
        }
    });
}

但是即使找到并更新了条目,调用也会updateAndReturnMatch为我们提供undefined

其原因是,return里面forEach从回调函数返回的回调,而不是从updateAndReturnMatch记住,回调是一个函数;return在一个函数中从那个函数返回,而不是包含它的那个。

要从 返回updateAndReturnMatch,我们需要记住条目并打破循环。由于您无法打破forEach循环,我们将some改为使用

function updateAndReturnMatch(array, value) {
    var foundEntry;
    array.some(function(entry) {
        if (entry.someProp == value) {
           foundEntry = entry;
           ++foundEntry.count;
           return true; // <== Breaks out of the `some` loop
        }
    });
    return foundEntry;
}

return true我们返回some的回调,而return foundEntry从回报updateAndReturnMatch

有时这就是你想要的,但通常上面的模式可以替换为Array#find,这是 ES2015 中的新内容,但可以为旧浏览器填充:

function updateAndReturnMatch(array, value) {
    var foundEntry = array.find(function(entry) {
        return entry.someProp == value;
    });
    if (foundEntry) {
        ++foundEntry.count;
    }
    return foundEntry;
}
@squint:是的,我在评论中标记了这一点。但我想不出更好的例子。我缺乏创造力。:-|
2021-04-23 14:50:59
@squint:我想我想出了一个更好的例子。
2021-05-20 14:50:59

因为

function(e) {
    return e;
}

是回调。Array.forEach 很可能以这种方式调用它:

function forEach(callback) {
    for(i;i<length;i++) {
        item = arr[i];
        callback.call(context, item, i, etc.)
    }
}

所以回调被调用,但返回不会去任何地方。如果回调被调用如下:

return callback.call();

它将在数组中的第一项上从 forEach 返回。