Removing all properties from a object

Javascriptnode.js

Javascript Problem Overview


I have this Javascript object.

req.session

In my code I add properties to this object. These properties can be other objects, arrays, or just plain strings.

req.session.savedDoc = someObject; 
req.session.errors = ['someThing', 'anotherThing', 'thirdThing'];
req.session.message = 'someString'

If I later would like to erase all added properties of this object, what is the easiest/best way?

There must be a better way than this?

// Delete all session values
delete req.session.savedDoc;
delete req.session.errors;
delete req.session.message;

Javascript Solutions


Solution 1 - Javascript

@VisioN's answer works if you want to clear that specific reference, but if you actually want to clear an object I found that this works:

for (var variableKey in vartoClear){
    if (vartoClear.hasOwnProperty(variableKey)){
        delete vartoClear[variableKey];
    }
}

Solution 2 - Javascript

There are two possible solutions to the problem:

Assign an empty object

req.session = {};

The garbage collector will clean the memory automatically. This variant is super fast and will work in most cases, however, you need to use it with caution, as it may keep the references to the objects in memory. This caveat is described in the TLDR section below.

Delete properties one-by-one

Object.keys(object).forEach(key => delete object[key]);

This will clean the object by going through every non-prototype property and deleting it. It's safer but slower. You need to decide if it makes sense for you to use it in a particular case.


TLDR

Any solution given above will do the job for the author in the current situation, as well as any other valid solution provided in this question. It mainly depends on the way how the developer wants to manipulate the deprecated data.

Session object may contain data that is linked by different variable, and setting a new empty object to req.session will not break the reference to the old data, so the old data will be available where it is still required. Although the correct way to keep old data is to clone the initial object, real-life scenarios can be different. Let's look at the following example:

req.session.user = { name: "Alexander" };  // we store an object in the session
var session = req.session;                 // save reference to the session in a variable
console.log( req.session, session );       // {user: Object}, {user: Object}

req.session = {};                          // let's replace session with a new object
console.log( req.session, session );       // {}, {user: Object}

We still can fetch old data from session variable but req.session is empty: here setting a new object works as a sort of alternative to deep cloning. The garbage collector will not remove data from the old req.session object as it is still referenced by the session variable.

Deep cleaning of the object with:

Object.keys(object).forEach(key => delete object[key]);

... will explicitly remove all values from the req.session object and, since session variable is linked to the same object, session will become empty as well. Let's see how it works:

req.session.user = { name: "Alexander" };  // we store an object in the session
var session = req.session;                 // save reference to the session in a variable
console.log( req.session, session );       // {user: Object}, {user: Object}

Object.keys(req.session).forEach(key => delete req.session[key]);
console.log( req.session, session );       // {}, {}

As you can see now, in both cases we get empty objects.

From speed and memory perspectives setting a new empty object will be much faster than cleaning the old object property by property, however memory-wise if the old data is still referenced somewhere, the new object approach won't free up memory that old data is consuming.

It's quite obvious that choosing the approach to take is mostly up to your coding scenario but in most cases req.session = {}; will do the job: it is fast and short. However, if you keep references to the original object in other variables, you may consider using deep implicit object properties deletion.

Solution 3 - Javascript

I can see only one correct solution for removing own properties from object:

for (var x in objectToClean) if (objectToClean.hasOwnProperty(x)) delete objectToClean[x];

If you want to use it more than once, you should create a cleaning function:

function deleteProperties(objectToClean) {
  for (var x in objectToClean) if (objectToClean.hasOwnProperty(x)) delete objectToClean[x];
}

For your case the usage would be:

deleteProperties(req.session);

This solution removes properties from the object wherever it's referenced and keeping the old reference.
Example:
Using empty object assignment:

var x = {a: 5};
var y = x;
x = {};    // x will be empty but y is still {a: 5}, also now reference is gone: x !== y

Using cleaning method:

var x = {a: 5};
var y = x;
deleteProperties(x);  // x and y are both empty and x === y

Solution 4 - Javascript

If you want to delete all properties without touching methods you can use :

for(var k in req.session) if(!req.session[k].constructor.toString().match(/^function Function\(/)) delete req.session[k];

Solution 5 - Javascript

I've done it like this

var 
    i,
    keys = Object.keys(obj);
for(i = 0; i < keys.length; i++){
    delete obj[keys[i]];
}

You could add it to Object (prototype's not ideal here) - will be static.

Object.defineproperties(Object, {
    'clear': function(target){
        var 
            i,
            keys = Object.keys(target);
        for(i = 0; i < keys.length; i++){
            delete target[keys[i]];
        }
    }
});

Then you can clear random objects with

Object.clear(yourObj);

yourObj = {} replaces the reference to a new object, the above removes it's properties - reference is the same.

Solution 6 - Javascript

The naive object = {} method is okay for vanilla Object, but it deletes prototypes of custom objects.

This method produces an empty object that preserves prototypes, using Object.getPrototypeOf() and Object.create():

    emptyObj = Object.create(Object.getPrototypeOf(obj), {});

Example:

class Custom extends Object {
  custom() {}
}

let custom = new Custom();
custom.foo = "bar";
console.log(custom.constructor.name, custom);
// Custom {"foo": "bar"}

// naive method:
let objVanilla = {}
console.log(objVanilla.constructor.name, objVanilla);
// Object {}

// safe method:
objSafe = Object.create(Object.getPrototypeOf(custom), {});
console.log(objSafe.constructor.name, objSafe);
// Custom {}

Solution 7 - Javascript

This script removes property recursively except for the data reported in vector.

You need the lodash library

-- Function:

function removeKeysExcept(object, keysExcept = [], isFirstLevel = true) {
        let arrayKeysExcept = [],
            arrayNextKeysExcept = {};
        _.forEach(keysExcept, (value, i) => {
            let j = value.split('.');
            let keyExcept = j[0];
            arrayKeysExcept.push(keyExcept);
            j.shift();
            if (j.length) {
                j = j.join('.');
                if (!arrayNextKeysExcept[keyExcept]) {
                    arrayNextKeysExcept[keyExcept] = [];
                }
                arrayNextKeysExcept[keyExcept].push(j);
            }
        })
        _.forEach(arrayNextKeysExcept, (value, key) => {
            removeKeysExcept(object[key], value, false);
        });
        if (isFirstLevel) {
            return;
        }
        Object.keys(object).forEach(function (key) {
            if (arrayKeysExcept.indexOf(key) == -1) {
                delete object[key];
            }
        });
    }

Run so:

-- Removes all properties except the first level and reported in the vector:

removeKeysExcept(obj, ['department.id','user.id']);

-- Removes all properties

removeKeysExcept(obj, ['department.id','user.id'], false);

-- Example:

let obj = {
    a: {
        aa: 1,
        ab: {
            aba: 21
        }
    },
    b: 10,
    c: {
        ca: 100,
        cb: 200
    }
};

removeKeysExcept(obj, ['a.ab.aba','c.ca']);
/*OUTPUT: {
    a: {
        ab: {
            aba: 21
        }
    },
    b: 10,
    c: {
        ca: 100,
    }
};*/

removeKeysExcept(obj, ['a.ab.aba','c.ca'], false); //Remove too firt level
/*OUTPUT: {
    a: {
        ab: {
            aba: 21
        }
    },
    c: {
        ca: 100,
    }
};*/

removeKeysExcept(obj);
/*OUTPUT: {b:10};*/

removeKeysExcept(obj, [], false); //Remove too firt level
/*OUTPUT: {};*/

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAnders &#214;stmanView Question on Stackoverflow
Solution 1 - JavascriptDave LuggView Answer on Stackoverflow
Solution 2 - JavascriptVisioNView Answer on Stackoverflow
Solution 3 - Javascripticl7126View Answer on Stackoverflow
Solution 4 - JavascriptyentView Answer on Stackoverflow
Solution 5 - JavascriptEnTr0cKsView Answer on Stackoverflow
Solution 6 - JavascriptterrymorseView Answer on Stackoverflow
Solution 7 - JavascriptJoão JúniorView Answer on Stackoverflow