102

假设我有一个对象:

var obj = {
  foo:"bar",
  fizz:"buzz"
};

我需要像这样动态访问该对象的属性:

var objSetter = function(prop,val){
  obj[prop] = val;
}

那里没有问题,除了prop需要不区分大小写以防将属性名称传递给函数,例如,Foo而不是foo.

那么如何不区分大小写按名称指向对象的属性呢?如果可能,我想避免迭代整个对象。

4

17 回答 17

61

试试这个:

var myObject = { "mIxeDCaSEKeY": "value" };

var searchKey = 'mixedCaseKey';
var asLowercase = searchKey.toLowerCase();
myObject[Object.keys(myObject).find(key => key.toLowerCase() === asLowercase)];

您也可以提供小写的 searchKey。

如果你想要它作为一个函数:

/**
  * @param {Object} object
  * @param {string} key
  * @return {any} value
 */
function getParameterCaseInsensitive(object, key) {
  const asLowercase = key.toLowercase();
  return object[Object.keys(object)
    .find(k => k.toLowerCase() === asLowercase)
  ];
}

如果找不到对象,那么它将返回 undefined,就像正常一样。

如果您需要支持较旧的浏览器,则可以filter改用:

function getParameterCaseInsensitive(object, key) {
  const asLowercase = key.toLowercase();
  return object[Object.keys(object).filter(function(k) {
    return k.toLowerCase() === asLowercase;
  })[0]];
}

如果您需要更旧的支持,我建议使用Object.keys()Array.filter()的 polyfill。

于 2017-11-28T17:58:32.427 回答
29

将 obj 的所有属性与 prop 进行比较。

var objSetter = function(prop,val){
  prop = (prop + "").toLowerCase();
  for(var p in obj){
     if(obj.hasOwnProperty(p) && prop == (p+ "").toLowerCase()){
           obj[p] = val;
           break;
      }
   }
}
于 2012-09-18T20:30:53.577 回答
12

为此,我更喜欢使用原型而不是独立函数,只是为了易于使用和表现力。如果我不需要的话,我只是不喜欢将对象汇集到函数中。

此外,虽然公认的答案有效,但我想要一个更全面的解决方案,用于获取和设置,其行为尽可能类似于原生点表示法或括号表示法。

考虑到这一点,我创建了几个原型函数来设置/获取对象属性,而不考虑大小写。在添加到 Object 原型时,您必须记住要非常负责。尤其是在使用 JQuery 和其他库时。将 enumerable 设置为 false 的 Object.defineProperty() 专门用于避免与 JQuery 冲突。我也没有费心为函数命名任何表明它们不区分大小写的东西,但你当然可以。我喜欢较短的名字。

这是吸气剂:

Object.defineProperty(Object.prototype, "getProp", {
    value: function (prop) {
        var key,self = this;
        for (key in self) {
            if (key.toLowerCase() == prop.toLowerCase()) {
                return self[key];
            }
        }
    },
    //this keeps jquery happy
    enumerable: false
});

这是二传手:

Object.defineProperty(Object.prototype, "setProp", {
    value: function (prop, val) {
        var key,self = this;
        var found = false;
        if (Object.keys(self).length > 0) {
            for (key in self) {
                if (key.toLowerCase() == prop.toLowerCase()) {
                    //set existing property
                    found = true;                        
                    self[key] = val;
                    break;
                }
            }
        }

        if (!found) {
            //if the property was not found, create it
            self[prop] = val;
        }  

        return val;
    },
    //this keeps jquery happy
    enumerable: false
});

现在我们已经创建了这些函数,我们的代码非常干净简洁,并且可以正常工作。

不区分大小写的获取:

var obj = {foo: 'bar', camelCase: 'humpy'}

obj.getProp("FOO");          //returns 'bar'
obj.getProp("fOO");          //returns 'bar'
obj.getProp("CAMELCASE");    //returns 'humpy' 
obj.getProp("CamelCase");    //returns 'humpy'

不区分大小写的设置:

var obj = {foo: 'bar', camelCase: 'humpy'}

obj.setProp('CAmelCasE', 'super humpy');     //sets prop 'camelCase' to 'super humpy'
obj.setProp('newProp', 'newval');      //creates prop 'newProp' and sets val to 'newval'  
obj.setProp('NewProp', 'anotherval');  //sets prop 'newProp' to 'anotherval'
于 2015-10-15T22:28:10.293 回答
7

已经提出的另一种变体将迭代向下推入下划线/LodashfindKey函数:

var _ = require('underscore');
var getProp = function (obj, name) {
    var realName = _.findKey(obj, function (value, key) {
        return key.toLowerCase() === name.toLowerCase();
    });
    return obj[realName];
};

例如:

var obj = { aa: 1, bB: 2, Cc: 3, DD: 4 };
getProp(obj, 'aa'); // 1
getProp(obj, 'AA'); // 1
getProp(obj, 'bb'); // 2
getProp(obj, 'BB'); // 2
getProp(obj, 'cc'); // 3
getProp(obj, 'CC'); // 3
getProp(obj, 'dd'); // 4
getProp(obj, 'DD'); // 4
getProp(obj, 'EE'); // undefined
于 2016-12-28T06:48:41.567 回答
2

您可以这样做以“正常化”prop

 var normalizedProp = prop.toLowerCase();
 obj[normalizedProp] = val;
于 2012-09-18T20:26:41.673 回答
2

在我看来,它是带有陷阱的代理的一个很好的候选者,可以将字符串键转换为大写或小写,并且表现得像一个常规对象。这适用于任何一种表示法:点或括号

这是代码:

'use strict';

function noCasePropObj(obj)
{
	var handler =
	{
		get: function(target, key)
			{
				//console.log("key: " + key.toString());
				if (typeof key == "string")
				{
					var uKey = key.toUpperCase();

					if ((key != uKey) && (key in target))
						return target[key];
					return target[uKey];
				}
				return target[key];
			},
		set: function(target, key, value)
			{
				if (typeof key == "string")
				{
					var uKey = key.toUpperCase();

					if ((key != uKey) && (key in target))
						target[key] = value;
					target[uKey] = value;
				}
				else
					target[key] = value;
			},
		deleteProperty: function(target, key)
			{
				if (typeof key == "string")
				{
					var uKey = key.toUpperCase();

					if ((key != uKey) && (key in target))
						delete target[key];
					if (uKey in target)
						delete target[uKey];
				}
				else
					delete target[key];
			},
	};
	function checkAtomic(value)
	{
		if (typeof value == "object")
			return new noCasePropObj(value); // recursive call only for Objects
		return value;
	}

	var newObj;

	if (typeof obj == "object")
	{
		newObj = new Proxy({}, handler);
        // traverse the Original object converting string keys to upper case
		for (var key in obj)
		{
			if (typeof key == "string")
			{
				var objKey = key.toUpperCase();

				if (!(key in newObj))
					newObj[objKey] = checkAtomic(obj[key]);
			}
		}
	}
	else if (Array.isArray(obj))
	{
        // in an array of objects convert to upper case string keys within each row
		newObj = new Array();
		for (var i = 0; i < obj.length; i++)
			newObj[i] = checkAtomic(obj[i]);
	}
	return newObj; // object with upper cased keys
}

// Use Sample:
var b = {Name: "Enrique", last: "Alamo", AdDrEsS: {Street: "1233 Main Street", CITY: "Somewhere", zip: 33333}};
console.log("Original: " + JSON.stringify(b));  // Original: {"Name":"Enrique","last":"Alamo","AdDrEsS":{"Street":"1233 Main Street","CITY":"Somewhere","zip":33333}}
var t = noCasePropObj(b);
console.log(JSON.stringify(t)); // {"NAME":"Enrique","LAST":"Alamo","ADDRESS":{"STREET":"1233 Main Street","CITY":"Somewhere","ZIP":33333}}
console.log('.NaMe:' + t.NaMe); // .NaMe:Enrique
console.log('["naME"]:' + t["naME"]); // ["naME"]:Enrique
console.log('.ADDreSS["CitY"]:' + t.ADDreSS["CitY"]); // .ADDreSS["CitY"]:Somewhere
console.log('check:' + JSON.stringify(Object.getOwnPropertyNames(t))); // check:["NAME","LAST","ADDRESS"]
console.log('check2:' + JSON.stringify(Object.getOwnPropertyNames(t['AddresS']))); // check2:["STREET","CITY","ZIP"]

于 2018-04-30T14:38:41.963 回答
2

这个答案需要 ES6。

const x = { 'aB': 1, 'X-Total-Count': 10, y3: 2 }
console.log(x[Object.keys(x).find(key=>{return key.match(/^ab$/i)})])
console.log(x[Object.keys(x).find(key=>{return key.match(/^x-total-count$/i)})])
console.log(x[Object.keys(x).find(key=>{return key.match(/^y3$/i)})])

于 2020-04-30T02:59:39.263 回答
1
const getPropertyNoCase = (obj, prop) => obj[Object.keys(obj).find(key => key.toLowerCase() === prop.toLowerCase() )];

或者

const getPropertyNoCase = (obj, prop) => {
    const lowerProp = prop.toLowerCase(obj[Object.keys(obj).find(key => key.toLowerCase() === prop.toLowerCase() )];
}
于 2020-05-13T15:00:44.080 回答
1

@nilloc 发布的 ES6 示例不正确,将无法使用。

这是一个工作示例:

const x = {'first':5,'X-Total-Count':10,'third':20};
console.log(x[Object.keys(x).reduce((result,key)=>{
   if (!result) {
      return key.match(/x-total-count/i)
   } else {
      return result;
   }
 },null)]);

或者更好的是,如果键不存在,它应该返回 undefined:

const x = {'first':5,'X-Total-Count':10,'third':20};
console.log(x[Object.keys(x).reduce((result,key)=>{
   if (!result) {
     return key.match(/x-total-count/i) || undefined
   } else {
     return result;
   }
  },undefined)]);

一个考虑是,如果有多个匹配的键,上面的示例将返回对象中最后一个匹配的键。

这是一个将代码制成函数的示例:

/**
  * @param {Object} object
  * @param {string} key
  * @return {string||undefined} value || undefined
 */
function getKeyCase(obj,key) {
  const re = new RegExp(key,"i");
  return Object.keys(obj).reduce((result,key)=>{
   if (!result) {
     return key.match(re) || undefined
   } else {
     return result;
   }
  },undefined);

const x = {'first':5,'X-Total-Count':10,'third':20};

console.log(x[getKeyCase(x,"x-total-count")]);
于 2020-12-02T19:58:24.670 回答
1

不能像看起来那样跳过迭代真的很遗憾。对我来说,可以接受但可能不是每个人都可以通过迭代来塑造对象一次,然后以常规的 hashmap 方式使用它。

const hashmap = {
  'FOO': 'foo as in function programming',
  'bar': 'bar is in baz',
};

const shapedmap = Object.entries(hashmap).reduce(
  (acc, [key, val]) => (acc[key.toUpperCase()] = val, acc), {}
);

for (const term of ['foo', 'bar', 'baz']) {
  const match = shapedmap[term.toUpperCase()]
  match && console.log('awesome, we got the term.', match);
};

即使只需要执行一次查找,它的性能也不会低于任何其他迭代解决方案,因为在 1 次通过后,查找速度是恒定的。(我猜)。

于 2020-12-16T21:22:06.703 回答
0

不需要任何迭代。由于prop可能不是字符串,因此应在适当的情况下首先将其强制转换为字符串,因为这是对象本机所做的。一个简单的 getter 函数是:

function objGetter(prop) {
  return obj[String(prop).toLowerCase()];
}

如果需要重新设置对自己属性的访问权限:

function objGetter(prop) {
  prop = String(prop).toLowerCase();

  if (obj.hasOwnProperty(prop)) {
    return obj.prop;
  }
}

和一个二传手:

function objSetter(prop, val) {
  obj[String(prop).toLowerCase()] = val;
}
于 2012-09-18T21:15:55.777 回答
0

这是一个非常简单的代码来执行此操作假设数据是对象数组,例如

data=[{"A":"bc","B":"nn"}]

var data=data.reduce(function(prev, curr) {
    var cc = curr; // current value
    var K = Object.keys(cc); // get all keys
    var n = {};
    for (var i = 0; i < K.length; i++) {
        var key = K[i];//get hte key

        n[key.toLowerCase()] = cc[key] // convert to lowercase and assign 
    }
    prev.push(n) // push to array
    return prev;
}, [])

输出将是

data=[{"a":"bc","b":"nn"}]
于 2015-11-25T15:51:06.620 回答
0

如果区分大小写的匹配(便宜且快速)失败,您可能只需要进行不区分大小写的匹配(通常由于对象迭代而昂贵)。

假设你有:

var your_object = { "Chicago" : 'hi' , "deTroiT" : 'word' , "atlanta" : 'get r dun' } ;

无论出于何种原因,您都有 the_value, Detroit

if( your_object.hasOwnProperty( the_value ) ) 
  { 
    // do what you need to do here
  } 
else  
  { // since the case-sensitive match did not succeed, 
    //   ... Now try a the more-expensive case-insensitive matching

    for( let lvs_prop in your_object ) 
      { if( the_value.toLowerCase()  == lvs_prop.toLowerCase() ) 
          { 

            // do what you need to do here

            break ;
          } ;
      } 
  } ;
于 2016-05-23T14:22:43.377 回答
0

当我们简单地把它全部变成小写时,为什么我们要做得那么复杂:

    var your_object = { 
"chickago" : 'hi' ,
 "detroit" : 'word', 
 "atlanta" : 'get r dun',     
GetName: function (status) {
        return this[status].name;
    } };

称之为: your_object.GetName(your_var.toLowerCase());

于 2016-12-22T16:11:30.923 回答
0

另一种简单的方法:

function getVal(obj, prop){
var val;
  prop = (prop + "").toLowerCase();
  for(var p in obj){
     if(obj.hasOwnProperty(p) && prop == (p+ "").toLowerCase()){
           val = obj[p]
           break;
      }
   }
   return val;
}

像这样使用它:

var obj = {
  foo:"bar",
  fizz:"buzz"
};
    getVal(obj,"FoO") -> returns "bar"
于 2018-01-12T12:56:15.823 回答
0

这是一个很好的递归函数,它允许您以不区分大小写的方式遍历 javascript 对象:

let testObject = {'a': {'B': {'cC': [1,2,3]}}}
let testSeq = ['a','b','cc']

function keySequence(o, kseq) {
  if(kseq.length==0){ return o; }
  let validKeys = Object.keys(o).filter(k=>k.toLowerCase()==kseq[0].toLowerCase());
  if(validKeys.length==0) { return `Incorrect Key: ${kseq[0]}` }
  return keySequence(o[validKeys[0]], kseq.slice(1))
}

keySequence(testObject, testSeq); //returns [1,2,3]
于 2020-10-22T15:16:46.753 回答
0

这会将所有内容都转换为小写,但如果您不关心保留大小写,这可能会有所帮助。

var somedata = {
    "MixEdCase": 1234
}

var temp = JSON.parse(JSON.stringify(somedata).toLowerCase());

console.log(temp.mixedcase);
// or
console.log(temp["mixedcase"]);
于 2021-03-17T07:35:25.837 回答