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

2020/09/21 08:01 · javascript ·  · 0评论

在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?

是。

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
}

这利用了新的“ 计算属性”语法和“ 模板文字”

是的,有可能。假设:

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'

data[newattribute] = somevalue

用于动态键。

除了前面所有的答案之外,如果您想知道将来如何使用计算属性名称(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

只是上述安倍答案的补充。您可以定义一个函数来封装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"}]

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

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

根据#abeing答案!

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

(.dot)向对象添加属性的方法仅应事先知道'key'的情况下使用,否则请使用[bracket]方法。

例:

   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 }

注意控制台日志末尾问题 -'key
:1999',而不是Property6:6,Property7:7,.........,Property1999:1999因此,添加动态创建的属性的最佳方法是[bracket]方法。

如果在运行时添加了新属性,则可能很有用:

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

但是,散布运算符使用浅表复制,但此处我们将数据分配给自身,因此应该不会丢失任何内容

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

这是我解决问题的方法。

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

我一直在寻找一种解决方案,可以在对象声明中使用动态键名(不使用诸如...或的ES6功能[key]: value

这是我想出的:

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

起初看起来有些复杂,但是确实很简单。我们使用逗号运算符来连续运行三个命令:

  1. obj = {}:创建一个新对象并将其分配给变量 obj
  2. obj[field] = 123:将计算出的属性名称添加obj
  3. obj:使用该obj变量作为括号/逗号列表的结果

此语法可以在函数参数内使用,而无需明确声明obj变量:

// The test function to see the result.
function showObject(obj) {
    console.log(obj);
}

// My dynamic field name.
var field = "myDynamicField";

// Call the function with our dynamic object.
showObject( (obj = {}, obj[field] = 123, obj) );

/*
Output:

{
  "myDynamicField": true
}
*/

一些变化

“严格模式”解决方法:

上面的代码不起作用,strict mode因为未声明变量“ obj”。

// This gives the same result, but declares the global variable `this.obj`!
showObject( (this.obj = {}, obj[field] = 123, obj) );

ES2015代码在初始化程序中使用计算的属性名称:

// Works in most browsers, same result as the other functions.
showObject( {[field] = 123} );

此解决方案可在所有现代浏览器中使用(但在IE中则无效,如果我需要提及的话)

超级hacky方式使用JSON.parse()

// Create a JSON string that is parsed instantly. Not recommended in most cases.
showObject( JSON.parse( '{"' + field +'":123}') );
// read: showObject( JSON.parse( '{"myDynamicfield":123}') );

允许按键中包含特殊字符

请注意,您还可以在计算出的属性名称(以及JSON.parse)中使用空格和其他特殊字符。

var field = 'my dynamic field :)';
showObject( {[field] = 123} );
// result: { "my dynamic field :)": 123 }

这些字段不能使用点(obj.my dynamic field :)显然在语法上无效)进行访问,而只能通过方括号表示,即obj['my dynamic field :)']返回123

完美的简便方法

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

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

本文地址:http://javascript.askforanswer.com/shifoukeyixiangjavascriptduixiangtianjiadongtaimingmingdeshuxing.html
文章标签:
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!