Có cách nào để sử dụng kiểu số làm khóa đối tượng không?


97

Có vẻ như khi tôi sử dụng kiểu số làm tên khóa trong một đối tượng, nó luôn được chuyển đổi thành chuỗi. Có cách nào để thực sự có được nó để lưu trữ dưới dạng số không? Việc đánh máy bình thường dường như không hoạt động.

Thí dụ:

var userId = 1;
console.log( typeof userId ); // number
myObject[userId] = 'a value';
console.dir(myObject);

Đầu ra Dir:

{
    '1': 'a value'
}

Điều tôi muốn là:

{
    1: 'a value'
}

Khuyên bảo?


Câu trả lời:


109

Không, điều này là không thể. Khóa sẽ luôn được chuyển đổi thành một chuỗi. Xem tài liệu về Người tiếp cận tài sản

Tên thuộc tính phải là chuỗi. Điều này có nghĩa là các đối tượng không phải chuỗi không thể được sử dụng làm khóa trong đối tượng. Bất kỳ đối tượng không phải chuỗi nào, bao gồm một số, được đánh máy thành chuỗi thông qua phương thức toString.

> var foo = {}
undefined

> foo[23213] = 'swag'
'swag'

> foo
{ '23213': 'swag' }

> typeof(Object.keys(foo)[0])
'string'

1
Đó là khá chủ quan. Như William đã lưu ý, thay vào đó, đối với các khóa số nguyên, bạn có thể sử dụng một mảng. Hầu hết các công cụ JS có thể sử dụng các mảng thưa thớt phía sau hậu trường.
Matthew Flaschen

7
Ngay cả trong một mảng, tất cả các tên thuộc tính đều được chuyển đổi thành chuỗi.
Tim Down

2
@ Roamer-1888: Không phải đâu. Sự khác biệt duy nhất là việc gán thuộc tính số cho một mảng sẽ ảnh hưởng đến thuộc tính của mảng length.
Tim Down

2
@TimDown, và những gì tôi đang nói là bạn đã sai. "Đặt thuộc tính số trên Mảng có thể ảnh hưởng đến thuộc tính length" là một tuyên bố không chính xác. Javascript Các thuộc tính của mảng hoàn toàn độc lập với các phần tử của Mảng. Điều khiến mọi người bối rối là cú pháp liên kết, ví dụ myArray["1"] = foo, dường như đang thiết lập một thuộc tính, trong khi nó thực sự đặt một phần tử mảng, nhưng chỉ vì "1" là biểu diễn chuỗi của một số nguyên, điều này hoàn toàn vô nghĩa về mặt ngôn ngữ - nhưng đó là Javascript.
Roamer-1888

4
@ Roamer-1888: "Các thuộc tính của mảng trong Javascript hoàn toàn độc lập với các phần tử của mảng" là một phát biểu không chính xác. myArray["1"] = fookhông chỉ có vẻ là thiết lập một thuộc tính, mà trên thực tế, nó là thiết lập một thuộc tính (với khóa "1") theo mọi nghĩa của định nghĩa thuộc tính. Ví dụ: myArray.hasOwnProperty("1")sản lượng true. Về mặt ngữ nghĩa, thuộc tính này cũng có thể được coi là một "phần tử" do có một khóa số, nhưng không có gì khác để phân biệt một "phần tử" mảng với một thuộc tính mảng. Đọc thông số kỹ thuật. Nếu bạn vẫn không đồng ý, vui lòng trích dẫn nguồn của bạn.
Hans

23

Trong một đối tượng, không, nhưng tôi thấy Bản đồ cực kỳ hữu ích cho ứng dụng này. Đây là nơi tôi đã sử dụng nó cho các phím số, một sự kiện dựa trên khóa.

onKeydown(e) {
  const { toggleSidebar, next, previous } = this.props;

  const keyMapping = new Map([
    [ 83, toggleSidebar ],  // user presses the s button
    [ 37, next          ],  // user presses the right arrow
    [ 39, previous      ]   // user presses the left arrow
  ]);

  if (keyMapping.has(e.which)) {
    e.preventDefault();
    keyMapping.get(e.which)();
  }
}

1
101 mục Ludumdare thanh lịch ! +1
kaiser

11

Có vẻ như theo thiết kế trong ECMA-262-5:

Loại Định danh thuộc tính được sử dụng để liên kết tên thuộc tính với Trình mô tả thuộc tính. Các giá trị của loại Định danh thuộc tính là các cặp của biểu mẫu (tên, bộ mô tả), trong đó tên là một Chuỗi và bộ mô tả là giá trị Bộ mô tả thuộc tính.

Tuy nhiên, tôi không thấy thông số kỹ thuật cụ thể cho nó trong ECMA-262-3. Bất kể, tôi sẽ không cố gắng sử dụng các chuỗi không phải là tên thuộc tính.


2

Chúng ta có cần một cái gì đó như thế này không?

var userId = 1;var myObject ={};
console.log( typeof userId ); // number
myObject[userId] = 'a value';
console.dir(myObject);

Bảng điều khiển: Đối tượng

1: "một giá trị"


0

Tôi nghĩ bạn có thể làm như sau nếu bạn muốn sử dụng điều trên để truy cập nó như một số, tôi đã làm như vậy và đã hoạt động.

var myObj = {"0":"a","1":"b","CNT":2};
$.each(myObj,function(key,value){
     if(isNaN(parseInt(key))){
          return true; //continue;
     }
     //Code to perform operation
}

Điều này chỉ hoạt động khi khóa không bắt đầu bằng và ký tự số, nếu không nó sẽ được chuyển đổi thành số. Xem ví dụ sau:

parseInt("45kjghk") === 45

Tôi đã sử dụng jQuery ở đây


Đã cập nhật:

var myObj = {"0":"a","1":"b","CNT":2};
$.each(myObj,function(key,value){
     if(isNaN(parseInt(key)) || (key.length !== parseInt(key).toString().length) ){
          return true; //continue;
     }
     //Code to perform operation
}

Nó có thể khắc phục vấn đề trên. Vui lòng đề xuất tốt hơn nếu có và vấn đề với câu trả lời này nếu có.


-3

Trong JavaScript, chuỗi số và số có thể hoán đổi cho nhau, vì vậy

myObject[1] == myObject['1']

Nếu bạn thực sự muốn số là khóa cho một đối tượng, bạn có thể muốn một mảng (tức là được tạo bằng new Array()hoặc []).


2
Cảm ơn bạn đã trả lời nhưng điều này không hoàn toàn chính xác. Một số sẽ chỉ trả về dưới dạng 'số' từ một typeof và ngược lại với một chuỗi.
Spot

@william 'chuỗi số và số có thể hoán đổi cho nhau' chỉ đơn giản là không đúng. Numbers là Numbers và Strings là Strings. Xem Object.prototype.toString.call(someObject)Vấn đề là bạn không thể sử dụng Numbers làm khóa.
mikemaccana
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.