简体   繁体   English

Javascript 删除 object 属性不起作用

[英]Javascript delete object property not working

I'm running some project on MEAN.js and I've got a following problem.我在 MEAN.js 上运行一些项目,我遇到了以下问题。 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:但是用户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):我想在保存之前删除用户 object 的密码,但我做不到(让我们看看下面代码中的注释):

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?为什么delete方法返回true,却没有任何反应? Thanks for your help:)谢谢你的帮助:)

Just do:做就是了:

user.password = undefined;

instead of:代替:

delete user.password;

and the password property will not appear at the output.并且密码属性不会出现在输出中。

there are certain rules for delete operator in javascript javascript中删除操作符有一定的规则

  1. if the property is an own non-configurable property in "strict mode" than it will return false.如果该属性在“严格模式”下是自己的不可配置属性,则它将返回 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 
  1. 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所以,请交叉检查这些点,有关更多信息,您可以阅读此链接

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; 

Working with MONGOOSE?使用 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如果您在使用 Mongoose(Mongo DB 的上层)时遇到此问题,那么您可以在find方法上使用lean属性

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.从启用了精简选项的查询返回的文档是普通的 javascript 对象,而不是 Mongoose 文档。 They have no save method, getters/setters, virtuals, or other Mongoose features.它们没有保存方法、getter/setter、virtuals 或其他 Mongoose 功能。

Documents are kind of read-only, so delete doesn't work on them文档是只读的,因此delete对它们不起作用

Reference - https://stackoverflow.com/a/48137096/10824697 https://mongoosejs.com/docs/api.html#query_Query-lean参考 - https://stackoverflow.com/a/48137096/10824697 https://mongoosejs.com/docs/api.html#query_Query-lean

Method 2 without lean方法 2 无精益

If you want to use the mongoose provided method to remove some property while you are querying, you can remove with select method,如果您想在查询时使用 mongoose 提供的方法删除某些属性,可以使用select方法删除,

const users = await User.find({ role: 'user' }).select('-password')

console.log(users)
 /* [
      {name:'John'}, 
      {name:'Susan'}
    ] 
 */ 

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.上面来自 Majed A 的答案是适用于单个对象属性的最简单的解决方案,我们甚至可以通过删除...user扩展器使其更容易。 just delete the property from your object._doc sub-object.只需从object._doc子对象中删除该属性。 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.

Had a similar issue.有一个类似的问题。 The delete operator "was not working" when trying to delete a property from an object in a specific case.在特定情况下尝试从对象中删除属性时, delete运算符“不起作用”。 Fixed it using Lodash unset :使用Lodash unset修复它:

_.unset(user, "password");

https://lodash.com/docs/4.17.11#unset https://lodash.com/docs/4.17.11#unset

Otherwise the delete operator does work.否则, delete运算符确实有效。 Just in case, delete operator docs here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete以防万一,请在此处delete操作员文档: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete

If password was defined with defineProperty , then configurable defaults to false if not set.如果密码是使用defineProperty定义的,那么如果未设置,则可configurable默认为 false。 In that case, then the property can't be deleted.在这种情况下,无法删除该属性。

For me, node js still tells me the property was deleted ( console.log(delete obj.prop) ), but it wasn't deleting.对我来说,node js 仍然告诉我该属性已被删除( console.log(delete obj.prop) ),但它没有被删除。

 function test(settings) { settings = {...{c: false, w:false}, ...settings} let obj = {} Object.defineProperty(obj, "prop", { configurable: settings.c, enumerable: settings.e?? true, writable: settings.w, value: "foo" }); console.log( JSON.stringify(settings), '\nset value to 1', (function() {obj.prop = 1})() || "", '\nappended bar:', (function() {obj.prop += "bar"})() || "", '\nobj:', JSON.stringify(obj), '\ndelete:', delete obj['prop'], '\nobj:', JSON.stringify(obj)) } console.log('baseline: unchangeable, undeletable'); test() console.log('unchangeable, deletable'); test({c: true}) console.log('changeable, undeletable'); test({w: true}) console.log('changeable, deletable'); test({c: true, w: true})

You may use this.你可以用这个。 It skips the unwanted key instead of deleting, it then returns an object.它会跳过不需要的密钥而不是删除,然后返回 object。

let x = {1:'1', 2:2}

console.log('in', x)


function remove(Object, key){

    let outputObject = {}

    for (let inKey in Object){

        if(key == inKey){

            console.log(key , 'was deleted')

        }else{

           outputObject[inKey] = Object[inKey]

        }

    }

    return outputObject

}

let out = remove(x, 1)

console.log('out', out)

The most likely, property which you want to delete has not owned the property for this object. In this case, the result of the operation will show true but nothing will be deleted.最有可能的是,您要删除的属性不拥有此 object 的属性。在这种情况下,操作结果将显示为true ,但不会删除任何内容。

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

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