假设我有一个对象:
var obj = {
foo:"bar",
fizz:"buzz"
};
我需要像这样动态访问该对象的属性:
var objSetter = function(prop,val){
obj[prop] = val;
}
那里没有问题,除了prop
需要不区分大小写以防将属性名称传递给函数,例如,Foo
而不是foo
.
那么如何不区分大小写按名称指向对象的属性呢?如果可能,我想避免迭代整个对象。
假设我有一个对象:
var obj = {
foo:"bar",
fizz:"buzz"
};
我需要像这样动态访问该对象的属性:
var objSetter = function(prop,val){
obj[prop] = val;
}
那里没有问题,除了prop
需要不区分大小写以防将属性名称传递给函数,例如,Foo
而不是foo
.
那么如何不区分大小写按名称指向对象的属性呢?如果可能,我想避免迭代整个对象。
试试这个:
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。
将 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;
}
}
}
为此,我更喜欢使用原型而不是独立函数,只是为了易于使用和表现力。如果我不需要的话,我只是不喜欢将对象汇集到函数中。
此外,虽然公认的答案有效,但我想要一个更全面的解决方案,用于获取和设置,其行为尽可能类似于原生点表示法或括号表示法。
考虑到这一点,我创建了几个原型函数来设置/获取对象属性,而不考虑大小写。在添加到 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'
已经提出的另一种变体将迭代向下推入下划线/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
您可以这样做以“正常化”prop
var normalizedProp = prop.toLowerCase();
obj[normalizedProp] = val;
在我看来,它是带有陷阱的代理的一个很好的候选者,可以将字符串键转换为大写或小写,并且表现得像一个常规对象。这适用于任何一种表示法:点或括号
这是代码:
'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"]
这个答案需要 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)})])
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() )];
}
@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")]);
不能像看起来那样跳过迭代真的很遗憾。对我来说,可以接受但可能不是每个人都可以通过迭代来塑造对象一次,然后以常规的 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 次通过后,查找速度是恒定的。(我猜)。
不需要任何迭代。由于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;
}
这是一个非常简单的代码来执行此操作假设数据是对象数组,例如
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"}]
如果区分大小写的匹配(便宜且快速)失败,您可能只需要进行不区分大小写的匹配(通常由于对象迭代而昂贵)。
假设你有:
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 ;
} ;
}
} ;
当我们简单地把它全部变成小写时,为什么我们要做得那么复杂:
var your_object = {
"chickago" : 'hi' ,
"detroit" : 'word',
"atlanta" : 'get r dun',
GetName: function (status) {
return this[status].name;
} };
称之为: your_object.GetName(your_var.toLowerCase());
另一种简单的方法:
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"
这是一个很好的递归函数,它允许您以不区分大小写的方式遍历 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]
这会将所有内容都转换为小写,但如果您不关心保留大小写,这可能会有所帮助。
var somedata = {
"MixEdCase": 1234
}
var temp = JSON.parse(JSON.stringify(somedata).toLowerCase());
console.log(temp.mixedcase);
// or
console.log(temp["mixedcase"]);