对象原型:所有属性不区分大小写的读取器

4

我正在尝试创建一个对象,当我搜索属性时,可以不区分大小写地执行该属性的“查找”操作。

var x = new CaseInsensitiveObject();

x.firstProperty = "Hello!";

alert(x.firstproperty); //alerts Hello!

我曾尝试使用Object.defineProperty()来实现这一点,但是它需要将属性的字符串文字作为参数传递(如果你考虑一下,Object.defineProperties()也会有同样的问题)
是否有一种方法可以通用地设置对象所有属性的getter而无需提供键名?例如:
Object.defineAllProperties(obj, {
    get: function(prop)
    {
        if(!prop.toLowerCase && prop.toString)
            prop = prop.toString();
        if(prop.toLowerCase)
            prop = prop.toLowerCase();
        return this[prop];
    }
});

如果不是全部属性,我该如何将一个Object的任意一个属性设置为不区分大小写?!
注意:
我知道扩展Object.prototype通常不是好习惯,但我有我的理由。由于一些数据库的更改,我需要快速修复。最终的修复需要花费几天时间,而在此期间我需要可运行的软件供QA测试。这个prototype方法将使所有事情都能正常工作,直到我完成所有必要的更改,并且这种方法不会被用于任何生产环境。因此,如果您打算反对并责骂我甚至考虑这么做,我是不会听的。
谢谢大家!

我查看了许多其他类似的帖子,但它们并没有真正涉及到这个问题,例如这些(这不是重复的!):大小写不敏感映射为所有对象属性设置原型等等。 - WebWanderer
3
你可以为每个属性名的大小写变形编写一堆 setter/getter 函数。或者,在支持Proxy对象的环境中使用Proxy对象 - apsillers
哈哈,我认为为一个键的所有渗透制作getter和setter可能有点繁琐。不过@apsillers做得很好。Proxy可以工作,但不幸的是它是ECMA6。不能使用它。 - WebWanderer
您的需求听起来似乎只需要一到两个备选拼写,并非所有都需要?我认为您应该手动完成它。 - Bergi
@Bergi,我只有两个备选拼写。apsillers的评论解决了我的问题,但并没有完全回答我的问题。 - WebWanderer
1个回答

0

所以,在遵循@apsillers的评论后,我解决了我的问题(我只需要支持小写和驼峰式大小写)。这并不是我认为理想的解决方案,也没有真正回答我的问题,即如何创建一个不区分大小写的对象属性,但我应该分享一下:

function makeCaseInsensitiveObject(obj)
{
    var keys;

    function PropertyScope(iObj, key, val)
    {
        var value = val;

        var _get = function()
        {
            return value;
        };

        var _set = function(v)
        {
            value = v;
        };

        Object.defineProperty(iObj, key, {
            get: _get,
            set: _set
        });

        Object.defineProperty(iObj, key.toLowerCase(), {
            get: _get,
            set: _set
        });
    };

    if(Object.keys)
        keys = Object.keys(obj);
    else
        keys = getObjectKeys(obj);

    for(var i = 0; i < keys.length; i++)
    {
        if(typeof keys[i] === 'string')
        {
            PropertyScope(obj, keys[i], obj[keys[i]]);
        }
    }

    return obj;
};

请注意,这里的不区分大小写仅适用于现有对象属性,而不适用于任何新属性。

谢谢大家!


1
我正在撰写一份答案,但实际上它就是这样。 我将在此处留下纯粹信息的部分:“根据属性名称执行任意决策”的一般行为类别仅可能通过代理来实现。 没有代理对象,仅可能向任何给定属性名称分配决策功能(即setter / getter)。 换句话说,如果没有代理,您必须提前知道属性名称;没有其他选择。 - apsillers
哎呀!这很糟糕,但是感谢@apsillers!迫不及待地等待ECMA6! - WebWanderer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接