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

0x4*_*2D2 10 javascript

Object.prototype.e = function() {
    [].forEach.call(this, function(e) {
        return e;
    });
}; 
var w = [1,2];

w.e(); // undefined
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用警报,这是有效的

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

w.e(); // 1, 2
Run Code Online (Sandbox Code Playgroud)

dan*_*way 8

我意识到这是一个老问题,但是当你搜索这个主题时,谷歌首次出现这个问题,我会提到你可能正在寻找的是javascript的for ... in循环,它表现得更接近for-each在许多其他语言中,如C#,C++等......

for(var x in enumerable) { /*code here*/ }
Run Code Online (Sandbox Code Playgroud)

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

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

要记住几件事:

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

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

for(var x in object) {
    if(object.hasOwnProperty(x)) {
        console.log(x + ": " + object[x]);   
    }
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*n P 7

该功能e()没有返回任何东西; 内部匿名函数返回 e值,但调用者正在忽略该返回值(调用者正在function e()(并且'e'的多次使用会让人更加困惑吗?))


Joe*_*Joe 6

因为

function(e) {
    return e;
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

return callback.call();
Run Code Online (Sandbox Code Playgroud)

它将在数组中的第一个项目上返回forEach.


T.J*_*der 6

你的例子有点奇怪,但随着这个问题成为规范的"回归forEach"问题,让我们用更简单的东西来证明这个问题:

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

function updateAndReturnMatch(array, value) {
    array.forEach(function(entry) {
        if (entry.someProp == value) {
           ++entry.count;
           return entry;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

但即使找到并更新了条目,呼叫也会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;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)