从对象删除所有属性


73

我有这个Javascript对象。

req.session

在我的代码中,我向该对象添加了属性。这些属性可以是其他对象,数组,也可以是纯字符串。

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

如果以后我要擦除此对象的所有添加属性,最简单/最佳方法是什么?

一定有比这更好的方法了吗?

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

Answers:


56

只需分配一个空对象:

req.session = {};

...,垃圾收集器将自动完成其余的工作。


更新:由于这个答案是有争议的,我想在这一点上提供更多的细节。

上面给出的解决方案将为作者在当前情况下工作,以及此问题中提供的任何其他有效解决方案。这主要取决于开发人员如何处理不推荐使用的数据的方式。

会话对象可能包含由不同变量链接的数据,并且将新的空对象设置为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变量引用。

使用@Dave提供的方法或更短的过孔深度清洗对象Object.keys(忽略原型链中的属性,并且对node.js不需要任何填充):

Object.keys(object).forEach(function(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(function(key) { delete req.session[key]; });
console.log( req.session, session );       // {}, {}

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

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

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


1
我想知道最好使用req.session = null或req.session = {}。Express网站建议将其设置为null expressjs.com/api.html#cookieSession
Sriharsha 2013年

58
这是一个有用的答案,但我不认为它是完整的,因为它实际上并未从对象中删除所有属性。如果对同一对象有2个引用,则req.session1和req.session2并分配req.session1 = {}。然后req.session2保持不变,其所有属性仍然定义
Theo

19
尽管结果是一个空对象,但该对象现在引用内存中的新点,即新对象。这意味着,如果对该对象有任何双重引用,它现在就消失了。底线-这不是清空对象,而是将其替换为新对象。
Tomer 2014年

7
这不能回答OP的问题。
皮特·阿尔文

2
他认为它应该打印一个空对象,因为这就是问题所在。从对象删除所有属性后,您将拥有一个空对象。
Dave Lugg 2015年

136

如果您想清除该特定引用,则@VisioN的答案有效,但是如果您实际上想要清除对象,我发现这有效:

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

29
为什么这个答案没有更多支持...实际上是清除对象,而不是创建新对象(如果旧对象引用了某些内容,则旧数据仍会存在)。
basic6 2015年

2
是的 @ basic6说了什么。我今天遇到这个问题,在那里创建一个新对象破坏了我的另一个参考。这应该是正确的答案。
James Manes

是否存在一些JavaScript实现会在枚举属性时混淆删除属性的危险?还是“枚举”中的定义准确地指定了如果在枚举过程中添加和删除属性会发生什么?
亚当·格恩-凯恩

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

6

如果要删除所有属性而不用触摸方法,则可以使用:

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

谢谢^^constructor.toString()事情是非常有用的,另一件事是:如果您想要的是的改进版本typeof,请尝试Object.prototype.toString.call(thing).replace(/^\[.+\s(.+)\]$/g, '$1').toLowerCase():p
yent 13-10-11

但是,为什么不简单地使用它typeof req.session[k] === 'function'呢?
2013年

非常正确。前一阵子typeof只在数字,字符串,布尔值,null和undefined之间进行了区别,其他所有内容都返回了“对象”,包括函数,所以我养成了使用更精确的东西的习惯。我提供的代码是我使用的较大脚本的一部分,在其中我需要获取使用原型(function foo() { this.a = 1; } foo.prototype.doThing = function ...)定义其类的对象的类名...
yent

for(var k in req.session) if(!(req.session[k] instanceof Function)) delete req.session[k];
米(Domi)2015年

2

我已经做到了

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

您可以将其添加到对象(此处不是理想的原型)-将是静态的。

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 = {} 替换对新对象的引用,以上内容删除了它的属性-引用相同。


我想补充一点,那就是这些操作有些昂贵-进行重组,并且可能有更好的方法可以实现自己的目标。
EnTr0cKs

0

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


0

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

您需要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: {};*/
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.