How to quickly clear a JavaScript Object?

后端 未结 8 1077
一个人的身影
一个人的身影 2020-11-27 12:52

With a JavaScript Array, I can reset it to an empty state with a single assignment:

array.length = 0;

This makes the Array \"appear\" empty

相关标签:
8条回答
  • 2020-11-27 13:05

    Something new to think about looking forward to Object.observe in ES7 and with data-binding in general. Consider:

    var foo={
       name: "hello"
    };
    
    Object.observe(foo, function(){alert('modified');}); // bind to foo
    
    foo={}; // You are no longer bound to foo but to an orphaned version of it
    foo.name="there"; // This change will be missed by Object.observe()
    

    So under that circumstance #2 can be the best choice.

    0 讨论(0)
  • 2020-11-27 13:07

    You can try this. Function below sets all values of object's properties to undefined. Works as well with nested objects.

    var clearObjectValues = (objToClear) => {
        Object.keys(objToClear).forEach((param) => {
            if ( (objToClear[param]).toString() === "[object Object]" ) {
                clearObjectValues(objToClear[param]);
            } else {
                objToClear[param] = undefined;
            }
        })
        return objToClear;
    };
    
    0 讨论(0)
  • 2020-11-27 13:11

    ES5

    ES5 solution can be:

    // for enumerable and non-enumerable properties
    Object.getOwnPropertyNames(obj).forEach(function (prop) {
      delete obj[prop];
    });
    

    ES6

    And ES6 solution can be:

    // for enumerable and non-enumerable properties
    for (const prop of Object.getOwnPropertyNames(obj)) {
      delete obj[prop];
    }
    

    Performance

    Regardless of the specs, the quickest solutions will generally be:

    // for enumerable and non-enumerable of an object with proto chain
    var props = Object.getOwnPropertyNames(obj);
    for (var i = 0; i < props.length; i++) {
      delete obj[props[i]];
    }
    
    // for enumerable properties of shallow/plain object
    for (var key in obj) {
      // this check can be safely omitted in modern JS engines
      // if (obj.hasOwnProperty(key))
        delete obj[key];
    }
    

    The reason why for..in should be performed only on shallow or plain object is that it traverses the properties that are prototypically inherited, not just own properties that can be deleted. In case it isn't known for sure that an object is plain and properties are enumerable, for with Object.getOwnPropertyNames is a better choice.

    0 讨论(0)
  • 2020-11-27 13:14

    So to recap your question: you want to avoid, as much as possible, trouble with the IE6 GC bug. That bug has two causes:

    1. Garbage Collection occurs once every so many allocations; therefore, the more allocations you make, the oftener GC will run;
    2. The more objects you've got ‘in the air’, the more time each Garbage Collection run takes (since it'll crawl through the entire list of objects to see which are marked as garbage).

    The solution to cause 1 seems to be: keep the number of allocations down; assign new objects and strings as little as possible.

    The solution to cause 2 seems to be: keep the number of 'live' objects down; delete your strings and objects as soon as you don't need them anymore, and create them afresh when necessary.

    To a certain extent, these solutions are contradictory: to keep the number of objects in memory low will entail more allocations and de-allocations. Conversely, constantly reusing the same objects could mean keeping more objects in memory than strictly necessary.


    Now for your question. Whether you'll reset an object by creating a new one, or by deleting all its properties: that will depend on what you want to do with it afterwards.

    You’ll probably want to assign new properties to it:

    • If you do so immediately, then I suggest assigning the new properties straightaway, and skip deleting or clearing first. (Make sure that all properties are either overwritten or deleted, though!)
    • If the object won't be used immediately, but will be repopulated at some later stage, then I suggest deleting it or assigning it null, and create a new one later on.

    There's no fast, easy to use way to clear a JScript object for reuse as if it were a new object — without creating a new one. Which means the short answer to your question is ‘No’, like jthompson says.

    0 讨论(0)
  • 2020-11-27 13:21

    You can delete the props, but don't delete variables. delete abc; is invalid in ES5 (and throws with use strict).

    You can assign it to null to set it for deletion to the GC (it won't if you have other references to properties)

    Setting length property on an object does not change anything. (it only, well, sets the property)

    0 讨论(0)
  • 2020-11-27 13:25

    This bugged me for ages so here is my version as I didn't want an empty object, I wanted one with all the properties but reset to some default value. Kind of like a new instantiation of a class.

    let object1 = {
      a: 'somestring',
      b: 42,
      c: true,
      d:{
        e:1,
        f:2,
        g:true,
        h:{
          i:"hello"
        }
      },
      j: [1,2,3],
      k: ["foo", "bar"],
      l:["foo",1,true],
      m:[{n:10, o:"food", p:true }, {n:11, o:"foog", p:true }],
      q:null,
      r:undefined
    };
    
    let boolDefault = false;
    let stringDefault = "";
    let numberDefault = 0;
    
    console.log(object1);
    //document.write("<pre>");
    //document.write(JSON.stringify(object1))
    //document.write("<hr />");
    cleanObject(object1);
    console.log(object1);
    //document.write(JSON.stringify(object1));
    //document.write("</pre>");
    
    function cleanObject(o) {
      for (let [key, value] of Object.entries(o)) {
        let propType = typeof(o[key]);
    
        //console.log(key, value, propType);
    
        switch (propType) {
          case "number" :
            o[key] = numberDefault;
            break;
    
          case "string":
            o[key] = stringDefault;
            break;
    
          case "boolean":
            o[key] = boolDefault;    
            break;
    
          case "undefined":
            o[key] = undefined;   
            break;
    
          default:
            if(value === null) {
                continue;
            }
    
            cleanObject(o[key]);
            break;
        }
      }
    }
    
    // EXPECTED OUTPUT
    // Object { a: "somestring", b: 42, c: true, d: Object { e: 1, f: 2, g: true, h: Object { i: "hello" } }, j: Array [1, 2, 3], k: Array ["foo", "bar"], l: Array ["foo", 1, true], m: Array [Object { n: 10, o: "food", p: true }, Object { n: 11, o: "foog", p: true }], q: null, r: undefined }
    // Object { a: "", b: 0, c: undefined, d: Object { e: 0, f: 0, g: undefined, h: Object { i: "" } }, j: Array [0, 0, 0], k: Array ["", ""], l: Array ["", 0, undefined], m: Array [Object { n: 0, o: "", p: undefined }, Object { n: 0, o: "", p: undefined }], q: null, r: undefined }

    0 讨论(0)
提交回复
热议问题