Как использовать переменную для ключа в литерале объекта JavaScript? - PullRequest
323 голосов
/ 16 февраля 2010

Почему работает следующее?

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

Принимая во внимание, что это не работает:

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

Чтобы сделать это еще яснее: В данный момент я не могу пройтисвойство CSS для функции animate как переменной.

Ответы [ 12 ]

546 голосов
/ 16 февраля 2010

{ 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

Вы можете использовать этот новый синтаксис в последних версиях каждого основного браузера.

99 голосов
/ 16 марта 2016

С ECMAScript 2015 теперь вы можете сделать это непосредственно в объявлении объекта с помощью скобок:

var obj = {
  [key]: value
}

Где key может быть любым выражением (например, переменной), возвращающим значение.

Итак, ваш код будет выглядеть так:

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

Где thetop будет оцениваться перед использованием в качестве ключа.

15 голосов

Цитата ES5, которая говорит, что она не должна работать

Примечание: правила для ES6 были изменены: https://stackoverflow.com/a/2274327/895245

Спецификация: http://www.ecma -international.org / ecma-262 / 5.1 / # sec-11.1.5

PropertyName:

  • ИмяИдентификатор
  • СтроковойЛитерал
  • ЧисловойЛитерал

[...]

Производство PropertyName: IdentifierName оценивается следующим образом:

  1. Возвращает значение String, содержащее ту же последовательность символов, что и IdentifierName.

Производство PropertyName: StringLiteral оценивается следующим образом:

  1. Возвращает SV [строковое значение] StringLiteral.

Производство PropertyName: NumericLiteral оценивается следующим образом:

  1. Пусть nbr будет результатом формирования значения NumericLiteral.
  2. Return ToString (nbr).

Это означает, что:

  • { theTop : 10 } точно так же, как { 'theTop' : 10 }

    PropertyName theTop - это IdentifierName, поэтому он преобразуется в строковое значение 'theTop', которое является строковым значением 'theTop'.

  • Невозможно написать инициализаторы объектов (литералы) с переменными ключами.

    Доступны только три параметра: IdentifierName (расширяется до строкового литерала), StringLiteral и NumericLiteral (также расширяется до строки).

5 голосов
/ 10 января 2014

Я использовал следующее для добавления свойства с «динамическим» именем к объекту:

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}

Это просто использование обязательной записи [] в соответствии с рекомендациями других ответов, но с меньшим количеством строк кода!

4 голосов
/ 13 мая 2017

Добавление квадратной скобки вокруг переменной работает хорошо для меня. Попробуйте это

var thetop = 'top';
<something>.stop().animate(
    { [thetop] : 10 }, 10
);
1 голос
/ 10 апреля 2019

Я не смог найти простой пример о различиях между 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));
1 голос
/ 09 октября 2017

Данный код:

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);
0 голосов
/ 13 февраля 2019

Вы можете сделать это так:

var thetop = 'top';
<something>.stop().animate(
    new function() {this[thetop] = 10;}, 10
);
0 голосов
/ 13 февраля 2019

Если вы хотите, чтобы ключ объекта совпадал с именем переменной, в ES 2015 есть сокращение. Новые обозначения в ECMAScript 2015

var thetop = 10;
var obj = { thetop };
console.log(obj.thetop); // print 10
0 голосов
/ 09 октября 2018

Вы можете сделать следующее для 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
)
...