88

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;
4

7 回答 7

153

如果您想清除该特定引用,@VisioN 的答案有效,但如果您真的想清除一个对象,我发现这有效:

for (var variableKey in vartoClear){
    if (vartoClear.hasOwnProperty(variableKey)){
        delete vartoClear[variableKey];
    }
}
于 2015-02-17T20:25:27.260 回答
69

该问题有两种可能的解决方案:

分配一个空对象

req.session = {};

垃圾收集器会自动清理内存。此变体速度非常快,并且在大多数情况下都可以使用,但是,您需要谨慎使用它,因为它可能会将对对象的引用保留在内存中。此警告在下面的TLDR部分中进行了描述。

一个一个地删除属性

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

这将通过检查每个非原型属性并删除它来清理对象。它更安全但更慢。您需要确定在特定情况下使用它是否有意义。


TLDR

上面给出的任何解决方案都将在当前情况下为作者完成工作,以及此问题中提供的任何其他有效解决方案。这主要取决于开发人员希望如何操作已弃用的数据。

会话对象可能包含由不同变量链接的数据,并且设置一个新的空对象req.session不会破坏对旧数据的引用,因此旧数据将在仍然需要的地方可用。尽管保留旧数据的正确方法是克隆初始对象,但实际情况可能会有所不同。让我们看下面的例子:

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}

session我们仍然可以从变量中获取旧数据,但req.session它是空的:这里设置一个新对象可以作为深度克隆的一种替代方法。垃圾收集器不会从旧req.session对象中删除数据,因为它仍然被session变量引用。

使用以下方法对物体进行深度清洁:

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

... 将从对象中显式删除所有值,req.session并且由于session变量链接到同一个对象,session因此也将变为空。让我们看看它是如何工作的:

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 );       // {}, {}

正如您现在所看到的,在这两种情况下,我们都会得到空对象。

从速度和内存的角度来看,设置一个新的空对象将比按属性清理旧对象属性快得多,但是如果旧数据仍然在某处引用,则新对象方法不会释放旧数据所在的内存消耗。

很明显,选择要采用的方法主要取决于您的编码方案,但在大多数情况下req.session = {};可以完成工作:它既快又短。但是,如果您在其他变量中保留对原始对象的引用,则可以考虑使用深层隐式对象属性删除。

于 2013-10-11T11:20:21.533 回答
13

我只能看到一种从对象中删除自己的属性的正确解决方案:

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

如果你想多次使用它,你应该创建一个清理函数:

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

对于您的情况,用法是:

deleteProperties(req.session);

此解决方案从对象中删除它被引用的任何属性并保留旧引用。
示例:
使用空对象赋值:

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

使用清洗方法:

var x = {a: 5};
var y = x;
deleteProperties(x);  // x and y are both empty and x === y
于 2015-07-07T09:25:44.350 回答
6

如果您想在不触及方法的情况下删除所有属性,您可以使用:

for(var k in req.session) if(!req.session[k].constructor.toString().match(/^function Function\(/)) delete req.session[k];
于 2013-10-11T11:26:51.920 回答
2

我已经这样做了

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

您可以将它添加到 Object (原型在这里并不理想) - 将是静态的。

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

然后你可以清除随机对象

Object.clear(yourObj);

yourObj = {}替换对新对象的引用,上面删除了它的属性 - 引用是相同的。

于 2015-08-05T14:08:47.597 回答
0

naiveobject = {}方法对于 vanilla Object 是可以的,但它会删除自定义对象的原型。

此方法使用Object.getPrototypeOf()Object.create()生成一个保留原型的空对象:

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

例子:

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 {}

于 2020-02-19T17:41:40.430 回答
-1

此脚本以递归方式删除属性,但向量中报告的数据除外。

你需要lodash 库

- 功能:

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];
            }
        });
    }

运行:

-- 删除除第一级以外的所有属性并在向量中报告:

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

-- 删除所有属性

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

- 例子:

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: {};*/
于 2018-02-23T14:02:42.327 回答