Supposons que j'ai un objet:
var obj = {
foo:"bar",
fizz:"buzz"
};
J'ai besoin d'accéder à une propriété de cet objet de façon dynamique comme ceci:
var objSetter = function(prop,val){
obj[prop] = val;
}
Aucun problème, sauf que prop
doit être insensible à la casse si le nom de la propriété est transmis à la fonction sous la forme, par exemple, Foo
au lieu de foo
.
Alors, comment puis-je désigner la propriété d'un objet par son nom sans tenir compte de la casse? Je voudrais éviter d'itérer l'objet entier si possible.
Comparez toutes les propriétés de obj avec 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;
}
}
}
Pour cela, je préfère utiliser le prototype plutôt qu'une fonction autonome pour la facilité d'utilisation et l'expression. Je n'aime simplement pas canaliser des objets dans des fonctions si ce n'est pas nécessaire.
De plus, alors que la réponse acceptée fonctionnait, je recherchais une solution plus complète pour obtenir et définir les paramètres, qui se comporterait autant que possible comme la notation en points native ou la notation en crochet.
Dans cet esprit, j'ai créé quelques fonctions prototypes pour définir/obtenir une propriété d'objet sans tenir compte de la casse. Vous devez vous rappeler d’êtreVERY/ responsable lors de l’ajout au prototype d’objet. Surtout lors de l'utilisation de JQuery et d'autres bibliothèques. Object.defineProperty () avec enumerable défini sur false a été utilisé spécifiquement pour éviter les conflits avec JQuery. Je n'ai pas non plus pris la peine de nommer les fonctions, quoi que ce soit qui indique qu'elles sont insensibles à la casse, mais vous pourriez le faire. J'aime les noms plus courts.
Voici le getter:
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
});
Voici le passeur:
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
});
Maintenant que nous avons créé ces fonctions, notre code est extrêmement propre et concis et fonctionne parfaitement.
Sensible à la casse:
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'
Paramètre insensible à la casse:
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'
Essaye ça:
var myObject = { "mIxeDCaSEKeY": "value" };
var searchKey = 'mixedCaseKey';
myObject[Object.keys(myObject).find(key => key.toLowerCase() === searchKey.toLowerCase())];
Vous pouvez également déjà fournir le searchKey en minuscule.
Si vous le souhaitez comme fonction:
/**
* @param {Object} object
* @param {string} key
* @return {any} value
*/
function getParameterCaseInsensitive(object, key) {
return object[Object.keys(object)
.find(k => k.toLowerCase() === key.toLowerCase())
];
}
Si l'objet ne peut pas être trouvé, il retournera undefined, comme d'habitude.
Si vous devez prendre en charge les anciens navigateurs, vous pouvez utiliser plutôt filter
:
function getParameterCaseInsensitive(object, key) {
return object[Object.keys(object).filter(function(k) {
return k.toLowerCase() === key.toLowerCase();
})[0]];
}
Je suggère d'utiliser les polyfills pour Object.keys () et Array.filter () si vous avez besoin d'un support encore plus ancien.
Encore une autre variante de celles déjà présentées qui repousse l’itération dans la fonction Underscore/Lodash findKey
:
var _ = require('underscore');
var getProp = function (obj, name) {
var realName = _.findKey(obj, function (value, key) {
return key.toLowerCase() === name.toLowerCase();
});
return obj[realName];
};
Par exemple:
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
Vous pouvez le faire pour "normaliser" prop
var normalizedProp = prop.toLowerCase();
obj[normalizedProp] = val;
pourquoi devrions-nous faire cela aussi compliqué quand nous pouvons simplement le faire en minuscule
var your_object = {
"chickago" : 'hi' ,
"detroit" : 'Word',
"atlanta" : 'get r dun',
GetName: function (status) {
return this[status].name;
} };
pour l'appeler: your_object.GetName(your_var.toLowerCase());
Il n'y a pas besoin d'itération. Étant donné que prop
n'est peut-être pas une chaîne, vous devez le forcer en premier à une chaîne, le cas échéant, car c'est ce que les objets font de manière native. Une simple fonction getter est:
function objGetter(prop) {
return obj[String(prop).toLowerCase()];
}
S'il est impératif de restreindre l'accès à ses propres propriétés:
function objGetter(prop) {
prop = String(prop).toLowerCase();
if (obj.hasOwnProperty(prop)) {
return obj.prop;
}
}
et un passeur:
function objSetter(prop, val) {
obj[String(prop).toLowerCase()] = val;
}
Voici un code très simple pour faire cela En supposant que ces données sont un tableau d'objets comme
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;
}, [])
La sortie sera
data=[{"a":"bc","b":"nn"}]
Un autre moyen simple:
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;
}
Utilisez-le comme ceci:
var obj = {
foo:"bar",
fizz:"buzz"
};
getVal(obj,"FoO") -> returns "bar"
Vous devrez peut-être uniquement faire une correspondance sensible à la casse (généralement coûteuse en raison de l'itération de l'objet) SI une correspondance sensible à la casse (économique et rapide) échoue.
Disons que vous avez:
var your_object = { "Chicago" : 'hi' , "deTroiT" : 'Word' , "atlanta" : 'get r dun' } ;
Et vous avez, pour une raison quelconque, la_ valeur, 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 ;
} ;
}
} ;
Cela me semble être un bon candidat pour Proxy avec des pièges pour convertir les clés de chaîne en majuscules ou en minuscules et se comporter comme un objet normal . Cela fonctionne avec l'une ou l'autre notation: points ou points.
Voici le code:
'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"]