简体   繁体   English

为什么Javascript .map()返回并且为字符串对象额外的“未定义”?

[英]Why does Javascript .map() return and extra “undefined” for an object of strings?

Please can anyone help with where an undefined item is coming from when mapping an object of strings. 映射字符串对象时,任何人都可以提供有关未定义项来自何处的帮助。 This is my object followed by the mapping: 这是我的对象,后面是映射:

function giveAdminTasks(){
var item;
var arr = [{adminTask: "Print Certificate",lessonNo: 0},
   {adminTask: "Study",lessonNo: 27},
   {adminTask: "Print Certificate",lessonNo: 3},
   {adminTask: "Calling Record",lessonNo: 3},
   {adminTask:"Calling Record",lessonNo: 3}];

 arr.map(function(elem){
 if(elem.lessonNo === 3){
 item += " + " + elem.adminTask;
 } 
})
console.log(item);
}

However, this returns a variable that looks like this: 但是,这将返回如下所示的变量:

"undefined + Print Certificate + Calling Record + Calling Record" “未定义+打印证书+通话记录+通话记录”

I can't figure out where the "undefined" item comes from. 我不知道“未定义”项目的来源。 This doesn't happen if I just map the object without the "if" statement. 如果我仅在没有“ if”语句的情况下映射对象,则不会发生这种情况。 Can anyone help? 有人可以帮忙吗?

This question talks about map only working on strings, but my object is all strings. 这个问题是关于map仅在字符串上起作用的,但是我的对象是所有字符串。

You did not initialize your item variable thus it has an initial value of undefined . 您没有初始化item变量,因此它的初始值为undefined

Change this: 更改此:

var item;

to this: 对此:

var item = "";

You also have to deal with the fact that item is initially empty and you don't want to add a leading + sign when it's empty. 您还必须处理以下事实: item最初是空的,并且不想在空的情况下添加前导+符号。


FYI, this is really a misuse of .map() . 仅供参考,这实际上是对.map()的滥用。 You should be using .forEach() or one of the other iterators instead since you aren't interested in a returned array. 您应该使用.forEach()或其他迭代器之一,因为您对返回的数组不感兴趣。

function giveAdminTasks() {
    var item = "";
    var arr = [
        {adminTask: "Print Certificate", lessonNo: 0}, 
        {adminTask: "Study", lessonNo: 27}, 
        {adminTask: "Print Certificate", lessonNo: 3}, 
        {adminTask: "Calling Record", lessonNo: 3}, 
        {adminTask: "Calling Record",lessonNo: 3
    }];

    arr.forEach(function(elem) {
        if (elem.lessonNo === 3) {
            if (item) item += " + ";
            item += elem.adminTask;
        }
    });
    console.log(item);
}

You could also use .reduce() like this: 您也可以像下面这样使用.reduce()

var item = arr.reduce(function(str, item) {
    if (item.lessonNo === 3) {
        if (str) str += " + ";
        str += elem.adminTask;
    }
    return str;
}, "");
console.log(item);

Here's a more declarative solution using ES6. 这是使用ES6的更具声明性的解决方案。 It's most similar to Oriol's solution but doesn't iterate through the data more than once. 它与Oriol的解决方案最相似,但不会多次遍历数据。

 const giveAdminTasks = (data, n) => data.reduce((acc, {adminTask, lessonNo}) => lessonNo === n ? [...acc, adminTask] : acc, []).join(' + ') let arr = [ {adminTask: "Print Certificate",lessonNo: 0}, {adminTask: "Study",lessonNo: 27}, {adminTask: "Print Certificate",lessonNo: 3}, {adminTask: "Calling Record",lessonNo: 3}, {adminTask: "Calling Record",lessonNo: 3} ] console.log(giveAdminTasks(arr, 3)) // Print Certificate + Calling Record + Calling Record console.log(giveAdminTasks(arr, 0)) // Print Certificate console.log(giveAdminTasks(arr, 27)) // Study 

And the ES5 equivalent 和ES5相当

 function giveAdminTasks (data, n) { return data.reduce(function (acc, x) { return x.lessonNo === n ? acc.concat([x.adminTask]) : acc }, []).join(' + ') } var arr = [ {adminTask: "Print Certificate",lessonNo: 0}, {adminTask: "Study",lessonNo: 27}, {adminTask: "Print Certificate",lessonNo: 3}, {adminTask: "Calling Record",lessonNo: 3}, {adminTask: "Calling Record",lessonNo: 3} ] console.log(giveAdminTasks(arr, 3)) // Print Certificate + Calling Record + Calling Record console.log(giveAdminTasks(arr, 0)) // Print Certificate console.log(giveAdminTasks(arr, 27)) // Study 


To address @jfriend00's comment, to preserve the readability of the code and prevent the needless creation of extra arrays, you can introduce a small helper function. 为了解决@ jfriend00的注释,以保持代码的可读性并防止不必要的额外数组创建,可以引入一个小的辅助函数。

At this point, I would call this a premature optimization. 在这一点上,我将其称为过早的优化。 It's likely the original code will meet your needs unless you have significantly large datasets. 除非您拥有大量数据集,否则原始代码很可能会满足您的需求。 If you run a profiler on your code and notice that this bit of code is slowing you down, then it might be time to start making some adjustments … 如果您在代码上运行了探查器,并且注意到这段代码使您放慢了速度,那么可能是时候开始进行一些调整了……

 const apush = (xs,x) => (xs.push(x), xs) const giveAdminTasks = (data, n) => data.reduce((acc, {adminTask, lessonNo}) => lessonNo === 3 ? apush(acc, adminTask) : acc, []).join(' + ') let arr = [ {adminTask: "Print Certificate",lessonNo: 0}, {adminTask: "Study",lessonNo: 27}, {adminTask: "Print Certificate",lessonNo: 3}, {adminTask: "Calling Record",lessonNo: 3}, {adminTask: "Calling Record",lessonNo: 3} ] console.log(giveAdminTasks(arr, 3)) // Print Certificate + Calling Record + Calling Record 

I would use filter , map and join : 我会使用filtermapjoin

 var arr = [{adminTask: "Print Certificate",lessonNo: 0}, {adminTask: "Study",lessonNo: 27}, {adminTask: "Print Certificate",lessonNo: 3}, {adminTask: "Calling Record",lessonNo: 3}, {adminTask:"Calling Record",lessonNo: 3}]; var item = arr.filter(function(elem){ return elem.lessonNo === 3; }).map(function(elem){ return elem.adminTask; }).join(' + '); console.log(item); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM