简体   繁体   中英

Mongoose + Node.js, Object.assign (copy of data returned from database) shows additional data

Today I found an interesting thing, that I never knew before. I need help in understanding why this happened:

User.findOne({email: req.body.email}, function(err, usr){
     return res.json({
          RAW: usr,
          COPY: Object.assign({}, usr, {some: 'change'})
     }) 
})

This yield

{
    "RAW": {
        "createdAt": "2018-06-25T09:16:35.516Z",
        "_id": "5b30b2f36c492c55a818b455",
        "email": "some@email.com",
        "password": "$2b$08$k5IRBF.1i.q.7D/BD4HCVuOdnIRDQOHaT6icNwIyc1XfeklUwyF5.",
        "__v": 0
    },
    "COPY": {
        "$__": {
            "strictMode": true,
            "selected": {},
            "getters": {},
            "_id": "5b30b2f36c492c55a818b455",
            "wasPopulated": false,
            "activePaths": {
                "paths": {
                    "createdAt": "init",
                    "_id": "init",
                    "email": "init",
                    "password": "init",
                    "__v": "init"
                },
                "states": {
                    "ignore": {},
                    "default": {},
                    "init": {
                        "_id": true,
                        "email": true,
                        "password": true,
                        "createdAt": true,
                        "__v": true
                    },
                    "modify": {},
                    "require": {}
                },
                "stateNames": [
                    "require",
                    "modify",
                    "init",
                    "default",
                    "ignore"
                ]
            },
            "pathsToScopes": {},
            "emitter": {
                "domain": null,
                "_events": {},
                "_eventsCount": 0,
                "_maxListeners": 0
            },
            "$options": true
        },
        "isNew": false,
        "_doc": {
            "createdAt": "2018-06-25T09:16:35.516Z",
            "_id": "5b30b2f36c492c55a818b455",
            "email": "some@email.com",
            "password": "$2b$08$k5IRBF.1i.q.7D/BD4HCVuOdnIRDQOHaT6icNwIyc1XfeklUwyF5.",
            "__v": 0
        },
        "$init": true,
        "some": "change"
    }
}

See the difference between RAW and COPY . According to my understanding

  1. Object.assign() just creates a copy of an Object with the new memory address.
  2. Then RAW.email should be EQUAL to COPY.email (but it's not, WHY?)

Clearly, the COPY contains information from MongoDB, if RAW already had those data (hidden) then how can RAW.email gets the data whereas COPY.email is undefined .

HOW does this abstraction work in case of RAW ?

As Express res.json documentation states,

Sends a JSON response. This method sends a response (with the correct content-type) that is the parameter converted to a JSON string using JSON.stringify().

And JSON.stringify uses toJSON method where available to get object values. Mongoose documents support it .

Since toJSON isn't own enumerable method of usr , it's omitted when it's shallowly copied with Object.assign({}, usr) , so the object is treated as is by JSON.stringify and internal document properties are exposed.

It likely should be:

 res.json({
      RAW: usr,
      COPY: Object.assign({}, usr.toJSON(), {some: 'change'})
 }) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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