繁体   English   中英

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

[英]Is it possible to add dynamically named properties to JavaScript object?

在 JavaScript 中,我创建了一个这样的对象:

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

如果直到运行时才确定属性名称,是否可以在初始创建后向该对象添加更多属性? IE

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

是的。

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

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

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

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

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

您可以使用函数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

ES6 引入了计算属性名,它允许你做

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

在这里,使用您的符号:

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'

您可以使用点符号添加任意数量的属性:

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

除了之前的所有答案,如果您想知道我们将如何在未来<\/strong>使用计算属性名称 (ECMAScript 6) 编写动态属性名称,以下是方法:

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

personIndex[ personId ]; // "John Doe"

只是上面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

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

在你的例子中:

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

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

data.key = value;

或者

data['key'] = value;

甚至更多..如果您的密钥也是动态的,您可以使用 Object 类定义:

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

其中data是您的对象, key是存储键名的变量, value是存储值的变量。

我希望这有帮助!

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

为了说明,假设我们有一个名为 person 的数组,里面有对象:

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

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

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

Person数组现在会变成这样:

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

我正在寻找一种解决方案,我可以在对象声明中使用动态键名(不使用...<\/code>或[key]: value<\/code>等 ES6 功能)

这是我想出的:

var obj = (obj = {}, obj[field] = 123, obj)

如果在运行时添加混合新属性会很有用:

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

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

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

使用.(dot)<\/strong>方法向现有对象添加属性时要小心<\/strong>。

(.dot)<\/strong>向对象添加属性的方法只有在您事先知道<\/strong>“键”<\/em><\/strong>时才应使用,否则使用[bracket]<\/strong>方法。

例子:<\/em><\/strong>

请注意控制台日志末尾的问题<\/strong>- 'key: 1999'<\/strong>而不是Property6: 6, Property7: 7,..........,Property1999: 1999<\/strong> 。 所以添加动态创建的属性最好的方法是 [bracket] 方法。

从包含对象的动态字符串名称访问的好方法(例如 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 相同

对的,这是可能的。 我已经使用下面的实现实现了。 为此,我得到数组作为响应,我希望在对象中作为属性列表。

response = {
  "equityMonths": [
    {
      "id": 1,
      "month": "JANUARY",
      "isEligible": false
    },
    {
      "id": 2,
      "month": "FEBRUARY",
      "isEligible": true
    },
    {
      "id": 3,
      "month": "MARCH",
      "isEligible": false
    },
    {
      "id": 4,
      "month": "APRIL",
      "isEligible": true
    },
    {
      "id": 5,
      "month": "MAY",
      "isEligible": false
    },
    {
      "id": 6,
      "month": "JUNE",
      "isEligible": true
    },
    {
      "id": 7,
      "month": "JULY",
      "isEligible": true
    },
    {
      "id": 8,
      "month": "AUGUST",
      "isEligible": false
    },
    {
      "id": 9,
      "month": "SEPTEMBER",
      "isEligible": true
    },
    {
      "id": 10,
      "month": "OCTOBER",
      "isEligible": false
    },
    {
      "id": 11,
      "month": "NOVEMBER",
      "isEligible": true
    },
    {
      "id": 12,
      "month": "DECEMBER",
      "isEligible": false
    }
  ]
}

在这里,我希望equityMonths作为对象,Jan 到Dec 它是关键, isEligible作为值。 为此,我们必须使用 Object 类的defineProperty()方法,该方法允许将动态属性添加到对象中。

用于向对象动态添加属性的代码。

let equityMonth = new Object();

response.equityMonths.forEach(element => {
    Object.defineProperty(equityMonth, element['month'], {
       value: element['isEligible'],
       writable: true,
       enumerable: true,
       configurable: true
    });
});
console.log("DATA : " + JSON.stringify(equityMonth));

在上面的代码中,我们有一个equityMonths数组,我们将其作为属性转换为对象。

输出:

DATA : {"JANUARY":false,"FEBRUARY":true,"MARCH":false,"APRIL":true,"MAY":false,"JUNE":true,"JULY":true,"AUGUST":false,"SEPTEMBER":true,"OCTOBER":false,"NOVEMBER":true,"DECEMBER":false}

这是我解决问题的方法。

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

一个完美的简单方法

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

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

console.log(data);

确实。 将其视为字典或关联数组。 您可以随时添加它。

"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM