Javascript 为什么spread操作符将数据嵌套在另一个对象中?

Javascript 为什么spread操作符将数据嵌套在另一个对象中?,javascript,mongoose,Javascript,Mongoose,我一直在和猫鼬合作。为了通过电子邮件找到用户,我回复了猫鼬的承诺,如下所示: async function findByEmail({ email }) { return await userModel.findOne({ email }).exec() } { "_id": "ck09o6bvq0000zxsv6vr57oll", "name": "bobo", "email": "a@a.a", "password": "$2b$10$1zQd/3Sw6zJi9N42zGLaT.R

我一直在和猫鼬合作。为了通过电子邮件找到用户,我回复了猫鼬的承诺,如下所示:

async function findByEmail({ email }) {
    return await userModel.findOne({ email }).exec()
}
{
"_id": "ck09o6bvq0000zxsv6vr57oll",
"name": "bobo",
"email": "a@a.a",
"password": "$2b$10$1zQd/3Sw6zJi9N42zGLaT.Re5tnbt.ANzZ1XoGA0LLWFpjc05ef.a",
"facebookId": null,
"googleId": null,
"createdOn": 1567868083622,
"approved": true,
"__v": 0
}
"$__": {
  "strictMode": true,
  "selected": {},
  "getters": {},
  "_id": "ck09o6bvq0000zxsv6vr57oll",
  "wasPopulated": false,
  "activePaths": {
    "paths": {
      "approved": "init",
      "createdOn": "init",
      "password": "init",
      "email": "init",
      "name": "init",
      "_id": "init",
      "facebookId": "init",
      "googleId": "init",
      "__v": "init"
    },
    "states": {
      "ignore": {},
      "default": {},
      "init": {
        "_id": true,
        "name": true,
        "email": true,
        "password": true,
        "facebookId": true,
        "googleId": true,
        "createdOn": true,
        "approved": true,
        "__v": true
      },
      "modify": {},
      "require": {}
    },
    "stateNames": [
      "require",
      "modify",
      "init",
      "default",
      "ignore"
    ]
  },
  "pathsToScopes": {},
  "cachedRequired": {},
  "$setCalled": {},
  "emitter": {
    "domain": null,
    "_events": {},
    "_eventsCount": 0,
    "_maxListeners": 0
  },
  "$options": {
    "skipId": true,
    "isNew": false,
    "willInit": true
  }
},
"isNew": false,
"_doc": {
  "_id": "ck09o6bvq0000zxsv6vr57oll",
  "name": "bobo",
  "email": "a@a.a",
  "password": "$2b$10$1zQd/3Sw6zJi9N42zGLaT.Re5tnbt.ANzZ1XoGA0LLWFpjc05ef.a",
  "facebookId": null,
  "googleId": null,
  "createdOn": 1567868083622,
  "approved": true,
  "__v": 0
},
"$locals": {},
"$init": true
}
这是当事情变得有点奇怪的时候,当我想使用Javascript的Spread操作符返回用户时

const user1 = await findByEmail({email: a@a.a});
const user2 = {...user1};
console.log('user1',user1);
console.log('user2',user2);
User1是这样的:

async function findByEmail({ email }) {
    return await userModel.findOne({ email }).exec()
}
{
"_id": "ck09o6bvq0000zxsv6vr57oll",
"name": "bobo",
"email": "a@a.a",
"password": "$2b$10$1zQd/3Sw6zJi9N42zGLaT.Re5tnbt.ANzZ1XoGA0LLWFpjc05ef.a",
"facebookId": null,
"googleId": null,
"createdOn": 1567868083622,
"approved": true,
"__v": 0
}
"$__": {
  "strictMode": true,
  "selected": {},
  "getters": {},
  "_id": "ck09o6bvq0000zxsv6vr57oll",
  "wasPopulated": false,
  "activePaths": {
    "paths": {
      "approved": "init",
      "createdOn": "init",
      "password": "init",
      "email": "init",
      "name": "init",
      "_id": "init",
      "facebookId": "init",
      "googleId": "init",
      "__v": "init"
    },
    "states": {
      "ignore": {},
      "default": {},
      "init": {
        "_id": true,
        "name": true,
        "email": true,
        "password": true,
        "facebookId": true,
        "googleId": true,
        "createdOn": true,
        "approved": true,
        "__v": true
      },
      "modify": {},
      "require": {}
    },
    "stateNames": [
      "require",
      "modify",
      "init",
      "default",
      "ignore"
    ]
  },
  "pathsToScopes": {},
  "cachedRequired": {},
  "$setCalled": {},
  "emitter": {
    "domain": null,
    "_events": {},
    "_eventsCount": 0,
    "_maxListeners": 0
  },
  "$options": {
    "skipId": true,
    "isNew": false,
    "willInit": true
  }
},
"isNew": false,
"_doc": {
  "_id": "ck09o6bvq0000zxsv6vr57oll",
  "name": "bobo",
  "email": "a@a.a",
  "password": "$2b$10$1zQd/3Sw6zJi9N42zGLaT.Re5tnbt.ANzZ1XoGA0LLWFpjc05ef.a",
  "facebookId": null,
  "googleId": null,
  "createdOn": 1567868083622,
  "approved": true,
  "__v": 0
},
"$locals": {},
"$init": true
}
User2是这样的:

async function findByEmail({ email }) {
    return await userModel.findOne({ email }).exec()
}
{
"_id": "ck09o6bvq0000zxsv6vr57oll",
"name": "bobo",
"email": "a@a.a",
"password": "$2b$10$1zQd/3Sw6zJi9N42zGLaT.Re5tnbt.ANzZ1XoGA0LLWFpjc05ef.a",
"facebookId": null,
"googleId": null,
"createdOn": 1567868083622,
"approved": true,
"__v": 0
}
"$__": {
  "strictMode": true,
  "selected": {},
  "getters": {},
  "_id": "ck09o6bvq0000zxsv6vr57oll",
  "wasPopulated": false,
  "activePaths": {
    "paths": {
      "approved": "init",
      "createdOn": "init",
      "password": "init",
      "email": "init",
      "name": "init",
      "_id": "init",
      "facebookId": "init",
      "googleId": "init",
      "__v": "init"
    },
    "states": {
      "ignore": {},
      "default": {},
      "init": {
        "_id": true,
        "name": true,
        "email": true,
        "password": true,
        "facebookId": true,
        "googleId": true,
        "createdOn": true,
        "approved": true,
        "__v": true
      },
      "modify": {},
      "require": {}
    },
    "stateNames": [
      "require",
      "modify",
      "init",
      "default",
      "ignore"
    ]
  },
  "pathsToScopes": {},
  "cachedRequired": {},
  "$setCalled": {},
  "emitter": {
    "domain": null,
    "_events": {},
    "_eventsCount": 0,
    "_maxListeners": 0
  },
  "$options": {
    "skipId": true,
    "isNew": false,
    "willInit": true
  }
},
"isNew": false,
"_doc": {
  "_id": "ck09o6bvq0000zxsv6vr57oll",
  "name": "bobo",
  "email": "a@a.a",
  "password": "$2b$10$1zQd/3Sw6zJi9N42zGLaT.Re5tnbt.ANzZ1XoGA0LLWFpjc05ef.a",
  "facebookId": null,
  "googleId": null,
  "createdOn": 1567868083622,
  "approved": true,
  "__v": 0
},
"$locals": {},
"$init": true
}
实际上是猫鼬皮。
有人能告诉我为什么会这样吗?为什么user1和user2不一样

Javascript中的spread操作符生成object的对象和实例,而不是保存其以前的类

console.log(user1.constructor.name) //model
console.log(user2.constructor.name) //object
这就是user2中有更多字段的原因。要仅从user2获取_doc(感谢),请使用如下toString

console.log(...user1.toObject())

因为spread创建了一个普通的对象,而不是继承了原型的mongoose包装器实例