動的に名前が付けられたプロパティを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はプロパティ名を知る必要がありますが、動的ではありません。
GeorgSchölly2009

6
これは私を助けたので、+ 1。しかし、オブジェクトのプロパティが配列のように処理される理由がわかりません。
Ron van der Heijden 2013年

9
@Bondye:それはjavascriptの奇妙なデザインの一部です。この場合object["property"]はとまったく同じではありませんarray[4]。前者は真の配列として作成されていません。
GeorgSchölly2013年

5
それは私だけですか、この投稿は195の賛成票を得ているときに質問に答えませんか?JavaScriptコードで生成されるまで、名前が不明なプロパティを定義する方法を尋ねていると思いました。
カンタス94ヘビー

20
@カンタス航空:直接回答しないとしましょう。しかし、からdata["PropertyD"]への移行data[function_to_get_property_name()]は簡単なようです。
GeorgSchölly2014

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 '10

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
evalの使用は本当に危険です。
GeorgSchölly2009

10
遅いことは言うまでもありません。
イーモンネルボンヌ2009

@GeorgSchölly真。
Obinna Nwakwue

1
(誰かが私と同じ問題に遭遇した場合):通常のオブジェクトの場合、これは正常に機能します。しかし、アイテムのリストを追跡するために、jQuery UIオブジェクトにいくつかのプロパティを追加する必要がありました。その場合、jQueryは常にコピーを作成するため、この方法で追加するとプロパティは失われます。ここではjQuery.extend()を使用する必要があります。
マット

以前のコメントに追加したいのですが、私の場合はうまくいきませんでした。そのため、私はを使用し$("#mySelector").data("propertyname", myvalue);て設定し、var myValue=$("#mySelector").data("propertyname");値を取得することにしました。複雑なオブジェクト(リスト、配列など)でも、この方法で追加できます。
マット

61

質問は完全に回答されていることは知っていますが、新しいプロパティを追加する別の方法も見つけて、あなたと共有したいと思いました。

あなたは関数を使うことができます Object.defineProperty()

Mozilla Developer Networkで見つかりました

例:

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 2014

@Thielicious Object.definePropertyは、簡単な便利ツールではなく、きめ細かい制御が可能なツールです。追加のコントロールが必要ない場合は、適切なツールではありません。
kleinfreund 2017

Object.defineProperty(obj, prop, valueDescriptor)V8の最適化は、単純に行うよりもはるかに遅く、困難ですobj[prop] = value
ジャックギ

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

1
または[]構文を使用します... data [somevar] = somevalue
Gabriel Hurley

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

次の2つの方法で、動的な値を持つプロパティを定義できます。

data.key = value;

または

data['key'] = value;

さらに、キーが動的である場合は、Objectクラスを使用して以下を定義できます。

Object.defineProperty(data, key, withValue(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"}]

実際にオブジェクトにプロパティを追加するのではなく、(spread演算子を介して)古いオブジェクトのプロパティと新しいプロップを使用して新しいオブジェクトを作成します。
Ed Orsi 2017年

3
あなたはそれが正しいはずだったのは正しいですPerson = Person.map(code here)。ただし、ポイントは、を使用して既存のオブジェクトにプロパティを簡単に追加できることES6です。
Edper、2017年

5

最も簡単で最もポータブルな方法です。

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

#abeingの回答に基づく!


3

。(dot)メソッドを使用して既存のオブジェクトにプロパティを追加するときは注意してください

(.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 }

コンソールログの最後の問題に 注意してください-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、2018

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.