Javascript sử dụng biến làm tên đối tượng


91

Tôi muốn sử dụng giá trị của một biến để truy cập một đối tượng.

Giả sử tôi có một đối tượng tên là myobject.

Tôi muốn điền vào một biến với tên này và sử dụng biến để truy cập đối tượng.

Thí dụ:

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

Câu trả lời:


125

Toàn cầu:

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

console.log(this[anObjectName]);

Toàn cầu: v2

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

console.log(myObject)

Địa phương: 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);
})();

Địa phương: v2

(function() {  
    var scope = this;

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

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

@Shaz - cả hai đều tham chiếu cùng một phạm vi thực sự ;-) (Giả sử chúng được thực thi trong một trình duyệt.) alert(this === window).
Sean Vieira

1
@PeeHaa - Ví dụ Cục bộ đặt một biến trên windowđối tượng được gọi objname, sau đó được tham chiếu qua this... bạn có thể thay thế windowcho thistrong ví dụ thứ hai và mọi thứ vẫn hoạt động. :-)
Sean Vieira

1
@SeanVieira: Hãy xem ví dụ được cập nhật. Hy vọng rằng điều này hoạt động chính xác ngay bây giờ.
Shaz

1
@Shaz - arguments.calleekhông được dùng nữa, nhưng dù sao thì đây cũng là một cách triển khai rất thông minh - nó không làm ảnh hưởng đến phạm vi toàn cầu. +1
Sean Vieira

1
Nó có thể không gây ô nhiễm phạm vi toàn cầu, nhưng nó tạo ra một đối tượng được chia sẻ bởi mọi lệnh gọi của hàm. Hàm của bạn đang giữ objnamenhư một thuộc tính của chính hàm. Nó có thể bị lỗi đối với các hàm đệ quy. Không chắc làm thế nào điều này có thể được sử dụng trong thế giới thực.
Juan Mendes

27

Sử dụng dấu ngoặc vuông xung quanh tên biến.

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

7
Điều này là hoàn hảo và đơn giản và nên là câu trả lời hàng đầu.
Brad

5
Điều này ném ra một ngoại lệ: SyntaxError: biểu thức mong đợi, đã nhận '.'. Nó không hoạt động; tại sao rất nhiều ủng hộ?
Lovro

9

Nó có phải là một biến toàn cục không? Nếu vậy, đây thực sự là một phần của windowđối tượng, vì vậy bạn có thể làm window[objname].value.

Nếu nó là cục bộ cho một chức năng, tôi không nghĩ có cách tốt để làm những gì bạn muốn.


8

Đối tượng tồn tại trong một số phạm vi, vì vậy bạn hầu như luôn có thể truy cập biến thông qua cú pháp sau:

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

Nơi duy nhất mà điều này trở nên phức tạp là khi bạn ở trong một phạm vi đóng và bạn muốn truy cập vào một biến cục bộ cấp cao nhất. Khi bạn có một cái gì đó như thế này:

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

Thay vào đó, bạn có thể giải quyết vấn đề đó bằng cách sử dụng evalđể truy cập chuỗi phạm vi hiện tại ... nhưng tôi không khuyên bạn nên sử dụng nó trừ khi bạn đã thực hiện nhiều thử nghiệm và bạn biết rằng đó là cách tốt nhất để tiếp tục mọi thứ.

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

Đặt cược tốt nhất của bạn là có một tham chiếu đến tên trong một đối tượng luôn-sẽ-tồn-tại (như thistrong phạm vi toàn cục hoặc một biến cấp cao nhất riêng trong phạm vi cục bộ) và đặt mọi thứ khác vào đó.

Như vậy:

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

Bạn có thể sử dụng eval:

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

Không được evalcoi là evil? Nếu không, tôi có thể sử dụng nó. Bởi vì nó là toàn cầu ngay bây giờ nhưng tôi muốn chuyển nó thành một chức năng để dọn dẹp mọi thứ.
PeeHaa

1
Cười lớn. Nếu tên biến đến từ đầu vào của người dùng, hãy đảm bảo bạn xác thực nó để nó không chứa bất kỳ mã JS nào evalcó thể thực thi.
Midas

1
Đây là một trong số ít cách sử dụng hợp pháp eval, theo ý kiến ​​của tôi. Tuy nhiên, chúng ta phải đảm bảo rằng biến sạch.
Levi Morrison

2
Vâng, nó không thực sự là một vấn đề. Nhưng hãy xem câu trả lời từ Shaz. Tôi nghĩ đó là một giải pháp sạch sẽ hơn.
Midas

2
@PeeHaa: Nếu bạn đang cân nhắc việc di chuyển nó, tại sao không chuyển nó vào một thuộc tính của một đối tượng đã biết, để bạn có thể làm gì đó như thế myVar[objname].valuenào?
JW.

6

Nói chung, bạn không thể làm điều này, ngoại trừ ở phạm vi cửa sổ, nơi bạn có thể viết window[objname].value = 'value';


4

Tôi nghĩ rằng câu trả lời của Shaz cho các biến cục bộ là khó hiểu, mặc dù nó hoạt động cho các hàm không đệ quy. Đây là một cách khác mà tôi nghĩ nó rõ ràng hơn (nhưng đó vẫn là ý tưởng của anh ấy, hành vi giống hệt nhau). Nó cũng không truy cập động các biến cục bộ, chỉ là thuộc tính của biến cục bộ.

Về cơ bản, nó sử dụng một biến toàn cục (được đính kèm với đối tượng hàm)

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

Về cơ bản, điều này giống với việc tạo toàn cục để lưu trữ biến, vì vậy bạn có thể truy cập nó như một thuộc tính. Tạo ra một toàn cầu để làm điều này là một hack.

Đây là một thủ thuật gọn gàng hơn không tạo biến toàn cục, thay vào đó nó sử dụng biến cục bộ.

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

Xem Javascript: diễn giải chuỗi dưới dạng tham chiếu đối tượng?


1

Nếu đối tượng nằm trong một số không gian tên tức là. Company.Module.Components.Foobạn có thể sử dụng chức năng này:

CoffeeScript:

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

Kết quả 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;
}

Sau đó, bạn có thể tạo một đối tượng mới hoặc làm bất cứ điều gì. Lưu ý các dấu ngoặc đơn thông qua.

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

Ý tưởng này được mượn từ câu hỏi tương tự: Làm thế nào để thực thi một hàm JavaScript khi tôi có tên của nó là một chuỗi


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

-> [something: {somethingElse: 'test'}];


0

Khi sử dụng window [objname], hãy đảm bảo rằng objname là các biến toàn cục. Nếu không, đôi khi sẽ hoạt động, và đôi khi thất bại. window [objname] .value.


0

Một trong những thách thức mà tôi gặp phải với câu trả lời là nó giả định rằng đối tượng là một cấp duy nhất. Ví dụ,

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

hoạt động tốt, nhưng

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

không hoạt động.

Cuối cùng, những gì tôi đã làm là xây dựng một chức năng để truy cập các đối tượng đa cấp:

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

Sau đó, trong tình huống thứ hai, tôi có thể truyền chuỗi vào hàm này để lấy lại đối tượng mà tôi đang tìm kiếm:

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

0

Bạn có thể đặt thuộc tính đối tượng theo cách này:

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


0

Nếu bạn đã biết danh sách các tên biến thể có thể có thì hãy thử tạo một Đối tượng mới (iconObj) có tên thuộc tính giống với tên đối tượng, Ở đây trong ví dụ dưới đây, biến iconLib sẽ chứa hai giá trị chuỗi, 'ZondIcons' hoặc 'MaterialIcons' . propertyName là thuộc tính của ZondIcons hoặc đối tượng MaterialsIcon.

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.