Javascript использует переменную как имя объекта

91

Я хочу использовать значение переменной для доступа к объекту.

Скажем, у меня есть объект с именем myobject.

Я хочу заполнить переменную этим именем и использовать переменную для доступа к объекту.

Пример:

var objname = 'myobject';
{objname}.value = 'value';
PeeHaa
источник

Ответы:

125

Глобальный:

myObject = { value: 0 };
anObjectName = "myObject";
this[anObjectName].value++;

console.log(this[anObjectName]);

Глобальный: v2

var anObjectName = "myObject";
this[anObjectName] = "myvalue"

console.log(myObject)

Местный: v1

(function() {
    var scope = this;

    if (scope != arguments.callee) {
        arguments.callee.call(arguments.callee);
        return false;
    }

    scope.myObject = { value: 0 };
    scope.anObjectName = "myObject";
    scope[scope.anObjectName].value++;

    console.log(scope.myObject.value);
})();

Локальный: v2

(function() {  
    var scope = this;

    scope.myObject = { value: 0 };
    scope.anObjectName = "myObject";
    scope[scope.anObjectName].value++;

    console.log(scope.myObject.value);    
}).call({});
Шаз
источник
@Shaz - оба они фактически ссылаются на одну и ту же область видимости ;-) (при условии, что они выполняются в браузере.) alert(this === window).
Шон Виейра
1
@PeeHaa - Пример Local устанавливает переменную для windowобъекта с именемobjname , которое затем ссылается через this... вы могли бы заменить windowна thisво втором примере , и все будет работать. :-)
Шон Виейра
1
@SeanVieira: Взгляните на обновленный пример. Надеюсь, теперь это работает правильно.
Shaz
1
@Shaz - arguments.calleeустарел, но, тем не менее , это очень умная реализация - и она не засоряет глобальную область видимости. +1
Шон Виейра
1
Возможно, это не загрязняет глобальную область видимости, но создает объект, который используется при каждом вызове функции. Ваша функция сохраняется objnameкак свойство самой функции. Это может не работать для рекурсивных функций. Не уверен, как это можно использовать в реальном мире.
Хуан Мендес
27

Используйте квадратные скобки вокруг имени переменной.

var objname = 'myobject';
{[objname]}.value = 'value';
Вайшали Венкатесан
источник
7
Это идеально и просто, и это должен быть главный ответ.
Брэд
5
Это вызывает исключение: SyntaxError: ожидаемое выражение, получено '.'. Это не работает; почему так много голосов?
Lovro
9

Это глобальная переменная? Если да, то они на самом деле являются частью windowобъекта, так что вы можете это сделать window[objname].value.

Если это локально для функции, я не думаю, что есть хороший способ делать то, что вы хотите.

JW.
источник
8

Объект существует в некоторой области, поэтому вы почти всегда можете получить доступ к переменной с помощью этого синтаксиса:

var objname = "myobject";
containing_scope_reference[objname].some_property = 'some value';

Единственное место, где это становится сложным, - это когда вы находитесь в закрытой области и вам нужен доступ к локальной переменной верхнего уровня. Когда у вас что-то вроде этого:

(function(){
    var some_variable = {value: 25};
    var x = "some_variable";
    console.log(this[x], window[x]); // Doesn't work
})();

Вы можете обойти это, используя evalвместо этого для доступа к текущей цепочке областей видимости ... но я не рекомендую это делать, если вы не провели много тестирования и не знаете , что это лучший способ действовать.

(function(){
    var some_variable = {value: 25};
    var x = "some_variable";
    eval(x).value = 42;
    console.log(some_variable); // Works
})();

Ваш лучший выбор должен иметь ссылку на имя в постоянно продолжающийся-к-быть-там объекта (например , thisв глобальном масштабе или частной переменной верхнего уровня в локальной области) и поставить все еще там.

Таким образом:

var my_outer_variable = {};
var outer_pointer = 'my_outer_variable';
// Reach my_outer_variable with this[outer_pointer]
// or window[outer_pointer]

(function(){
    var my_inner_scope = {'my_inner_variable': {} };
    var inner_pointer = 'my_inner_variable';
    // Reach my_inner_variable by using
    // my_inner_scope[inner_pointer]
})();
Шон Виейра
источник
7

Вы можете использовать eval:

eval(variablename + ".value = 'value'");
Мидас
источник
Не evalсчитается evil? Если нет, я мог бы использовать это. Потому что сейчас он глобальный, но я хотел переместить его в функцию для очистки.
PeeHaa
1
Лол. Если имя переменной получено из пользовательского ввода, убедитесь, что вы проверили его, чтобы он не содержал никакого JS-кода, который evalможет выполняться.
Мидас
1
На evalмой взгляд, это одно из немногих законных применений . Однако мы должны убедиться, что переменная чистая.
Леви Моррисон
2
Да это не проблема. Но взгляните на ответ от Shaz. Думаю, это более чистое решение.
Мидас
2
@PeeHaa: Если вы планируете переместить его, почему бы не переместить его в свойство известного объекта, чтобы вы могли сделать что-нибудь вроде myVar[objname].value?
JW.
6

Вы не можете сделать это в целом, за исключением области окна, где вы можете написать window[objname].value = 'value';

Нил
источник
4

Я думаю, что ответ Shaz для локальных переменных трудно понять, хотя он работает для нерекурсивных функций. Вот другой способ, который, я думаю, более понятен (но это все еще его идея, точно такое же поведение). Он также не обращается к локальным переменным динамически, а только к свойству локальной переменной.

По сути, он использует глобальную переменную (прикрепленную к объекту функции)

// Here's  a version of it that is more straight forward.
function doIt() {
    doIt.objname = {};
    var someObject = "objname";
    doIt[someObject].value = "value";    
    console.log(doIt.objname);
})();

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

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

function doIt() {
  var scope = {
     MyProp: "Hello"
  };
  var name = "MyProp";
  console.log(scope[name]);
}

См. Javascript: интерпретировать строку как ссылку на объект?

Хуан Мендес
источник
1

Если объект находится в некотором пространстве имен, т.е. Company.Module.Components.Fooвы можете использовать эту функцию:

CoffeeScript:

objByName: (name, context = window) ->
    ns = name.split "."
    func = context
    for n, i in ns
        func = func[n]
    return func

Полученные Js:

objByName: function(name, context) {
  var func, i, n, ns, _i, _len;
  if (context == null) {
    context = window;
  }
  ns = name.split(".");
  func = context;
  for (i = _i = 0, _len = ns.length; _i < _len; i = ++_i) {
    n = ns[i];
    func = func[n];
  }
  return func;
}

Затем вы можете создать новый объект или сделать что угодно. Обратите внимание на круглые скобки.

var o = new (objByName('Company.Module.Components.Foo'))
objByName('some.deeply.nested.object').value

Эта идея заимствована из аналогичного вопроса: как выполнить функцию JavaScript, когда у меня есть ее имя в виде строки

Сообщество
источник
1
let players = [];
players[something] = {};
players[something].somethingElse = 'test';
console.log(players); 

-> [что-то: {somethingElse: 'test'}];

part1cle
источник
0

При использовании окна [имя_объекта] убедитесь, что имя_объекта - это глобальные переменные. В противном случае будет работать когда-нибудь, а иногда и не получится. окно [имя объекта]. значение.

Lyon819
источник
0

Одна из проблем, с которыми я столкнулся с ответами, заключалась в том, что предполагалось, что объект был одноуровневым. Например,

const testObj = { testKey: 'testValue' }
const refString = 'testKey';
const refObj = testObj[refString];

работает нормально, но

const testObj = { testKey:
                  { level2Key: 'level2Value' }
                }
const refString = 'testKey.level2Key';
const refObj = testObj[refString];

не работает.

В итоге я создал функцию для доступа к многоуровневым объектам:

objVar(str) {
    let obj = this;
    const parts = str.split('.');
    for (let p of parts) {
        obj = obj[p];
    }
    return obj;
}

Во втором сценарии я могу передать строку этой функции, чтобы вернуть объект, который я ищу:

const testObj = { testKey:
                  { level2Key: 'level2Value' }
                }
const refString = 'testObj.testKey.level2Key';
const refObj = objVar[refString];
Митч Паркер
источник
0

Вы можете установить свойство объекта следующим образом:

var obj = {};
obj.whateverVarName = 'yourVal';
console.log(obj);

ThisisFish
источник
0

Если вы уже знаете список возможных имен переменных, попробуйте создать новый объект (iconObj), имена свойств которого совпадают с именами объектов. В приведенном ниже примере переменная iconLib будет содержать два строковых значения: «ZondIcons» или «MaterialIcons». . propertyName - это свойство объекта ZondIcons или MaterialsIcon.

   const iconObj = {
    ZondIcons,
    MaterialIcons,
  }
  const objValue = iconObj[iconLib][propertyName]
Шумер
источник
-1
var micro=[{'test':'hello'}];

var device = 'test';

console.log(micro[device]);
альфонсолаваррия
источник