JavaScript nesnesine dinamik olarak adlandırılmış özellikler eklemek mümkün müdür?


745

JavaScript'te şöyle bir nesne oluşturdum:

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

Özellik adı çalışma süresine kadar belirlenmezse, ilk oluşturulduktan sonra bu nesneye başka özellikler eklemek mümkün müdür? yani

var propName = 'Property' + someUserInput
//imagine someUserInput was 'Z', how can I now add a 'PropertyZ' property to 
//my object?

Yanıtlar:


1211

Evet.

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, yeterince dinamik olmayan özellik adını bilmelidir.
Georg Schölly

6
+1 çünkü bu bana yardımcı oldu. Ama neden bir nesne özellikleri bir dizi gibi ele anlamıyorum.
Ron van der Heijden

9
@Bondye: Bu, javascript'in garip tasarımının bir parçası. Bu durumda object["property"], tam olarak aynı array[4]değildir, birincisi gerçek bir dizi olarak oluşturulmamıştır.
Georg Schölly

5
Sadece ben mi yoksa 195 gönderi alırken bu yazı soruyu cevaplamıyor mu? JavaScript kodunda oluşturulana kadar adın bilinmeyen özelliklerini nasıl tanımlayacağını sordum.
Qantas 94 Heavy

20
@Qantas: Diyelim ki doğrudan cevap vermiyor. Ama bu noktadan data["PropertyD"]başa çıkmak data[function_to_get_property_name()]önemsiz görünüyor.
Georg Schölly

154

Kazanmak için ES6!

const b = 'b';
const c = 'c';

const data = {
    a: true,
    [b]: true, // dynamic property
    [`interpolated-${c}`]: true, // dynamic property + interpolation
    [`${b}-${c}`]: true
}

Eğer giriş datayaparsanız bunu elde edersiniz:

{
  a: true,
  b: true,
  interpolated-c: true,
  b-c: true
}

Bu, yeni Computed Property sözdizimini ve Şablon Değişmezlerini kullanır .


1
Kodumun tamamen işlevsel olmasını istediğim durumda ihtiyacım olan şey buydu (zorunlu ifadeler olduğu gibi obj[propname]). Bunun yerine bunu nesne yayılımı sözdizimi ile kullanabildim.
intcreator

2
Bu kod pasajının yeni sözdizimini görmemiş veya anlamayan birine ne yaptığı hemen belli değildir. Çıktı / beklenen properies 'a' const ile görüntülemek için bir düzenleme öneriyoruz.

Şahsen, ES5 yolunun çok daha temiz ve anlaşılması daha kolay olduğunu düşünüyorum:var a = {}; a["dynamic-" + prop] = true;
Jack Giffin

1
@JackGiffin bazı durumlarda evet, ancak değişmez yapılarla çalışırken, bu sözdizimi çok kullanışlı olabilir, çünkü gösterdiğin yaklaşım mutasyona uğramaktadır a. (Özellikle redux gibi paketleri kullanırken)
Mauricio Soares

3
Bu sadece harika {... devlet, [prop]: val}
Xipo

87

Evet mümkün. varsayarsak:

var data = {
    'PropertyA': 1,
    'PropertyB': 2,
    'PropertyC': 3
};
var propertyName = "someProperty";
var propertyValue = "someValue";

Ya:

data[propertyName] = propertyValue;

veya

eval("data." + propertyName + " = '" + propertyValue + "'");

İlk yöntem tercih edilir. eval (), kullanıcı tarafından sağlanan değerleri kullanıyorsanız açık güvenlik endişelerine sahiptir, bu yüzden önleyebiliyorsanız kullanmayın, ancak var olduğunu ve ne yapabileceğini bilmeye değer.

Buna aşağıdakilerle başvurabilirsiniz:

alert(data.someProperty);

veya

data(data["someProperty"]);

veya

alert(data[propertyName]);

40
Eval kullanmak gerçekten tehlikelidir.
Georg Schölly

10
Yavaş bahsetmiyorum bile.
Eamon Nerbonne

@ GeorgSchölly Doğru.
Obinna Nwakwue

1
Not (birisinin benim yaptığımla aynı sorunla karşılaşması durumunda): Normal nesneler için bu iyi çalışır. Ancak bir jQuery UI nesnesine öğeler listesini izlemek için bazı özellik eklemek zorunda kaldı. Bu durumda, jQuery her zaman bir kopya oluşturduğu için bu şekilde eklenirse özellik kaybolur. Burada jQuery.extend () kullanmanız gerekir .
Matt

Önceki yorumuma eklemek istiyorum - bu bile benim durumumda işe yaramadı. Böylece $("#mySelector").data("propertyname", myvalue);set ve var myValue=$("#mySelector").data("propertyname");değeri geri almak için kullanarak sona erdi . Karmaşık nesneler (listeler, diziler ...) bile bu şekilde eklenebilir.
Matt

61

Sorunun mükemmel bir şekilde cevaplandığını biliyorum, ancak yeni özellikler eklemenin başka bir yolunu buldum ve sizinle paylaşmak istedim:

İşlevi kullanabilirsiniz Object.defineProperty()

Mozilla Geliştirici Ağı'nda bulundu

Misal:

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
Bu yöntemin artıları ve eksileri?
Trevor

6
@Trevor: Toplam yapılandırılabilirlik ve alıcı ve ayarlayıcı ekleme yeteneği; ayrıca, defineProperties(çoğul) ile aynı anda birden fazla özellik ekleme yeteneği .
rvighne

@Thielicious Object.definePropertykolay kolaylık aracı değil, hassas kontrol sahibi olan araç. Bu ek kontrole ihtiyacınız yoksa, seçmek için doğru araç değildir.
kleinfreund

Object.defineProperty(obj, prop, valueDescriptor)V8'in optimizasyonunu yapmaktan çok daha yavaş ve daha zordur obj[prop] = value;
Jack Giffin

27

ES6, yapmanızı sağlayan bilgisayarlı özellik adları sunar

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

23

Burada, yazınızı kullanarak:

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

Nokta gösterimini kullanarak istediğiniz kadar çok özellik ekleyebilirsiniz:

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

veya :

data[newattribute] = somevalue

dinamik anahtarlar için.


4
özellik adı çalışma zamanına kadar belirlenmezse "- eval kullanmadıkça işe yaramaz, bu iyi bir seçenek değildir
Marc Gravell

1
ya da [] sözdizimi ... verilerini kullanın [somevar] = somevalue
Gabriel Hurley

17

önceki tüm yanıtlara ek olarak ve Gelecekte Hesaplanmış Özellik Adlarını (ECMAScript 6) kullanarak nasıl dinamik özellik adları yazacağımızı merak ediyorsanız, nasıl yapacağınız aşağıda açıklanmıştır :

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

personIndex[ personId ]; // "John Doe"

başvuru: ECMAScript 6'yı anlama - Nickolas Zakas


11

Yukarıdaki yanıtın sadece bir yanı. Aşağıdaki gibi defineProperty'nin karmaşıklığını kapsüllemek için bir işlev tanımlayabilirsiniz.

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

başvuru: http://addyosmani.com/resources/essentialjsdesignpatterns/book/#constructorpatternjavascript


9

Aşağıdaki seçeneklerden bazılarını kullanarak özellikleri dinamik olarak ekleyebilirsiniz:

Örnekte:

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

Dinamik değere sahip bir özelliği sonraki iki yolla tanımlayabilirsiniz:

data.key = value;

veya

data['key'] = value;

Daha da fazlası ... anahtarınız da dinamikse, Object sınıfını aşağıdakilerle kullanarak tanımlayabilirsiniz:

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

Burada veri nesneniz olduğunda, anahtar anahtar adını saklamak için değişken ve değer değeri saklamak için değişken.

Umarım bu yardımcı olur!


8

Zaten bu yazıya birkaç cevap olduğunu biliyorum, ama ben birden fazla özellik ve bir dizi içinde olduğu bir görmedim. Bu arada bu çözüm ES6 için.

Örnek olarak, içinde nesneleri olan kişi adında bir dizimiz olduğunu varsayalım:

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

Böylece, karşılık gelen değere sahip bir özellik ekleyebilirsiniz. Diyelim ki varsayılan değeri EN olan bir Dil eklemek istiyoruz .

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

Kişi dizisi artık böyle olacak:

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

Aslında bir nesneye özellikler eklemiyorsunuz, eski nesnenin özellikleri (yayma operatörü aracılığıyla) ve yeni sahne öğeleri ile yeni bir nesne oluşturuyorsunuz.
Ed Orsi

3
Olması gerektiği konusunda haklısın Person = Person.map(code here). Ancak asıl nokta, mevcut bir nesneye kolayca özellik ekleyebilmenizdir ES6.
Edper

5

En basit ve taşınabilir yol.

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

#Abeing cevabına göre!


3

. (Dot) yöntemini kullanarak mevcut nesneye bir özellik eklerken dikkatli olun .

(.dot) nesneye özellik ekleme yöntemi, yalnızca 'anahtarı' önceden biliyorsanız , aksi takdirde [ayraç] yöntemini kullanın.

Misal:

   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 }

Not Sorunu konsol günlüğünün sonunda - 'tuşu: 1999' yerine Property6: 6, Property7: 7, ........., Property1999: 1999 . Dinamik olarak oluşturulan özellik eklemenin en iyi yolu [braket] yöntemidir.


1

Nesne içeren dinamik dize adlarından erişmenin güzel bir yolu (örneğin, 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;
}

Misal:

ReadValue("object.subobject.property");
WriteValue("object.subobject.property",5);

eval okuma değeri için çalışır, ancak yazma değeri biraz daha zordur.

Daha gelişmiş bir sürüm (Varsa alt sınıflar oluşturun ve genel değişkenler yerine nesnelere izin verin)

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

Misal:

ReadValue("object.subobject.property",o);
WriteValue("object.subobject.property",5,o);

Bu, o.object.subobject.property ile aynıdır


1
tam olarak ne aradığını, bu tepki tepki için yararlıdır. setState ({dynamic property: value}) teşekkür ederim!
Kevin Danikowski

0

Sorunu şu şekilde çözdüm.

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

Aşağıdaki nesneyi oluşturur:

{
  "someouter": {
    "someinner": {
      "someValue": 123
    }
  },
  "simpleString": "string"
}

0

Çalışma zamanında karışık yeni özellik eklenmesi yararlı olabilir:

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

Ancak, forma operatörü sığ kopya kullanır, ancak burada kendisine veri atarız.


-2

Mükemmel ve kolay bir yol

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

var newProperty = 'getThisFromUser';
data[newProperty] = 4;

console.log(data);

Bir dizi veriye uygulamak istiyorsanız (ES6 / TS sürümü)

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

Kesinlikle. Bir sözlük veya ilişkilendirilebilir dizi olarak düşünün. İstediğiniz zaman ekleyebilirsiniz.


1
Sadece bunu söylemek yardımcı olmaz.
Obinna Nwakwue
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.