如何在JavaScript对象文字中使用一个键的变量?

为什么下面的工作?

<something>.stop().animate(
{ 'top' : 10 }, 10
);

然而这是行不通的:

var thetop = 'top';
<something>.stop().animate(
{ thetop : 10 }, 10
);

更清楚地说:目前我还不能将CSS属性作为变量传递给动画函数。

287975 次浏览

{ thetop : 10 }是一个有效的对象字面值。这段代码将创建一个对象,其属性名为thetop,值为10。以下两种情况相同:

obj = { thetop : 10 };
obj = { "thetop" : 10 };

在ES5及更早的版本中,不能在对象文字中使用变量作为属性名。你唯一的选择是做以下事情:

var thetop = "top";


// create the object literal
var aniArgs = {};


// Assign the variable property name with a value of 10
aniArgs[thetop] = 10;


// Pass the resulting object to the animate method
<something>.stop().animate(
aniArgs, 10
);

ES6 定义了 ComputedPropertyName作为对象字面量语法的一部分,这允许你像这样编写代码:

var thetop = "top",
obj = { [thetop]: 10 };


console.log(obj.top); // -> 10

您可以在每个主流浏览器的最新版本中使用这种新语法。

我已经使用下面的方法来添加一个具有“动态”名称的属性到对象:

var key = 'top';
$('#myElement').animate(
(function(o) { o[key]=10; return o;})({left: 20, width: 100}),
10
);

key是新属性的名称。

传递给animate的属性对象将是{left: 20, width: 100, top: 10}

这只是使用了其他答案所推荐的必需的[]符号,但是代码行数更少!

ES5引用说它不应该工作

注意:ES6的规则已经改变:https://stackoverflow.com/a/2274327/895245

规范:# EYZ0

PropertyName:

  • IdentifierName
  • StringLiteral
  • NumericLiteral

[…]

产品PropertyName: IdentifierName的计算方法如下:

  1. 返回String值,该值包含与IdentifierName相同的字符序列。

产品PropertyName: StringLiteral的计算方法如下:

  1. 返回StringLiteral的SV [String value]。

产品PropertyName: NumericLiteral的计算方法如下:

  1. 设nbr为数值字面值形成的结果。
  2. 返回ToString (nbr)。

这意味着:

  • { theTop : 10 }{ 'theTop' : 10 }完全相同

    PropertyName theTop是一个IdentifierName,所以它被转换为'theTop'字符串值,这是'theTop'的字符串值

  • 不能用可变键写对象初始化式(字面量)。

    只有三个选项是IdentifierName(展开为字符串文字),StringLiteralNumericLiteral(也展开为字符串)

使用ECMAScript 2015,你现在可以直接在对象声明中使用括号符号: 

var obj = {
[key]: value
}

其中key可以是返回值的任何类型的表达式(例如变量)。

你的代码看起来是这样的:

<something>.stop().animate({
[thetop]: 10
}, 10)

其中thetop在被用作键之前将被计算。

在变量周围加上方括号对我来说很好。试试这个

var thetop = 'top';
<something>.stop().animate(
{ [thetop] : 10 }, 10
);

给定的代码:

var thetop = 'top';
<something>.stop().animate(
{ thetop : 10 }, 10
);

翻译:

var thetop = 'top';
var config = { thetop : 10 }; // config.thetop = 10
<something>.stop().animate(config, 10);

正如您所看到的,{ thetop : 10 }声明没有使用变量thetop。相反,它创建了一个具有名为thetop键的对象。如果你想让键值是变量thetop的值,那么你必须在thetop周围使用方括号:

var thetop = 'top';
var config = { [thetop] : 10 }; // config.top = 10
<something>.stop().animate(config, 10);

方括号语法已在ES6中引入。在JavaScript的早期版本中,您必须执行以下操作:

var thetop = 'top';
var config = (
obj = {},
obj['' + thetop] = 10,
obj
); // config.top = 10
<something>.stop().animate(config, 10);

这样也可以实现预期的输出

var jsonobj={};
var count=0;
$(document).on('click','#btnadd', function() {
jsonobj[count]=new Array({ "1"  : $("#txtone").val()},{ "2"  : $("#txttwo").val()});
count++;
console.clear();
console.log(jsonobj);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span>value 1</span><input id="txtone" type="text"/>
<span>value 2</span><input id="txttwo" type="text"/>
<button id="btnadd">Add</button>

ES5实现分配键如下:

var obj = Object.create(null),
objArgs = (
(objArgs = {}),
(objArgs.someKey = {
value: 'someValue'
}), objArgs);


Object.defineProperties(obj, objArgs);

我附上了一个片段,我用来转换为裸对象。

var obj = {
'key1': 'value1',
'key2': 'value2',
'key3': [
'value3',
'value4',
],
'key4': {
'key5': 'value5'
}
}


var bareObj = function(obj) {


var objArgs,
bareObj = Object.create(null);


Object.entries(obj).forEach(function([key, value]) {


var objArgs = (
(objArgs = {}),
(objArgs[key] = {
value: value
}), objArgs);


Object.defineProperties(bareObj, objArgs);


});


return {
input: obj,
output: bareObj
};


}(obj);


if (!Object.entries) {
Object.entries = function(obj){
var arr = [];
Object.keys(obj).forEach(function(key){
arr.push([key, obj[key]]);
});
return arr;
}
}


console(bareObj);

您可以为ES5执行以下操作:

var theTop = 'top'
<something>.stop().animate(
JSON.parse('{"' + theTop + '":' + JSON.stringify(10) + '}'), 10
)

或提取为一个函数:

function newObj (key, value) {
return JSON.parse('{"' + key + '":' + JSON.stringify(value) + '}')
}


var theTop = 'top'
<something>.stop().animate(
newObj(theTop, 10), 10
)
如果你想让对象键和变量名相同,在es2015中有一个简短的手。 # EYZ0 < / p >
var thetop = 10;
var obj = { thetop };
console.log(obj.thetop); // print 10

你可以这样做:

var thetop = 'top';
<something>.stop().animate(
new function() {this[thetop] = 10;}, 10
);

我找不到关于ES6和ES5之间区别的简单的例子,所以我做了一个。两个代码示例都创建了完全相同的对象。但是ES5的例子也适用于较老的浏览器(如IE11),而ES6的例子则不能。

ES6

var matrix = {};
var a = 'one';
var b = 'two';
var c = 'three';
var d = 'four';


matrix[a] = {[b]: {[c]: d}};

ES5

var matrix = {};
var a = 'one';
var b = 'two';
var c = 'three';
var d = 'four';


function addObj(obj, key, value) {
obj[key] = value;
return obj;
}


matrix[a] = addObj({}, b, addObj({}, c, d));

你也可以这样尝试:

const arr = [{
"description": "THURSDAY",
"count": "1",
"date": "2019-12-05"
},
{
"description": "WEDNESDAY",
"count": "0",
"date": "2019-12-04"
}]
const res = arr.map(value => {
return { [value.description]: { count: value.count, date: value.date } }
})
console.log(res);

更新:正如一位评论者指出的,任何支持箭头函数的JavaScript版本都将支持({[myKey]:myValue}),所以这个答案是没有实际用例(事实上,它可能会在一些奇怪的角落情况下崩溃)。

不要使用下面列出的方法。


I 不能相信这个还没有发布:只使用匿名求值的箭头函数!

完全非侵入性,不会混淆名称空间,它只需要一行:

myNewObj = ((k,v)=>{o={};o[k]=v;return o;})(myKey,myValue);

演示:

var myKey="valueof_myKey";
var myValue="valueof_myValue";
var myNewObj = ((k,v)=>{o={};o[k]=v;return o;})(myKey,myValue);
console.log(myNewObj);

# EYZ1 # EYZ2

(我确信你可能会做出一些更强大/可扩展的解决方案,或者任何涉及巧妙使用reduce的解决方案,但在这一点上,你可能会更好地将对象创建分解到自己的函数中,而不是强制地将其全部内联)


这并不重要,因为OP十年前就问过这个问题,但为了完整起见,并证明它是如何回答上述问题的完全 ,我将在原始上下文中展示这一点:

var thetop = 'top';
<something>.stop().animate(
((k,v)=>{o={};o[k]=v;return o;})(thetop,10), 10
);

2020年更新/例子…

一个更复杂的例子,使用括号和字面量…您可能需要做一些事情,例如使用vue/axios。把文字用括号括起来,所以

['…]']

{
[`filter[${query.key}]`]: query.value,  // 'filter[foo]' : 'bar'
}

Es6 / 2020

如果您试图使用“;key:value"从任何其他来源,你可以使用这样的东西:

let obj = {}
let key = "foo"
let value = "bar"


obj[`${key}`] = value


// A `console.log(obj)` would return:
// {foo: "bar}


// A `typeof obj` would return:
// "object"

希望这能帮助到一些人:)