Program Tip

대소 문자를 구분하지 않고 JavaScript 속성에 액세스 하시겠습니까?

programtip 2021. 1. 8. 22:14
반응형

대소 문자를 구분하지 않고 JavaScript 속성에 액세스 하시겠습니까?


객체가 있다고 가정합니다.

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

다음과 같이 해당 개체의 속성에 동적으로 액세스해야합니다.

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

prop속성 이름이 . Foo대신 함수에 전달되는 경우 대소 문자를 구분하지 않아야 한다는 점을 제외하고는 문제가 없습니다 foo.

그렇다면 대소 문자에 관계없이 이름으로 객체의 속성을 어떻게 가리킬 수 있습니까? 가능하면 전체 개체를 반복하지 않으려 고합니다.


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

이 시도:

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

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

또는 이미 소문자로 searchKey를 제공 할 수 있습니다.

함수로 원하는 경우 :

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

객체를 찾을 수 없으면 정상처럼 undefined를 반환합니다.

이전 브라우저를 지원해야하는 경우 다음을 filter대신 사용할 수 있습니다 .

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

더 오래된 지원이 필요한 경우 Object.keys ()Array.filter ()에 polyfill을 사용하는 것이 좋습니다 .


이를 위해 사용 편의성과 표현력을 위해 독립형 기능보다 프로토 타입을 사용하는 것을 선호합니다. 나는 할 필요가 없다면 객체를 함수로 퍼널 링하는 것을 좋아하지 않습니다.

또한 받아 들여지는 답변이 작동하는 동안 가능한 한 기본 점 표기법 또는 대괄호 표기법처럼 작동하는 가져 오기 및 설정을위한보다 포괄적 인 솔루션을 원했습니다.

이를 염두에두고 대소 문자에 관계없이 객체 속성을 설정 / 가져 오기위한 몇 가지 프로토 타입 함수를 만들었습니다. 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'

반복을 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];
};

예를 들면 :

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;

단순히 모두 소문자로 만들 수 있는데 왜 그렇게 복잡할까요?

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

그것을 부르기 위해 : your_object.GetName(your_var.toLowerCase());


문자열 키를 대문자 또는 소문자로 변환하고 일반 객체처럼 동작하는 트랩이있는 Proxy의 좋은 후보처럼 보입니다. 이는 점 또는 브라켓 표기법과 함께 작동합니다.

다음은 코드입니다.

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


반복 할 필요가 없습니다. 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;
}

Heres a very simple code to do this Assuming that data is the array of objects like

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;
}, [])

Output will be

data=[{"a":"bc","b":"nn"}]

You might only need to do case-insensitive matching (usually expensive because of object iteration) IF a case-sensitive match (cheap and quick) fails.

Say you have:

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

And you have, for whatever reason, 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 ;
          } ;
      } 
  } ;

Another simple way:

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

Use it like this:

var obj = {
  foo:"bar",
  fizz:"buzz"
};
    getVal(obj,"FoO") -> returns "bar"

ReferenceURL : https://stackoverflow.com/questions/12484386/access-javascript-property-case-insensitively

반응형