Node中Object.entries()返回异常结果的原因及解决咨询
问题场景
Node.js环境中,dbResultsArr是通过dbResultsArr = [...doc[result]]从Mongoose文档中解构得到的对象数组。循环中console.log(resultObj)能正常显示业务属性,但调用Object.entries(resultObj)时,返回的是包含__parentArray、_doc等Mongoose内部属性的数组,导致无法生成预期的myStr字符串。
相关代码
let ixi = 0; for(const r of dbResultsArr){ ixi++ const resultObj = new Object(r); // without this console.log('Object.entries(r)', Object.entries(r)); was not working if(ixi === 1) { // see output below console.log('r', resultObj); console.log('Object.entries(resultObj)', Object.entries(resultObj)); } let resultsV2Obj = { searchType: searchType, }; let myStr = ''; for (const [key, value] of Object.entries(resultObj)) { if(ixi === 1) { // see output below console.log('key of r - ', `${key}`); } if(key === 'pan') { resultsV2Obj.pan = value; } else if(key !== '_id' && key !== '__v') { myStr += `${key}: ${value}; ` } } resultsV2Obj.nameDetails = myStr; newCheckObj.pmlaCheckResultsV2.push(resultsV2Obj); }
控制台输出
r { _id: 610796d7cb5778deff3ef9bb, entity: 'Order in the matter of Infrastructures Limited and its Directors', name: 'Kumar Sharma', pan: 'xxxxx', orderDate: '02/11/2015\n\n\n03/10/2016', orderDetail: 'Restrained the entity from .....', __v: 0 } Object.entries(resultObj) [ [ '__parentArray', [ [Object], [Object], [Object], [Object], [Object], [Object] ] ], [ '__index', 0 ], [ '$isDocumentArrayElement', true ], [ '$__', InternalCache { strictMode: true, selected: undefined, shardval: undefined, saveError: undefined, validationError: undefined, adhocPaths: undefined, removing: undefined, inserting: undefined, saving: undefined, version: undefined, getters: {}, _id: 610796d7cb5778deff3ef9bb, populate: undefined, populated: undefined, wasPopulated: false, scope: undefined, activePaths: [StateMachine], pathsToScopes: {}, cachedRequired: {}, session: null, '$setCalled': Set(0) {}, ownerDocument: [Object], fullPath: 'sebiResultsFM', emitter: [EventEmitter], '$options': [Object] } ], [ 'isNew', false ], [ 'errors', undefined ], [ '$locals', {} ], [ '$op', null ], [ '_doc', { _id: 610796d7cb5778deff3ef9bb, entity: 'Order in the matter of Infrastructures Limited and its Directors', name: 'Kumar Sharma', pan: 'xxxxx', orderDate: '02/11/2015\n\n\n03/10/2016', orderDetail: 'Restrained the entity from .....', __v: 0 } ], [ '$init', true ] ] key of r - __parentArray key of r - __index key of r - $isDocumentArrayElement key of r - $__ key of r - isNew key of r - errors key of r - $locals key of r - $op key of r - _doc key of r - $init
预期myStr结果
entity: 'Order in the matter of Infrastructures Limited and its Directors'; name: 'Kumar Sharma'; orderDate: '02/11/2015\n\n\n03/10/2016'; orderDetail: 'Restrained the entity from .....'
问题原因
你处理的不是普通JavaScript对象,而是Mongoose Document实例。Mongoose重写了Document的toString/console.log方法,打印时只会展示_doc里的业务数据,但实际对象本身包含大量Mongoose内部管理的属性(比如__parentArray、$__等)。用new Object(r)复制的方式并没有剥离这些Mongoose的包装层,所以Object.entries会遍历到所有内部属性。
解决方法
只需把Mongoose Document转换为纯JavaScript对象即可,有几种常用方式:
方法1:使用Mongoose内置的toObject()方法
这是最推荐的方式,专门用来将Document转为普通JS对象:
// 替换原来的const resultObj = new Object(r); const resultObj = r.toObject();
方法2:使用toJSON()方法
效果和toObject()类似,部分场景下会自动应用schema里的transform规则:
const resultObj = r.toJSON();
方法3:直接提取_doc属性
Document的业务数据都存在_doc属性里,可以直接取用:
const resultObj = {...r._doc}; // 解构复制,避免直接修改原对象
方法4:JSON序列化再反序列化
通用的对象转换方式,适合任何场景,但性能略低:
const resultObj = JSON.parse(JSON.stringify(r));
修改后再运行,Object.entries(resultObj)就只会遍历你的业务属性,生成预期的myStr字符串。
内容的提问来源于stack exchange,提问作者hemant

