क्या जावास्क्रिप्ट ऑब्जेक्ट में गतिशील रूप से नामित गुण जोड़ना संभव है?


745

जावास्क्रिप्ट में, मैंने एक वस्तु बनाई है जैसे:

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?

जवाबों:


1210

हाँ।

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 को संपत्ति के नाम को जानना होगा, जो पर्याप्त गतिशील नहीं है।
जॉर्ज शॉर्ली

6
+1 क्योंकि इससे मुझे मदद मिली। लेकिन मुझे समझ में नहीं आता है कि ऑब्जेक्ट गुण को सरणी की तरह क्यों संभाला जाता है।
रॉन वैन डेर हाइजेन

9
@ बॉन्ड: यह जावास्क्रिप्ट के अजीब डिजाइन का हिस्सा है। इस मामले object["property"]में ठीक वैसा ही नहीं है, जैसा array[4]कि पूर्व को एक सच्चे सरणी के रूप में नहीं बनाया गया था।
जॉर्ज शॉर्ली

5
क्या यह सिर्फ मेरे लिए है या इस पोस्ट में १ ९ ५ तक के सवाल का जवाब नहीं दिया गया है? मुझे लगा कि यह पूछ रहा है कि जावास्क्रिप्ट कोड में उत्पन्न होने तक नाम जहां अज्ञात है, गुणों को कैसे परिभाषित किया जाए।
कांता 94 94

20
@Qantas: मान लीजिए कि इसका सीधा जवाब नहीं है। लेकिन से जा रहा data["PropertyD"]करने के लिए data[function_to_get_property_name()]तुच्छ लगता है।
जॉर्ज शॉली

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])। इसके बजाय, मैं इसका उपयोग ऑब्जेक्ट स्प्रेड सिंटैक्स के साथ करने में सक्षम था।
इंट्रक्रेटर

2
यह तुरंत स्पष्ट नहीं है कि यह कोड स्निपेट किसी ऐसे व्यक्ति के लिए क्या कर रहा है जिसने नए वाक्यविन्यास को नहीं देखा या समझ नहीं पाया है। मैं 'a' कॉन्स्ट के साथ आउटपुट / उम्मीद की गई उचितताओं को प्रदर्शित करने के लिए एक संपादन का सुझाव दूंगा।

व्यक्तिगत रूप से, मुझे लगता है कि ES5 रास्ता एक बहुत क्लीनर और समझने में आसान है:var a = {}; a["dynamic-" + prop] = true;
जैक जिफिन

1
कुछ मामलों में @JackGiffin हाँ, लेकिन अपरिवर्तनीय संरचनाओं के साथ काम करते समय, यह वाक्यविन्यास बहुत आसान हो सकता है, क्योंकि आपके द्वारा दिखाया गया दृष्टिकोण उत्परिवर्तित होता है a। (विशेष रूप से रिडक्स जैसे पैकेजों का उपयोग करते समय)
मौरिसियो सोरेस

3
यह सिर्फ महान {... राज्य, [सहारा]: घाटी}
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 का उपयोग करना वास्तव में खतरनाक है।
जॉर्ज शॉली

10
धीमी गति का उल्लेख नहीं है।
Eamon Nerbonne

@ GeorgSchölly सच है।
ओबिना किवकुवे

1
ध्यान दें (यदि कोई मेरे द्वारा जारी किए गए मुद्दे के अनुसार चलता है): सामान्य वस्तुओं के लिए यह ठीक काम करता है। लेकिन मुझे वस्तुओं की सूची का ट्रैक रखने के लिए एक jQuery UI ऑब्जेक्ट में कुछ संपत्ति जोड़ना पड़ा। उस स्थिति में, संपत्ति खो गई थी अगर इस तरह से जोड़ा गया क्योंकि jQuery हमेशा एक प्रतिलिपि बनाता है। यहां आपको jQuery.extend () का उपयोग करने की आवश्यकता है ।
मैट

मुझे अपनी पिछली टिप्पणी में जोड़ना पसंद है - यहां तक ​​कि मेरे मामले में काम नहीं किया। इसलिए मैं $("#mySelector").data("propertyname", myvalue);सेट का उपयोग कर , और var myValue=$("#mySelector").data("propertyname");मूल्य वापस पाने के लिए समाप्त हो गया । यहां तक ​​कि जटिल वस्तुओं (सूचियों, सरणियों ...) को इस तरह से जोड़ा जा सकता है।
मैट

61

मुझे पता है कि प्रश्न का पूरी तरह से उत्तर दिया गया है, लेकिन मुझे नई संपत्तियों को जोड़ने का एक और तरीका मिला है और मैं इसे आपके साथ साझा करना चाहता हूं:

आप फ़ंक्शन का उपयोग कर सकते हैं Object.defineProperty()

मोज़िला डेवलपर नेटवर्क पर मिला

उदाहरण:

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
इस विधि के पेशेवरों और विपक्ष?
ट्रेवर

6
@ ट्रेवर: गेट और बसने वालों को जोड़ने के लिए कुल विन्यास और क्षमता; इसके अलावा, defineProperties(बहुवचन) के साथ एक ही बार में कई गुण जोड़ने की क्षमता ।
rvighne

@ Object.definePropertyआसान का मतलब आसान सुविधा उपकरण नहीं है, लेकिन ठीक-ठीक नियंत्रण के साथ एक है। यदि आपको उस अतिरिक्त नियंत्रण की आवश्यकता नहीं है, तो यह चुनने का सही उपकरण नहीं है।
kleinfreund

Object.defineProperty(obj, prop, valueDescriptor)V8 के लिए बस करने की तुलना में अनुकूलन करने के लिए बहुत धीमा और कठिन है obj[prop] = value;
जैक गिफिन

27

ईएस 6 गणना की गई संपत्ति के नाम का परिचय देता है, जो आपको करने की अनुमति देता है

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
या [] वाक्य रचना ... डेटा [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 को समझना - निकोलस ज़कस


11

ऊपर दिए गए उत्तर का पालन करने के लिए बस एक अतिरिक्त। आप एक फ़ंक्शन को परिभाषित कर सकते हैं जैसा कि नीचे बताया गया है।

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/#constructorpatternatavavcript


9

आप नीचे दिए गए कुछ विकल्पों का उपयोग करके गतिशील रूप से गुण जोड़ सकते हैं:

आप उदाहरण में:

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

आप एक संपत्ति को अगले दो तरीकों से एक गतिशील मूल्य के साथ परिभाषित कर सकते हैं:

data.key = value;

या

data['key'] = value;

इससे भी अधिक..यदि आपकी कुंजी भी गतिशील है, तो आप ऑब्जेक्ट क्लास का उपयोग करके इसे परिभाषित कर सकते हैं:

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

जहां डेटा आपकी वस्तु है, कुंजी कुंजी नाम को संग्रहीत करने के लिए चर है और मूल्य को संग्रहीत करने के लिए चर है।

आशा है कि ये आपकी मदद करेगा!


8

मुझे पता है कि इस पोस्ट के कई उत्तर पहले से ही हैं, लेकिन मैंने एक भी नहीं देखा है जिसमें कई गुण हैं और वे एक सरणी में हैं। और वैसे यह समाधान ईएस 6 के लिए है।

उदाहरण के लिए, मान लें कि हमारे पास एक सरणी है जिसका नाम अंदर की वस्तुओं के साथ है:

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

आप वास्तव में किसी ऑब्जेक्ट में गुण नहीं जोड़ रहे हैं, आप पुरानी ऑब्जेक्ट के गुणों (स्प्रेड ऑपरेटर के माध्यम से) और नए प्रॉप्स के साथ एक नई ऑब्जेक्ट बना रहे हैं।
एड ऑर्सी

3
आप सही हैं कि यह होना चाहिए था Person = Person.map(code here)। लेकिन मुद्दा यह है कि आप किसी मौजूदा ऑब्जेक्ट के साथ आसानी से संपत्ति जोड़ सकते हैं ES6
एडपर

5

सबसे सरल और सबसे पोर्टेबल तरीका है।

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

# जवाब देने के आधार पर!


3

मौजूदा ऑब्जेक्ट (डॉट) पद्धति का उपयोग करते हुए एक संपत्ति जोड़ते समय सावधान रहें

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

कंसोल लॉग के अंत में समस्या पर ध्यान दें - प्रॉपर्टी 6: 6, प्रॉपर्टी 7: 7, ........., प्रॉपर्टी 1999 : 1999 के बजाय 'की: 1999' । तो गतिशील रूप से बनाई गई संपत्ति को जोड़ने का सबसे अच्छा तरीका [ब्रैकेट] विधि है।


1

गतिशील स्ट्रिंग नामों से एक्सेस करने का एक अच्छा तरीका है जिसमें ऑब्जेक्ट्स हैं (उदाहरण के लिए ऑब्जेक्ट.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
वास्तव में मैं क्या देख रहा था, यह इस प्रतिक्रिया के लिए उपयोगी है। शुरू (गतिशील संपत्ति: मूल्य}) धन्यवाद!
केविन डेनिकोव्स्की

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 14
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.