代码之家  ›  专栏  ›  技术社区  ›  Lee D

是否可以向javascript对象添加动态命名的属性?

  •  624
  • Lee D  · 技术社区  · 15 年前

    在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?
    
    16 回复  |  直到 6 年前
        1
  •  1023
  •   H. Pauwelyn    8 年前

    对。

    var data = {
        'PropertyA': 1,
        'PropertyB': 2,
        'PropertyC': 3
    };
    
    data["PropertyD"] = 4;
    
    // dialog box with 4 in it
    alert(data.PropertyD);
    alert(data["PropertyD"]);
        2
  •  83
  •   Luca Kiebel    6 年前

    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
    }
    

    这利用了新的 Computed Property 语法和 Template Literals .

        3
  •  80
  •   cletus    15 年前

    是的,这是可能的。假设:

    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]);
    
        4
  •  52
  •   artgrohe    11 年前

    我知道这个问题得到了完美的回答,但我也找到了另一种添加新属性的方法,并希望与您共享:

    你可以使用这个功能 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
    
        5
  •  19
  •   Maxim Sloyko    15 年前

    这里,使用您的符号:

    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'
    
        6
  •  16
  •   Gabriel Hurley    15 年前

    只需使用点表示法,您就可以添加任意多的属性:

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

    :

    data[newattribute] = somevalue
    

    动态键。

        7
  •  16
  •   Anas Nakawa pete otaqui    11 年前

    除了前面所有的答案之外,如果您想知道我们将如何在 未来 使用计算属性名(ecmascript 6),如下所示:

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

    参考文献: Understanding ECMAScript 6 - Nickolas Zakas

        8
  •  10
  •   Sarvesh    11 年前

    只不过是对以上Abeing答案的补充。您可以定义一个函数来封装定义属性的复杂性,如下所述。

    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
  •  7
  •   morewry    7 年前

    可以使用以下某些选项动态添加属性:

    在你的例子中:

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

    可以通过以下两种方式定义具有动态值的属性:

    data.key = value;
    

    data['key'] = value;
    

    更多..如果您的键也是动态的,您可以使用对象类定义:

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

    哪里 数据 是你的目标, 钥匙 是存储密钥名称的变量,并且 价值 是存储值的变量。

    希望这有帮助!

        10
  •  5
  •   Edper    7 年前

    我知道这篇文章已经有几个答案了,但是我还没有看到一个答案,其中有多个属性,并且它们在一个数组中。顺便说一下,这个解决方案是针对ES6的。

    例如,我们有一个名为person的数组,其中包含对象:

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

    因此,可以添加具有相应值的属性。假设我们要添加一个 语言 默认值为 .

    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"}]
    
        11
  •  4
  •   Sydwell    9 年前

    最简单和最便携的方法是。

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

    基于abeing答案!

        12
  •  1
  •   hamboy75    8 年前

    从包含对象(例如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相同

        13
  •  0
  •   lewma    8 年前

    我就是这样解决这个问题的。

    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"
    }
    
        14
  •  0
  •   Eugen Konkov    6 年前

    小心 向现有对象添加属性时,使用 (点) 方法。

    (点) 向对象添加属性的方法只能在 知道 这个 “钥匙” 事先,否则使用 [括号] 方法。

    例子:

       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 }

    注意 问题 在控制台日志的末尾- 钥匙:1999 而不是 财产6:6,财产7:7,………,财产1999:1999 . 因此,添加动态创建属性的最佳方法是[bracket]方法。

        15
  •  0
  •   Umesh    6 年前

    非常简单的方法

    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);
    
        16
  •  -11
  •   thedz    15 年前

    一定地。把它当作字典或关联数组。你可以在任何时候添加它。