'Javascript delete object property not working
I'm running some project on MEAN.js and I've got a following problem. I want to make some user's profile calculation and the save it to database. But there's a problem with method in users model:
UserSchema.pre('save', function(next) {
if (this.password && this.password.length > 6) {
this.salt = new Buffer(crypto.randomBytes(16).toString('base64'), 'base64');
this.password = this.hashPassword(this.password);
}
next();
});
If I will send a password with my changes, it will change credentials, so user is unable to login next time. I want to delete password from user object before save, but I'm not able to do it (let's look at the comments in my code below):
exports.signin = function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err || !user) {
res.status(400).send(info);
} else {
/* Some calculations and user's object changes */
req.login(user, function(err) {
if(err) {
res.status(400).send(err);
} else {
console.log(delete user.password); // returns true
console.log(user.password); // still returns password :(
//user.save();
//res.json(user);
}
});
}
})(req, res, next);
};
What's wrong? Why the delete method returns true, but nothing happens? Thanks for your help :)
Solution 1:[1]
there are certain rules for delete operator in javascript
- if the property is an own non-configurable property in "strict mode" than it will return false.
for example
x = 42; // creates the property x on the global object
var y = 43; // creates the property y on the global object, and marks it as non-configurable
// x is a property of the global object and can be deleted
delete x; // returns true
// y is not configurable, so it cannot be deleted
delete y; // returns false
- If the object inherits a property from a prototype, and doesn't have the property itself, the property can't be deleted by referencing the object. You can, however, delete it directly on the prototype.
for example
function Foo(){}
Foo.prototype.bar = 42;
var foo = new Foo();
// returns true, but with no effect,
// since bar is an inherited property
delete foo.bar;
// logs 42, property still inherited
console.log(foo.bar);
so, please cross check these point and for more information your can read this Link
Solution 2:[2]
Just do:
user.password = undefined;
instead of:
delete user.password;
and the password property will not appear at the output.
Solution 3:[3]
Had a similar problem. This worked for me:
// create a new copy
let newUser= ({...user}._doc);
// delete the copy and use newUser that thereafter.
delete newUser.password;
Solution 4:[4]
The answer above from Majed A is the simplest solution that works for single objects properties, we can even make it for more easier by removing the ...user spreader. just delete the property from your object._doc sub-object. in your example it would have been:
user.save()
delete user._doc.password
res.status(201).json(user) // The password will not be shown in JSON but it has been saved.
Solution 5:[5]
Working with MONGOOSE?
If you're facing this issue when working with Mongoose (Mongo DB's upper layer) then you can use lean property on find method
Examples
Without lean (The keys won't be deleted)
const users = await User.find({ role: 'user' }) // no lean method
users.forEach((user) => {
delete user.password. // doesn't delete the password
})
console.log(users)
/* [
{name:'John', password:'123'},
{name:'Susan', password:'456'}
]
*/
With lean (The keys get deleted)
const users = await User.find({ role: 'user' }).lean()
users.forEach((user) => {
delete user.password // deletes the password
})
console.log(users)
/* [
{name:'John'},
{name:'Susan'}
]
*/
Reason why lean works
Documents returned from queries with the lean option enabled are plain javascript objects, not Mongoose Documents. They have no save method, getters/setters, virtuals, or other Mongoose features.
Documents are kind of read-only, so delete doesn't work on them
Reference - https://stackoverflow.com/a/48137096/10824697 https://mongoosejs.com/docs/api.html#query_Query-lean
Method 2 without lean
If you want to use the mongoose provided method to remove some property while you are querying, you can remove with select method,
const users = await User.find({ role: 'user' }).select('-password')
console.log(users)
/* [
{name:'John'},
{name:'Susan'}
]
*/
Solution 6:[6]
Had a similar issue. The delete operator "was not working" when trying to delete a property from an object in a specific case. Fixed it using Lodash unset:
_.unset(user, "password");
https://lodash.com/docs/4.17.11#unset
Otherwise the delete operator does work. Just in case, delete operator docs here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Virendra Yadav |
| Solution 2 | LEMUEL ADANE |
| Solution 3 | Majed A |
| Solution 4 | Bw. Kizito |
| Solution 5 | |
| Solution 6 |
