Как использовать переменную для ключа в литерале объекта JavaScript?
почему после работы?
<something>.stop().animate(
{ 'top' : 10 }, 10
);
Если это не работает:
var thetop = 'top';
<something>.stop().animate(
{ thetop : 10 }, 10
);
чтобы было еще яснее: на данный момент я не могу передать свойство CSS функции animate в качестве переменной.
8 ответов
{ 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
);
ЕС6 определяет ComputedPropertyName как часть грамматики для объектных литералов, которая позволяет писать код такой:
var thetop = "top",
obj = { [thetop]: 10 };
console.log(obj.top); // -> 10
вы можете использовать этот новый синтаксис в последних версиях каждого основного браузера.
С ECMAScript 2015 теперь вы можете сделать это непосредственно в объявлении объекта с пометкой скобки:
var obj = {
[key]: value
}
здесь key
может быть любым выражением (например, переменной), возвращающим значение.
так вот ваш код будет выглядеть так:
<something>.stop().animate({
[thetop]: 10
}, 10)
здесь thetop
будет заменено значением переменной.
ES5 цитата, которая говорит, что она не должна работать
Spec:http://www.ecma-international.org/ecma-262/5.1/#sec-11.1.5
PropertyName:
- IdentifierName
- StringLiteral
- NumericLiteral
[...]
production PropertyName: IdentifierName оценивается следующим образом:
- возвращает строковое значение, содержащее ту же самую последовательность символов как IdentifierName.
production PropertyName: StringLiteral оценивается следующим образом:
- возвращает SV [строковое значение]StringLiteral.
Production PropertyName: NumericLiteral оценивается следующим образом:
- пусть nbr будет результатом формирования значения NumericLiteral.
- Return ToString(nbr).
это означает, что:
-
{ theTop : 10 }
Это то же самое, что{ 'theTop' : 10 }
на
PropertyName
theTop
- этоIdentifierName
, поэтому он преобразуется в элемент'theTop'
строковое значение, которое является строковым значением'theTop'
. -
невозможно написать инициализаторы объектов (литералы) с переменными ключами.
только три варианты
IdentifierName
(расширяется до строкового литерала),StringLiteral
иNumericLiteral
(также расширяется до строки).
правила изменились для ES6:https://stackoverflow.com/a/2274327/895245
я использовал следующее, Чтобы добавить свойство с "динамическим" именем к объекту:
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}
Это просто с помощью []
обозначения, рекомендованные другими ответами, но с меньшим количеством строк кода!
добавление квадратной скобки вокруг переменной хорошо работает для меня. Попробуйте это
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);