Получите доступ к свойствам JavaScript без учета регистра?
Спасибо, что посмотрели.
Предположим, у меня есть объект:
var obj = {
foo:"bar",
fizz:"buzz"
};
Мне нужно получить доступ к свойству этого объекта динамически следующим образом:
var objSetter = function(prop,val){
obj[prop] = val;
}
Там нет проблем, кроме того, что prop
должен быть нечувствительным к регистру, если имя свойства передается в функцию как, скажем, Foo
вместо Foo
.
Итак, как я могу указать свойство объекта по имени без учета случая? Я хотел бы избежать итерации всего объекта, если это возможно.
Спасибо!
Ответы
Ответ 1
Сравните все свойства 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;
}
}
}
Ответ 2
Вы можете сделать это, чтобы "нормализовать" prop
var normalizedProp = prop.toLowerCase();
obj[normalizedProp] = val;
Ответ 3
Для этого я предпочитаю использовать прототип над автономной функцией только для удобства использования и выразительности. Мне просто не нравится вставлять объекты в функции, если мне это не нужно.
Кроме того, в то время как принятый ответ работает, я хотел получить более полное решение как для получения, так и для установки, которое будет вести себя так же, как обозначение нативной точки или обозначение скобки, насколько это возможно.
С учетом этого, я создал пару прототипов функций для установки/получения свойства объекта без учета случая. При добавлении в прототип объекта вы должны помнить, что ОЧЕНЬ. Особенно при использовании JQuery и других библиотек. Object.defineProperty() с перечислимым набором в false использовался специально, чтобы избежать конфликта с 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'
Ответ 4
Еще одна вариация на уже представленные, которая толкает итерацию вниз в функцию 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
Ответ 5
зачем нам это делать, что сложно, когда мы просто можем сделать все в нижнем регистре:
var your_object = {
"chickago" : 'hi' ,
"detroit" : 'word',
"atlanta" : 'get r dun',
GetName: function (status) {
return this[status].name;
} };
, чтобы называть его: your_object.GetName(your_var.toLowerCase());
Ответ 6
Нет никакой итерации. Поскольку 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;
}
Ответ 7
Вот очень простой код для этого
Предполагая, что данные представляют собой массив объектов типа
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"}]
Ответ 8
Вам может потребоваться выполнить нечувствительность к регистру (обычно дорогостоящую из-за итерации объекта), если совпадение с учетом регистра (дешевое и быстрое) терпит неудачу.
Скажите, что у вас есть:
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 ;
} ;
}
} ;
Ответ 9
Попробуйте следующее:
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(), если вам нужна более старая поддержка.