JavaScript 객체에 동적으로 명명 된 속성을 추가 할 수 있습니까?


745

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?

답변:


1211

예.

var data = {
    'PropertyA': 1,
    'PropertyB': 2,
    'PropertyC': 3
};

data["PropertyD"] = 4;

// dialog box with 4 in it
alert(data.PropertyD);
alert(data["PropertyD"]);


142
@thedz : data.PropertyD는 동적이지 않은 속성 이름을 알아야합니다.
Georg Schölly

6
+1 도움이 되었기 때문에 +1. 그러나 왜 객체 속성이 배열처럼 처리되는지 이해하지 못합니다.
Ron van der Heijden

9
@Bondye : 그것은 자바 스크립트의 이상한 디자인의 일부입니다. 이 경우 object["property"]와 정확히 동일 array[4]하지 않으며 전자는 실제 배열로 생성되지 않았습니다.
Georg Schölly

5
195 upvotes를 얻는 동안 나만이 게시물이 질문에 대답하지 않습니까? JavaScript 코드에서 생성 될 때까지 이름을 알 수없는 속성을 정의하는 방법을 묻는 것이라고 생각했습니다.
콴타스 94 헤비

20
@ Qantas : 직접 응답하지 않는다고 가정 해 봅시다. 그러나에서가는 data["PropertyD"]것은 data[function_to_get_property_name()]사소한 것 같다.
Georg Schölly

154

승리를위한 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
}

새로운 계산 속성 구문과 템플릿 리터럴을 사용 합니다.


1
이것은 코드가 완벽하게 작동하기를 원했던 경우에 필요한 것입니다 (예 : obj[propname]. 대신, 이것을 객체 스프레드 구문과 함께 사용할 수있었습니다.
intcreator

2
이 코드 스 니펫이 새로운 구문을 보거나 이해하지 못하는 사람에게 무엇을하고 있는지는 분명하지 않습니다. 'a'const를 사용하여 출력 / 예상 속성을 표시하도록 편집을 제안합니다.

개인적으로 저는 ES5 방식이 훨씬 깨끗하고 이해하기 쉽다고 생각합니다.var a = {}; a["dynamic-" + prop] = true;
Jack Giffin

1
@JackGiffin 어떤 경우에는 그렇습니다. 그러나 불변 구조로 작업 할 때이 구문은 매우 유용 할 수 있습니다 a. (특히 redux와 같은 패키지를 사용할 때)
Mauricio Soares

3
이것은 대단하다 {... state, [prop] : val}
Xipo

87

네 가능합니다. 가정 :

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

40
평가 사용은 정말 위험합니다.
게오르그 Schölly

10
천천히 말할 것도 없습니다.
Eamon Nerbonne

@ GeorgSchölly 사실입니다.
Obinna Nwakwue

1
참고 (누군가가했던 것과 같은 문제가 발생하는 경우) : 일반 객체의 경우 정상적으로 작동합니다. 그러나 항목 목록을 추적하려면 jQuery UI 객체에 속성을 추가해야했습니다. 이 경우 jQuery는 항상 사본을 작성하므로이 방법으로 추가하면 특성이 손실됩니다. 여기서는 jQuery.extend () 를 사용해야 합니다.
Matt

나는 이전 의견에 추가하고 싶습니다. 제 경우에는 효과가 없었습니다. 그래서 $("#mySelector").data("propertyname", myvalue);to를 사용하여 설정 var myValue=$("#mySelector").data("propertyname");하고 값을 다시 얻었습니다. 복잡한 객체 (목록, 배열 ...) 조차도이 방법으로 추가 할 수 있습니다.
Matt

61

질문에 완벽하게 답변했지만 새로운 속성을 추가하는 다른 방법을 찾아서 공유하고 싶었습니다.

당신은 기능을 사용할 수 있습니다 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

4
이 방법의 장단점?
Trevor

6
@Trevor : 게터와 세터를 추가 할 수있는 전체 구성 기능과 기능; 또한 defineProperties(복수)로 여러 속성을 한 번에 추가 할 수 있습니다 .
rvighne

@Thielicious Object.defineProperty는 쉬운 편의 도구가 아니라 세밀한 제어 기능을 갖춘 도구입니다. 추가 제어가 필요하지 않은 경우 선택하기에 적합한 도구가 아닙니다.
kleinfreund

Object.defineProperty(obj, prop, valueDescriptor)V8이 단순히 수행하는 것보다 최적화하는 것이 훨씬 느리고 어렵습니다 obj[prop] = value.
Jack Giffin

27

ES6는 계산 된 속성 이름을 소개합니다.

let a = 'key'
let myObj = {[a]: 10};
// output will be {key:10}

23

여기에 표기법을 사용하십시오.

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'

18

점 표기법을 사용하여 원하는만큼 더 많은 속성을 추가 할 수 있습니다.

var data = {
    var1:'somevalue'
}
data.newAttribute = 'newvalue'

또는 :

data[newattribute] = somevalue

동적 키용.


4
속성 이름이 런타임까지 결정되지 않으면 "-따라서 eval을 사용하지 않으면 작동하지 않습니다. 이는 좋은 옵션이 아닙니다.
Marc Gravell

1
또는 [] 구 ... 데이터 [의 somevar]를 사용 = someValue와
가브리엘 할리

17

이전의 모든 답변 외에도 컴퓨팅 속성 이름 (ECMAScript 6)을 사용 하여 미래 에 동적 속성 이름을 작성하는 방법을 궁금해하는 경우 다음 과 같이하십시오.

var person = "John Doe";
var personId = "person_" + new Date().getTime();
var personIndex = {
    [ personId ]: person
//  ^ computed property name
};

personIndex[ personId ]; // "John Doe"

참조 : ECMAScript 6 이해-Nickolas Zakas


11

위의 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/#constructorpatternjavascript


9

아래 옵션 중 일부를 사용하여 속성을 동적으로 추가 할 수 있습니다.

당신의 예에서 :

var data = {
    'PropertyA': 1,
    'PropertyB': 2,
    'PropertyC': 3
};

다음 두 가지 방법으로 동적 값으로 특성을 정의 할 수 있습니다.

data.key = value;

또는

data['key'] = value;

키가 동적 인 경우 Object 클래스를 사용하여 다음을 정의 할 수 있습니다.

Object.defineProperty(data, key, withValue(value));

여기서 data 는 객체이고 key 는 키 이름 을 저장하는 변수 이고 value 을 저장하는 변수입니다.

이게 도움이 되길 바란다!


8

이 게시물에 대한 답변이 이미 여러 개 있다는 것을 알고 있지만 여러 속성이 있고 배열 내에있는 것을 보지 못했습니다. 그리고이 솔루션은 ES6를위한 것입니다.

예를 들어 객체가 포함 된 person이라는 배열이 있다고 가정 해 보겠습니다.

 let Person = [{id:1, Name: "John"}, {id:2, Name: "Susan"}, {id:3, Name: "Jet"}]

따라서 해당 값으로 속성을 추가 할 수 있습니다. 기본값이 EN 인 언어 를 추가한다고 가정 해 봅시다 .

Person.map((obj)=>({...obj,['Language']:"EN"}))

사람의 배열은 지금과 같이 될 것입니다 :

Person = [{id:1, Name: "John", Language:"EN"}, 
{id:2, Name: "Susan", Language:"EN"}, {id:3, Name: "Jet", Language:"EN"}]

실제로 객체에 속성을 추가하는 것이 아니라 기존 객체의 속성 (확산 연산자를 통해)과 새 소품을 사용하여 새 객체를 만드는 것입니다.
Ed Orsi

3
당신이 그랬어 야한다고 옳습니다 Person = Person.map(code here). 그러나 요점은을 사용하여 기존 객체에 속성을 쉽게 추가 할 수 있다는 것입니다 ES6.
Edper

5

가장 간단하고 휴대하기 쉬운 방법입니다.

var varFieldName = "good";
var ob = {};
Object.defineProperty(ob, varFieldName , { value: "Fresh Value" });

#abeing 답변을 기반으로!


3

. (dot) 메서드를 사용하여 기존 객체에 속성을 추가 할 때 주의하십시오 .

객체에 속성을 추가하는 (.dot) 메서드는 미리 'key'알고 있는 경우에만 사용해야하며, 그렇지 않으면 [bracket] 메서드를 사용하십시오 .

예:

   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 }

콘솔 로그 끝의 문제 -Property6 : 6, Property7 : 7, ........., Property1999 : 1999 대신 'key : 1999'에 주목하십시오 . 따라서 동적으로 생성 된 속성을 추가하는 가장 좋은 방법은 [브래킷] 방법입니다.


1

객체가 포함 된 동적 문자열 이름 (예 : 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와 동일합니다.


1
정확히 내가 찾던 것은 this.setState ({dynamic property : value}) 반응에 유용합니다. 감사합니다!
Kevin Danikowski

0

다음은 문제를 해결 한 방법입니다.

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

0

런타임에 혼합 된 새 속성을 추가하는 경우 유용 할 수 있습니다.

data = { ...data, newPropery: value}

그러나 스프레드 연산자는 얕은 복사를 사용하지만 여기서는 데이터를 자체에 할당하므로 아무것도 잃지 않아야합니다.


-2

완벽한 쉬운 방법

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

-14

명확히. 그것을 사전 또는 연관 배열로 생각하십시오. 언제든지 추가 할 수 있습니다.


1
도움이되지 않는다고 말하는 것입니다.
Obinna Nwakwue
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.