Javascript używa zmiennej jako nazwy obiektu


91

Chcę użyć wartości zmiennej, aby uzyskać dostęp do obiektu.

Powiedzmy, że mam obiekt o nazwie myobject.

Chcę wypełnić zmienną o tej nazwie i użyć zmiennej, aby uzyskać dostęp do obiektu.

Przykład:

var objname = 'myobject';
{objname}.value = 'value';

Odpowiedzi:


125

Światowy:

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

console.log(this[anObjectName]);

Globalny: v2

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

console.log(myObject)

Lokalny: 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);
})();

Lokalny: v2

(function() {  
    var scope = this;

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

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

@Shaz - oba odnoszą się w rzeczywistości do tego samego zakresu ;-) (Zakładając, że są wykonywane w przeglądarce) alert(this === window).
Sean Vieira

1
@PeeHaa - The Local przykład ustawia zmienną na windowobiekcie o nazwie objname, która jest następnie odwołanie przez this... można podstawić windowna thisw drugim przykładzie i wszystko będzie nadal działać. :-)
Sean Vieira

1
@SeanVieira: spójrz na zaktualizowany przykład. Mam nadzieję, że teraz działa to poprawnie.
Shaz

1
@Shaz - arguments.calleejest przestarzały, ale mimo to jest to bardzo sprytna implementacja - i nie zaśmieca globalnego zasięgu. +1
Sean Vieira

1
Może nie zanieczyszcza zasięgu globalnego, ale tworzy obiekt, który jest współdzielony przez każde wywołanie funkcji. Twoja funkcja zachowuje objnamewłasność samej funkcji. Może się nie powieść w przypadku funkcji rekurencyjnych. Nie wiem, jak można to wykorzystać w prawdziwym świecie.
Juan Mendes

27

Użyj nawiasu kwadratowego wokół nazwy zmiennej.

var objname = 'myobject';
{[objname]}.value = 'value';

7
To jest doskonałe i proste i powinno być najlepszą odpowiedzią.
Brad

5
Spowoduje to zgłoszenie wyjątku: SyntaxError: oczekiwane wyrażenie, otrzymano „.”. To nie działa; dlaczego tak wiele głosów za?
Lovro

9

Czy jest to zmienna globalna? Jeśli tak, to w rzeczywistości są one częścią windowobiektu, więc możesz to zrobićwindow[objname].value .

Jeśli jest lokalny dla funkcji, nie sądzę, aby był dobry sposób na robienie tego, co chcesz.


8

Obiekt istnieje w pewnym zakresie, więc prawie zawsze możesz uzyskać dostęp do zmiennej za pomocą następującej składni:

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

Jedynym miejscem, w którym staje się to trudne, jest sytuacja, gdy znajdujesz się w zakresie zamkniętym i chcesz uzyskać dostęp do zmiennej lokalnej najwyższego poziomu. Kiedy masz coś takiego:

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

Możesz to obejść, używając evalzamiast tego dostępu do bieżącego łańcucha zasięgu ... ale nie polecam tego, chyba że wykonałeś wiele testów i wiesz , że to najlepszy sposób na załatwienie sprawy.

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

Twój najlepszy zakład ma mieć odniesienie do nazwy na zawsze będzie-to-be-tam obiektu (jak thisw zasięgu globalnym lub prywatnej zmiennej najwyższego poziomu w zakresie lokalnego) i umieścić wszystkiego innego tam.

A zatem:

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

Możesz użyć eval:

eval(variablename + ".value = 'value'");

Nie jest evalbrane pod uwagę evil? Jeśli nie, mogę go użyć. Ponieważ jest teraz globalny, ale chciałem przenieść go do funkcji porządkującej rzeczy.
PeeHaa

1
Lol. Jeśli nazwa zmiennej pochodzi z danych wprowadzonych przez użytkownika, upewnij się, że została ona zweryfikowana, aby nie zawierała żadnego kodu JS, który evalmożna wykonać.
Midas

1
evalMoim zdaniem jest to jedno z nielicznych legalnych zastosowań . Musimy jednak upewnić się, że zmienna jest czysta.
Levi Morrison

2
Tak, to naprawdę nie jest problem. Ale spójrz na odpowiedź od Shaz. Myślę, że to bardziej przejrzyste rozwiązanie.
Midas

2
@PeeHaa: Jeśli zastanawiasz się nad przeniesieniem go, dlaczego nie przenieść go do właściwości znanego obiektu, abyś mógł zrobić coś takiego myVar[objname].value?
JW.

6

Nie możesz tego zrobić w ogóle, z wyjątkiem zakresu okna, gdzie możesz pisać window[objname].value = 'value';


4

Myślę, że odpowiedź Shaza na zmienne lokalne jest trudna do zrozumienia, chociaż działa w przypadku funkcji nierekurencyjnych. Oto inny sposób, który moim zdaniem jest jaśniejszy (ale to wciąż jego pomysł, dokładnie to samo zachowanie). Nie jest to również dynamiczny dostęp do zmiennych lokalnych, a jedynie właściwość zmiennej lokalnej.

Zasadniczo używa zmiennej globalnej (dołączonej do obiektu funkcji)

// 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);
})();

Co jest zasadniczo tym samym, co tworzenie globalnej do przechowywania zmiennej, aby można było uzyskać do niej dostęp jako właściwość. Stworzenie globalnego, aby to zrobić, to taki hack.

Oto bardziej przejrzysty hack, który nie tworzy zmiennych globalnych, zamiast tego używa zmiennej lokalnej.

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

Zobacz Javascript: interpretować ciąg jako odniesienie do obiektu?


1

Jeśli obiekt znajduje się w jakiejś przestrzeni nazw, tj. Company.Module.Components.Foomożesz użyć tej funkcji:

CoffeeScript:

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

Wynikowe 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;
}

Następnie możesz stworzyć nowy obiekt lub zrobić cokolwiek. Zwróć uwagę na nawiasy do.

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

Pomysł ten jest zapożyczony z podobnego pytania: jak wykonać funkcję JavaScript, gdy mam jej nazwę jako ciąg


1
let players = [];
players[something] = {};
players[something].somethingElse = 'test';
console.log(players); 

-> [coś: {somethingElse: 'test'}];


0

Używając okna [nazwa_obiektu], upewnij się, że nazwa_obiektu to zmienne globalne. W przeciwnym razie kiedyś zadziała i czasami zawiedzie. okno [nazwa_obiektu] .value.


0

Jednym z wyzwań, jakie miałem z odpowiedziami, było założenie, że obiekt jest jednopoziomowy. Na przykład,

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

działa dobrze, ale

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

nie działa.

Skończyło się na tym, że zbudowałem funkcję dostępu do obiektów wielopoziomowych:

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

W drugim scenariuszu mogę zatem przekazać ciąg znaków do tej funkcji, aby odzyskać obiekt, którego szukam:

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

0

Możesz ustawić właściwość obiektów w ten sposób:

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


0

Jeśli znasz już listę możliwych nazw zmiennych, spróbuj utworzyć nowy obiekt (iconObj), którego nazwa właściwości jest taka sama jak nazwy obiektów. W poniższym przykładzie zmienna iconLib będzie zawierać dwie wartości ciągów, „ZondIcons” lub „MaterialIcons” . propertyName jest właściwością obiektu ZondIcons lub MaterialsIcon.

   const iconObj = {
    ZondIcons,
    MaterialIcons,
  }
  const objValue = iconObj[iconLib][propertyName]

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.