Можно ли добавить динамически именованные свойства в объект JavaScript?
В JavaScript я создал объект примерно так:
var data = {
'PropertyA': 1,
'PropertyB': 2,
'PropertyC': 3
};
Можно ли добавить дополнительные свойства к этому объекту после его первоначального создания, если имя свойства не определено до времени выполнения? т.е.
var propName = 'Property' + someUserInput
//imagine someUserInput was 'Z', how can I now add a 'PropertyZ' property to
//my object?
22 ответа
Да.
var data = {
'PropertyA': 1,
'PropertyB': 2,
'PropertyC': 3
};
data["PropertyD"] = 4;
// dialog box with 4 in it
alert(data.PropertyD);
alert(data["PropertyD"]);
ES6 для победы!
const b = 'b';
const c = 'c';
const data = {
a: true,
[b]: true, // dynamic property
[`interpolated-${c}`]: true, // dynamic property + interpolation
[`${b}-${c}`]: true
}
Если вы войдете data
Вы получаете это:
{
a: true,
b: true,
interpolated-c: true,
b-c: true
}
Это использует новый синтаксис вычисляемого свойства и литералы шаблона.
Да, это возможно. Предполагая, что:
var data = {
'PropertyA': 1,
'PropertyB': 2,
'PropertyC': 3
};
var propertyName = "someProperty";
var propertyValue = "someValue";
Или:
data[propertyName] = propertyValue;
или же
eval("data." + propertyName + " = '" + propertyValue + "'");
Первый метод является предпочтительным. eval() имеет очевидные проблемы безопасности, если вы используете значения, предоставленные пользователем, поэтому не используйте его, если вы можете избежать этого, но стоит знать, что он существует и что он может делать.
Вы можете ссылаться на это с:
alert(data.someProperty);
или же
data(data["someProperty"]);
или же
alert(data[propertyName]);
ES6 вводит вычисляемые имена свойств, которые позволяют вам делать
let a = 'key'
let myObj = {[a]: 10};
// output will be {key:10}
Я знаю, что на вопрос ответили отлично, но я также нашел другой способ добавить новые свойства и хотел поделиться им с вами:
Вы можете использовать функцию Object.defineProperty()
Найдено в сети разработчиков Mozilla
Пример:
var o = {}; // Creates a new object
// Example of an object property added with defineProperty with a data property descriptor
Object.defineProperty(o, "a", {value : 37,
writable : true,
enumerable : true,
configurable : true});
// 'a' property exists in the o object and its value is 37
// Example of an object property added with defineProperty with an accessor property descriptor
var bValue;
Object.defineProperty(o, "b", {get : function(){ return bValue; },
set : function(newValue){ bValue = newValue; },
enumerable : true,
configurable : true});
o.b = 38;
// 'b' property exists in the o object and its value is 38
// The value of o.b is now always identical to bValue, unless o.b is redefined
// You cannot try to mix both :
Object.defineProperty(o, "conflict", { value: 0x9f91102,
get: function() { return 0xdeadbeef; } });
// throws a TypeError: value appears only in data descriptors, get appears only in accessor descriptors
Здесь, используя вашу запись:
var data = {
'PropertyA': 1,
'PropertyB': 2,
'PropertyC': 3
};
var propName = 'Property' + someUserInput
//imagine someUserInput was 'Z', how can I now add a 'PropertyZ' property to
//my object?
data[propName] = 'Some New Property value'
Вы можете добавить столько свойств, сколько захотите, просто используя точечную запись:
var data = {
var1:'somevalue'
}
data.newAttribute = 'newvalue'
или:
data[newattribute] = somevalue
для динамических клавиш.
В дополнение ко всем предыдущим ответам, и в случае, если вам интересно, как мы будем писать динамические имена свойств в будущем с использованием вычисляемых имен свойств ( ECMAScript 6), вот как:
var person = "John Doe";
var personId = "person_" + new Date().getTime();
var personIndex = {
[ personId ]: person
// ^ computed property name
};
personIndex[ personId ]; // "John Doe"
Просто дополнение к ответу Abeing выше. Вы можете определить функцию для инкапсуляции сложности defineProperty, как указано ниже.
var defineProp = function ( obj, key, value ){
var config = {
value: value,
writable: true,
enumerable: true,
configurable: true
};
Object.defineProperty( obj, key, config );
};
//Call the method to add properties to any object
defineProp( data, "PropertyA", 1 );
defineProp( data, "PropertyB", 2 );
defineProp( data, "PropertyC", 3 );
ссылка: http://addyosmani.com/resources/essentialjsdesignpatterns/book/
Вы можете добавлять свойства динамически, используя некоторые параметры ниже:
В вашем примере:
var data = {
'PropertyA': 1,
'PropertyB': 2,
'PropertyC': 3
};
Вы можете определить свойство с динамическим значением следующими двумя способами:
data.key = value;
или же
data['key'] = value;
Более того, если ваш ключ также динамический, вы можете определить его с помощью класса Object с помощью:
Object.defineProperty(data, key, withValue(value));
где data - ваш объект, key - это переменная для хранения имени ключа, а value - это переменная для хранения значения.
Надеюсь, это поможет!
Это может быть полезно, если во время выполнения добавлено новое смешанное свойство:
data = { ...data, newPropery: value}
Однако оператор распространения использует неглубокую копию, но здесь мы назначаем данные себе, поэтому ничего не потеряем
Я знаю, что на этот пост уже есть несколько ответов, но я не видел ни одного, в котором есть несколько свойств, и они находятся в массиве. И это решение, кстати, для ES6.
Для иллюстрации, скажем, у нас есть массив с именем person с объектами внутри:
let Person = [{id:1, Name: "John"}, {id:2, Name: "Susan"}, {id:3, Name: "Jet"}]
Таким образом, вы можете добавить свойство с соответствующим значением. Допустим, мы хотим добавить язык со значением по умолчанию EN.
Person.map((obj)=>({...obj,['Language']:"EN"}))
Массив Person теперь будет выглядеть так:
Person = [{id:1, Name: "John", Language:"EN"},
{id:2, Name: "Susan", Language:"EN"}, {id:3, Name: "Jet", Language:"EN"}]
Я искал решение, в котором я мог бы использовать динамические имена ключей внутри объявления объекта (без использования таких функций ES6, как ...
или [key]: value
)
Вот что я придумал:
var obj = (obj = {}, obj[field] = 123, obj)
Сначала это кажется немного сложным, но на самом деле все просто. Мы используем оператор Comma для запуска трех команд подряд:
obj = {}
: создает новый объект и присваивает его переменнойobj
obj[field] = 123
: добавляет вычисленное имя свойства кobj
obj
: использоватьobj
переменная как результат списка скобок / запятых
Этот синтаксис можно использовать внутри параметра функции без необходимости явно объявлять obj
переменная:
// The test function to see the result.
function showObject(obj) {
console.log(obj);
}
// My dynamic field name.
var field = "myDynamicField";
// Call the function with our dynamic object.
showObject( (obj = {}, obj[field] = 123, obj) );
/*
Output:
{
"myDynamicField": true
}
*/
Некоторые вариации
Временное решение в "строгом режиме":
Приведенный выше код не работает в strict mode
потому что переменная obj не объявлена.
// This gives the same result, but declares the global variable `this.obj`!
showObject( (this.obj = {}, obj[field] = 123, obj) );
Код ES2015 с использованием вычисленных имен свойств в инициализаторе:
// Works in most browsers, same result as the other functions.
showObject( {[field] = 123} );
Это решение работает во всех современных браузерах (но не в IE, если мне нужно это упомянуть)
Супер хакерский способ использования JSON.parse()
:
// Create a JSON string that is parsed instantly. Not recommended in most cases.
showObject( JSON.parse( '{"' + field +'":123}') );
// read: showObject( JSON.parse( '{"myDynamicfield":123}') );
Позволяет использовать специальные символы в клавишах
Обратите внимание, что вы также можете использовать пробелы и другие специальные символы в именах вычисляемых свойств (а также в JSON.parse).
var field = 'my dynamic field :)';
showObject( {[field] = 123} );
// result: { "my dynamic field :)": 123 }
К этим полям нельзя получить доступ через точку (obj.my dynamic field :)
очевидно синтаксически неверен), но только через скобки, т. е. obj['my dynamic field :)']
возвращается 123
Самый простой и самый портативный способ.
var varFieldName = "good";
var ob = {};
Object.defineProperty(ob, varFieldName , { value: "Fresh Value" });
На основании ответа #abeing!
Будьте осторожны при добавлении свойства к существующему объекту с помощью метода .(Точка).
(.dot) метод добавления свойства к объекту следует использовать, только если вы заранее знаете "ключ", в противном случае используйте метод [скобки].
Пример:
var data = {
'Property1': 1
};
// Two methods of adding a new property [ key (Property4), value (4) ] to the
// existing object (data)
data['Property2'] = 2; // bracket method
data.Property3 = 3; // dot method
console.log(data); // { Property1: 1, Property2: 2, Property3: 3 }
// But if 'key' of a property is unknown and will be found / calculated
// dynamically then use only [bracket] method not a dot method
var key;
for(var i = 4; i < 6; ++i) {
key = 'Property' + i; // Key - dynamically calculated
data[key] = i; // CORRECT !!!!
}
console.log(data);
// { Property1: 1, Property2: 2, Property3: 3, Property4: 4, Property5: 5 }
for(var i = 6; i < 2000; ++i) {
key = 'Property' + i; // Key - dynamically calculated
data.key = i; // WRONG !!!!!
}
console.log(data);
// { Property1: 1, Property2: 2, Property3: 3,
// Property4: 4, Property5: 5, key: 1999 }
Обратите внимание на проблему в конце журнала консоли: "ключ: 1999" вместо свойства 6: 6, свойства 7: 7,........., свойство 1999: 1999. Поэтому лучшим способом добавления динамически создаваемого свойства является метод [скобка].
Хороший способ доступа к динамическим именам строк, которые содержат объекты (например, object.subobject.property)
function ReadValue(varname)
{
var v=varname.split(".");
var o=window;
if(!v.length)
return undefined;
for(var i=0;i<v.length-1;i++)
o=o[v[i]];
return o[v[v.length-1]];
}
function AssignValue(varname,value)
{
var v=varname.split(".");
var o=window;
if(!v.length)
return;
for(var i=0;i<v.length-1;i++)
o=o[v[i]];
o[v[v.length-1]]=value;
}
Пример:
ReadValue("object.subobject.property");
WriteValue("object.subobject.property",5);
eval работает для чтения значения, но записать значение немного сложнее.
Более продвинутая версия (создайте подклассы, если они не существуют, и разрешите объекты вместо глобальных переменных)
function ReadValue(varname,o=window)
{
if(typeof(varname)==="undefined" || typeof(o)==="undefined" || o===null)
return undefined;
var v=varname.split(".");
if(!v.length)
return undefined;
for(var i=0;i<v.length-1;i++)
{
if(o[v[i]]===null || typeof(o[v[i]])==="undefined")
o[v[i]]={};
o=o[v[i]];
}
if(typeof(o[v[v.length-1]])==="undefined")
return undefined;
else
return o[v[v.length-1]];
}
function AssignValue(varname,value,o=window)
{
if(typeof(varname)==="undefined" || typeof(o)==="undefined" || o===null)
return;
var v=varname.split(".");
if(!v.length)
return;
for(var i=0;i<v.length-1;i++)
{
if(o[v[i]]===null || typeof(o[v[i]])==="undefined")
o[v[i]]={};
o=o[v[i]];
}
o[v[v.length-1]]=value;
}
Пример:
ReadValue("object.subobject.property",o);
WriteValue("object.subobject.property",5,o);
Это то же самое, что o.object.subobject.property
Вы могли бы сделать что-то вроде этого
let myObj = {
propertyA: 1,
propertyB: 2,
propertyC: 3,
}
// Declaring val here, could get from the user
let val = 'D';
myObj = {...myObj, [`property${val}`]: 4}
Вот как я решил проблему.
var obj = {
};
var field = "someouter.someinner.someValue";
var value = 123;
function _addField( obj, field, value )
{
// split the field into tokens
var tokens = field.split( '.' );
// if there's more than one token, this field is an object
if( tokens.length > 1 )
{
var subObj = tokens[0];
// define the object
if( obj[ subObj ] !== undefined ) obj[ subObj ] = {};
// call addfield again on the embedded object
var firstDot = field.indexOf( '.' );
_addField( obj[ subObj ], field.substr( firstDot + 1 ), value );
}
else
{
// no embedded objects, just field assignment
obj[ field ] = value;
}
}
_addField( obj, field, value );
_addField(obj, 'simpleString', 'string');
console.log( JSON.stringify( obj, null, 2 ) );
Создает следующий объект:
{
"someouter": {
"someinner": {
"someValue": 123
}
},
"simpleString": "string"
}
Да, это возможно. Я добился использования нижеприведенной реализации. для этого я получаю в ответ массив, который я хочу в объекте в виде списка атрибутов.
response = {
"equityMonths": [
{
"id": 1,
"month": "JANUARY",
"isEligible": false
},
{
"id": 2,
"month": "FEBRUARY",
"isEligible": true
},
{
"id": 3,
"month": "MARCH",
"isEligible": false
},
{
"id": 4,
"month": "APRIL",
"isEligible": true
},
{
"id": 5,
"month": "MAY",
"isEligible": false
},
{
"id": 6,
"month": "JUNE",
"isEligible": true
},
{
"id": 7,
"month": "JULY",
"isEligible": true
},
{
"id": 8,
"month": "AUGUST",
"isEligible": false
},
{
"id": 9,
"month": "SEPTEMBER",
"isEligible": true
},
{
"id": 10,
"month": "OCTOBER",
"isEligible": false
},
{
"id": 11,
"month": "NOVEMBER",
"isEligible": true
},
{
"id": 12,
"month": "DECEMBER",
"isEligible": false
}
]
}
здесь я хочу
equityMonths
как объект и с января по декабрь это ключ и
isEligible
как ценность. для этого мы должны использовать объект класса
defineProperty()
метод, позволяющий добавлять в объекты динамическое свойство.
код для динамического добавления свойства к объекту.
let equityMonth = new Object();
response.equityMonths.forEach(element => {
Object.defineProperty(equityMonth, element['month'], {
value: element['isEligible'],
writable: true,
enumerable: true,
configurable: true
});
});
console.log("DATA : " + JSON.stringify(equityMonth));
в приведенном выше коде у нас есть массив
equityMonths
который мы преобразовали как свойство в объект.
вывод:
DATA : {"JANUARY":false,"FEBRUARY":true,"MARCH":false,"APRIL":true,"MAY":false,"JUNE":true,"JULY":true,"AUGUST":false,"SEPTEMBER":true,"OCTOBER":false,"NOVEMBER":true,"DECEMBER":false}
Самый простой способ динамического добавления данных в объект js.
// Create an object
const data = {};
// Add properties to it with a key and value
data['key'] = value;
Идеальный простой способ
var data = {
'PropertyA': 1,
'PropertyB': 2,
'PropertyC': 3
};
var newProperty = 'getThisFromUser';
data[newProperty] = 4;
console.log(data);
Если вы хотите применить его к массиву данных (версия ES6/TS)
const data = [
{ 'PropertyA': 1, 'PropertyB': 2, 'PropertyC': 3 },
{ 'PropertyA': 11, 'PropertyB': 22, 'PropertyC': 33 }
];
const newProperty = 'getThisFromUser';
data.map( (d) => d[newProperty] = 4 );
console.log(data);
Определенно. Думайте об этом как словарь или ассоциативный массив. Вы можете добавить к нему в любой момент.