web-dev-qa-db-fra.com

Accéder à la propriété JavaScript sans tenir compte de la casse?

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.

48
Matt Cashatt

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;
      }
   }
}
23
Anoop

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'
10
Matt Goodwin

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.

7
ShortFuse

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
6
Rusty Shackleford

Vous pouvez le faire pour "normaliser" prop

 var normalizedProp = prop.toLowerCase();
 obj[normalizedProp] = val;
3
Claudio Redi

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());

1
user2390480

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;
}
0
RobG

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"}]
0
prajnavantha

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"
0
JerryGoyal

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 ;
          } ;
      } 
  } ;
0
dsdsdsdsd

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"]

0
Enrique Alamo