admin管理员组

文章数量:1356908

I am looking to set inner properties of an object only if they already exist. Lodash _.set will create the whole hierarchy if it does not exist.

Is there an easy way to do this ? (Without and if statement ?)

Snippet below:

const obj = {a: {b: 1}};

_.set(obj, 'a.b', 2);

console.log(obj); // Great !

_.set(obj, 'a.c', 1);

console.log(obj); // Great but not what I want. I would like c not to be set because it does not exist in the first place
<script src=".js/4.17.4/lodash.min.js"></script>

I am looking to set inner properties of an object only if they already exist. Lodash _.set will create the whole hierarchy if it does not exist.

Is there an easy way to do this ? (Without and if statement ?)

Snippet below:

const obj = {a: {b: 1}};

_.set(obj, 'a.b', 2);

console.log(obj); // Great !

_.set(obj, 'a.c', 1);

console.log(obj); // Great but not what I want. I would like c not to be set because it does not exist in the first place
<script src="https://cdnjs.cloudflare./ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Share Improve this question asked Dec 7, 2017 at 2:53 klugjoklugjo 20.9k10 gold badges64 silver badges81 bronze badges 2
  • 6 Check it with _.has first? – zerkms Commented Dec 7, 2017 at 2:57
  • 1 lodash./docs/4.17.4#has – charlietfl Commented Dec 7, 2017 at 2:58
Add a ment  | 

4 Answers 4

Reset to default 3

you can try by this way

const obj = {a: {b: 1}};

_.set(obj, 'a.b', 2);

console.log(obj); // Great !
_.has(obj,'a.c')==true?_.set(obj, 'a.c', 1):""

console.log(obj); // Great but not what I want. I would like c not to be set because it does not exist in the first place
<script src="https://cdnjs.cloudflare./ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

The answer from Kalaiselvan A below put me on the way but this is not quite what I was looking for.

Using the same idea but improving the ternary gives me the following solution which I am happy with.

const obj = {a: {b: 1}};

_.has(obj, 'a.b') && _.set(obj, 'a.b', 2);

console.log(obj);

_.has(obj, 'a.c') && _.set(obj, 'a.c', 2);

console.log(obj);
<script src="https://cdn.jsdelivr/lodash/4/lodash.min.js"></script>

You could look at Object.seal

Though, you'll want to "deeply" seal the object:

const sealDeep = obj => {
    const sealProps = o => {
        Object.values(o).forEach(value => {
            if (typeof value === 'object') {
                sealProps(value);
                Object.seal(value);
            }
        });
    };
    sealProps(obj);
    Object.seal(obj);
};

var x = {
    hello: {
        world: {
            foo: 1,
            bar: 2
        },
        bat: '3'
    },
    foo2: 4
};
sealDeep(x);
console.log(JSON.stringify(x));
x.newthing = 999;
x.hello.newthing = 999;
x.hello.world.newthing = 999;
x.hello.world.foo = 999;
console.log(JSON.stringify(x));

I was looking for the same thing, and settled for this non-lodash solution

function overridePropertyByJsonPath(obj, thePath, value) {
  const path = thePath.split('.');
  let i
  for (i = 0; i < path.length - 1; i++) {
    const val = obj[path[i]]
    if (val === undefined) {
      return
    }
    obj = val
  }
  if (obj[path[i]] === undefined) {
    return
  }
  obj[path[i]] = value;
}

It passes all these tests I came up with


describe("Key overriding should allow ", () => {
  it("override shallow key", () => {
    const o = { a1: true }
    overridePropertyByJsonPath(o, "a1", false)
    expect(o["a1"]).toEqual(false)
  })
  it("no extra key with non-empty object", () => {
    const o = { a1: true }
    overridePropertyByJsonPath(o, "a2", false)
    expect(o["a2"]).toBeUndefined()
  })

  it("no extra keys with empty object", () => {
    const o = {}
    overridePropertyByJsonPath(o, "not_there_to_begin_with", true)
    expect(o["not_there_to_begin_with"]).toBeUndefined()
  })
  it("no extra keys in override (deep)", () => {
    const o = { a: { b: true } }
    overridePropertyByJsonPath(o, "a.b.not_there_to_begin_with", true)
    expect(o["a"]["b"]["not_there_to_begin_with"]).toBeUndefined()
  })
  it("no extra keys in override (too deep)", () => {
    const o = { a: { b: true } }
    overridePropertyByJsonPath(o, "a.b.c.not_there_to_begin_with", true)
    expect(o["a"]["b"]["c"]).toBeUndefined()
  })
  it("override deep key", () => {
    const o = { a: { b: true } }
    overridePropertyByJsonPath(o, "a.b", false)
    expect(o["a"]["b"]).toEqual(false)
  })
  it("override deep key with array value", () => {
    const o = { a: { b: [1] } }
    overridePropertyByJsonPath(o, "a.b", [2])
    expect(o["a"]["b"]).toContain(2)
    expect(o["a"]["b"].length).toEqual(1)
  })
  it("override deep key with object value", () => {
    const o = { a: { b: {} } }
    overridePropertyByJsonPath(o, "a.b", { "x": true })
    expect(o["a"]["b"]["x"]).toEqual(true)
  })

})

本文标签: javascriptLodash set only if object existsStack Overflow