代码之家  ›  专栏  ›  技术社区  ›  klugjo

洛达斯_。仅当对象存在时设置

  •  1
  • klugjo  · 技术社区  · 7 年前

    我希望仅当对象的内部属性已经存在时才设置它们。洛达斯 _.set 如果不存在,将创建整个层次结构。

    有没有简单的方法?(没有和如果声明?)

    下面的代码段:

    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.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
    4 回复  |  直到 7 年前
        1
  •  3
  •   Kalaiselvan    7 年前

    你可以这样试试

    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.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
        2
  •  1
  •   Jaromanda X    7 年前

    你可以看看 Object.seal

    不过,您需要“深度”密封该对象:

    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));
        3
  •  1
  •   klugjo    7 年前

    下面来自Kalaiselvan A的答案让我走上了正轨,但这并不是我想要的。

    使用相同的想法,但改进了三元结构,得到了以下我满意的解决方案。

    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.net/lodash/4/lodash.min.js"></script>
        4
  •  0
  •   sscarduzio    3 年前

    我也在寻找同样的东西,并满足于这种非lodash解决方案

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

    它通过了我提出的所有测试

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