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.