Tìm kiếm trang web

Làm thế nào để sử dụng một biến làm khóa trong literal đối tượng JavaScript?


Tại sao cái sau lại hoạt động?

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

Trong khi điều này không hoạt động:

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

Để làm rõ hơn: Hiện tại tôi không thể truyền một thuộc tính CSS vào hàm animate dưới dạng biến.

Câu trả lời #1

{ thetop : 10 } là một literal đối tượng hợp lệ. Mã này sẽ tạo ra một đối tượng với một thuộc tính có tên thetop có giá trị là 10. Cả hai điều sau đều giống nhau:

obj = { thetop : 10 };
obj = { "thetop" : 10 };

Trong ES5 và các phiên bản trước đó, bạn không thể sử dụng một biến làm tên thuộc tính bên trong một object literal. Lựa chọn duy nhất của bạn là thực hiện như sau:

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 định nghĩa ComputedPropertyName như một phần của ngữ pháp cho các literal đối tượng, điều này cho phép bạn viết mã như sau:

var thetop = "top",
    obj = { [thetop]: 10 };

console.log(obj.top); // -> 10

Bạn có thể sử dụng cú pháp mới này trong các phiên bản mới nhất của mỗi trình duyệt chính.

Câu trả lời #2

Với ECMAScript 2015, bạn bây giờ có thể làm điều đó trực tiếp trong khai báo đối tượng với ký hiệu dấu ngoặc vuông:

var obj = {
  [key]: value
}

Trong đó key có thể là bất kỳ loại biểu thức nào (ví dụ: một biến) trả về một giá trị.

Vậy ở đây mã của bạn sẽ trông như sau:

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

Nơi thetop sẽ được đánh giá trước khi được sử dụng làm khóa.

Câu trả lời #3

Trích dẫn ES5 nói rằng nó không nên hoạt động

Lưu ý: các quy tắc đã thay đổi cho ES6: https://stackoverflow.com/a/2274327/895245

Thông số kỹ thuật: http://www.ecma-international.org/ecma-262/5.1/#sec-11.1.5

Tên thuộc tính :

  • IdentifierName
  • StringLiteral
  • NumericLiteral

[...]

Phần sản xuất PropertyName : IdentifierName được đánh giá như sau:

  1. Trả về giá trị Chuỗi chứa cùng một chuỗi ký tự với IdentifierName.

Phần sản xuất PropertyName : StringLiteral được đánh giá như sau:

  1. Trả về SV [Giá trị chuỗi] của StringLiteral.

Khai báo sản xuất PropertyName : NumericLiteral được đánh giá như sau:

  1. Hãy để nbr là kết quả của việc hình thành giá trị của NumericLiteral.
  2. Trả về ToString(nbr).

Điều này có nghĩa là:

  • { theTop : 10 } giống hệt với { 'theTop' : 10 }

    Thuộc tính PropertyName theTop là một IdentifierName, vì vậy nó được chuyển đổi thành giá trị chuỗi 'theTop', chính là giá trị chuỗi của 'theTop'.

  • Không thể viết bộ khởi tạo đối tượng (biểu thức chữ) với các khóa biến.

    Ba lựa chọn duy nhất là IdentifierName (mở rộng thành hằng chuỗi), StringLiteral, và NumericLiteral (cũng mở rộng thành một chuỗi).

Câu trả lời #4

ES6/2020

Nếu bạn đang cố gắng đẩy dữ liệu vào một đối tượng bằng cách sử dụng "key:value" từ bất kỳ nguồn nào khác, bạn có thể sử dụng thứ gì đó như sau:

let obj = {}
let key = "foo"
let value = "bar"

obj[`${key}`] = value

// A `console.log(obj)` would return:
// {foo: "bar}

// A `typeof obj` would return:
// "object"

Hy vọng điều này sẽ giúp được ai đó :)

Bài viết liên quan