Multiple key names, same pair value

后端 未结 9 1712
萌比男神i
萌比男神i 2020-12-08 13:33

I\'m trying to setup an object literal in a JavaScript script that has a key with multiple names. referring to the same object value i.e. something like these that I have al

相关标签:
9条回答
  • 2020-12-08 14:00

    With ES6 you could do it like this, but it's not ideal:

    const holidays = {
        "single": {
            singleValue: "foo",
        },
    
        ...([
            "thanksgiving day", "thanksgiving", "t-day",
        ].reduce((a, v) => ({...a, [v]: {
            someValue: "foo",
        }}), {})),
    
        "other": {
            otherValue: "foo",
        },
    };
    

    I still think the cleanest solution is probably:

    let holidays = {
        "t-day": {
            someValue: "foo",
        },
    };
    holidays["thanksgiving"] = holidays["t-day"];
    holidays["thanksgiving day"] = holidays["t-day"];
    
    0 讨论(0)
  • 2020-12-08 14:02

    Now this may be overkill for you, but here's a generic function that will create an object with "multiple keys." What it actually does is have one real property with the actual value, and then defines getters and setters to forward operations from the virtual keys to the actual property.

    function multiKey(keyGroups) {
        let obj = {};
        let props = {};
    
        for (let keyGroup of keyGroups) {
            let masterKey = keyGroup[0];
            let prop = {
                configurable: true,
                enumerable: false,
    
                get() {
                    return obj[masterKey];
                },
    
                set(value) {
                    obj[masterKey] = value;
                }
            };
    
            obj[masterKey] = undefined;
            for (let i = 1; i < keyGroup.length; ++i) {
                if (keyGroup.hasOwnProperty(i)) {
                    props[keyGroup[i]] = prop;
                }
            }
        }
    
        return Object.defineProperties(obj, props);
    }
    

    This is less sketchy than you would expect, has basically no performance penalty once the object is created, and behaves nicely with enumeration (for...in loops) and membership testing (in operator). Here's some example usage:

    let test = multiKey([
        ['north', 'up'],
        ['south', 'down'],
        ['east', 'left'],
        ['west', 'right']
    ]);
    
    test.north = 42;
    test.down = 123;
    
    test.up; // returns 42
    test.south; // returns 123
    
    let count = 0;
    for (let key in test) {
        count += 1;
    }
    
    count === 4; // true; only unique (un-linked) properties are looped over
    

    Taken from my Gist, which you may fork.

    0 讨论(0)
  • 2020-12-08 14:11

    Another approach is to do some postprocessing

    function expand(obj) {
        var keys = Object.keys(obj);
        for (var i = 0; i < keys.length; ++i) {
            var key = keys[i],
                subkeys = key.split(/,\s?/),
                target = obj[key];
            delete obj[key];
            subkeys.forEach(function(key) { obj[key] = target; })
        }
        return obj;
    }
    
    var holidays = expand({
        "thanksgiving day, thanksgiving, t-day": {
            someValue : "foo"
        } 
    });
    
    0 讨论(0)
  • 2020-12-08 14:12
    //create some objects(!) you want to have aliases for..like tags
    var {learn,image,programming} = 
     ["learn", "image", "programming"].map(tag=>({toString:()=>tag }));
    
    
    //create arbitrary many aliases using a Map
    var alias = new Map();
    alias.set("photo", image);
    alias.set("pic", image);
    alias.set("learning", learn);
    alias.set("coding", programming);
    
    //best put the original tagNames in here too.. 
    //pretty easy huh? 
    
    // returns the image object 
    alias.get("pic");
    
    // ;)
    
    0 讨论(0)
  • 2020-12-08 14:13

    Another solution, if you can afford RegExp execution, and ES6 Proxy:

    let align = new Proxy({
    
        'start|top|left': -1,
        'middle|center': 0,
        'end|bottom|right': 1,
    
    }, {
    
        get: function(target, property, receiver) {
    
            for (let k in target)
                if (new RegExp(k).test(property))
                    return target[k]
    
            return null
    
        }
    
    })
    
    align.start     // -1
    align.top       // -1
    align.left      // -1
    
    align.middle    // 0
    align.center    // 0
    
    align.end       // 1
    align.bottom    // 1
    align.right     // 1
    

    See docs:
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/get

    0 讨论(0)
  • 2020-12-08 14:14

    I guess you could do something like this:

    var holidays = {
      'thanksgiving day': {
        foo: 'foo'
      }
    };
    
    holidays.thanksgiving = holidays['t-day'] = holidays['thanksgiving day'];
    

    If you see yourself doing this often or you have more values consider this pattern:

    'thanksgiving, t-day, thanks, thank, thank u'.split(',').forEach(function(key) {
      holidays[key] = holidays['thanksgiving day'];
    });
    

    A better approach would be to process your data beforehand instead of adding duplicates.

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