Remove value from object without mutation

后端 未结 8 772
天涯浪人
天涯浪人 2020-12-07 18:50

What\'s a good and short way to remove a value from an object at a specific key without mutating the original object?

I\'d like to do something like:



        
8条回答
  •  感情败类
    2020-12-07 19:17

    To add some spice bringing in Performance. Check this thread bellow

    https://github.com/googleapis/google-api-nodejs-client/issues/375

    The use of the delete operator has performance negative effects for the V8 hidden classes pattern. In general it's recommended do not use it.

    Alternatively, to remove object own enumerable properties, we could create a new object copy without those properties (example using lodash):

    _.omit(o, 'prop', 'prop2')

    Or even define the property value to null or undefined (which is implicitly ignored when serializing to JSON):

    o.prop = undefined

    You can use too the destructing way

    const {remov1, remov2, ...new} = old;
    old = new;
    

    And a more practical exmple:

    this._volumes[this._minCandle] = undefined;
    { 
         const {[this._minCandle]: remove, ...rest} = this._volumes;
         this._volumes = rest; 
    }
    

    As you can see you can use [somePropsVarForDynamicName]: scopeVarName syntax for dynamic names. And you can put all in brackets (new block) so the rest will be garbage collected after it.

    Here a test:

    exec:

    Or we can go with some function like

    function deleteProps(obj, props) {
        if (!Array.isArray(props)) props = [props];
        return Object.keys(obj).reduce((newObj, prop) => {
            if (!props.includes(prop)) {
                newObj[prop] = obj[prop];
            }
            return newObj;
        }, {});
    }
    

    for typescript

    function deleteProps(obj: Object, props: string[]) {
        if (!Array.isArray(props)) props = [props];
        return Object.keys(obj).reduce((newObj, prop) => {
            if (!props.includes(prop)) {
                newObj[prop] = obj[prop];
            }
            return newObj;
        }, {});
    }
    

    Usage:

    let a = {propH: 'hi', propB: 'bye', propO: 'ok'};
    
    a = deleteProps(a, 'propB'); 
    
    // or 
    
    a = deleteProps(a, ['propB', 'propO']);
    

    This way a new object is created. And the fast property of the object is kept. Which can be important or matter. If the mapping and the object will be accessed many many times.

    Also associating undefined can be a good way to go with. When you can afford it. And for the keys you can too check the value. For instance to get all the active keys you do something like:

    const allActiveKeys = Object.keys(myObj).filter(k => myObj[k] !== undefined);
    //or
    const allActiveKeys = Object.keys(myObj).filter(k => myObj[k]); // if any false evaluated value is to be stripped.
    

    Undefined is not suited though for big list. Or development over time with many props to come in. As the memory usage will keep growing and will never get cleaned. So it depend on the usage. And just creating a new object seem to be the good way.

    Then the Premature optimization is the root of all evil will kick in. So you need to be aware of the trade off. And what is needed and what's not.

    Note about _.omit() from lodash

    It's removed from version 5. You can't find it in the repo. And here an issue that talk about it.

    https://github.com/lodash/lodash/issues/2930

    v8

    You can check this which is a good reading https://v8.dev/blog/fast-properties

提交回复
热议问题