มีวิธีใดบ้างในการใช้ประเภทตัวเลขเป็นคีย์ออบเจ็กต์


110

ดูเหมือนว่าเมื่อฉันใช้ประเภทตัวเลขเป็นชื่อคีย์ในออบเจ็กต์มันจะถูกแปลงเป็นสตริงเสมอ จะมีการเก็บเป็นตัวเลขจริงหรือไม่? การพิมพ์ปกติดูเหมือนจะไม่ทำงาน

ตัวอย่าง:

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

เอาต์พุต Dir:

{
    '1': 'a value'
}

สิ่งที่ฉันต้องการคือ:

{
    1: 'a value'
}

คำแนะนำ?


ดูความคิดเห็นนี้ด้วย - stackoverflow.com/questions/3633362/…
Manohar Reddy Poreddy

คำตอบ:


118

ไม่นี่เป็นไปไม่ได้ คีย์จะถูกแปลงเป็นสตริงเสมอ ดูเอกสาร Property Accessor

ชื่อคุณสมบัติต้องเป็นสตริง ซึ่งหมายความว่าไม่สามารถใช้อ็อบเจกต์ที่ไม่ใช่สตริงเป็นคีย์ในออบเจ็กต์ได้ อ็อบเจ็กต์ที่ไม่ใช่สตริงใด ๆ รวมถึงตัวเลขจะถูกพิมพ์ลงในสตริงโดยใช้เมธอด toString

> var foo = {}
undefined

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

> foo
{ '23213': 'swag' }

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

1
นั่นค่อนข้างเป็นเรื่องส่วนตัว ดังที่วิลเลียมกล่าวไว้สำหรับคีย์จำนวนเต็มคุณสามารถใช้อาร์เรย์แทนได้ เอ็นจิ้น JS ส่วนใหญ่สามารถใช้อาร์เรย์แบบเบาบางเบื้องหลังได้
Matthew Flaschen

8
แม้ในอาร์เรย์ชื่อคุณสมบัติทั้งหมดจะถูกแปลงเป็นสตริง
Tim Down

2
@ Roamer-1888: ไม่มันไม่ใช่ ข้อแตกต่างเพียงอย่างเดียวคือการกำหนดคุณสมบัติตัวเลขให้กับอาร์เรย์มีผลต่อlengthคุณสมบัติของอาร์เรย์
Tim Down

2
@ TimDown และสิ่งที่ฉันกำลังพูดคือคุณคิดผิด "การตั้งค่าคุณสมบัติตัวเลขบนอาร์เรย์อาจส่งผลต่อคุณสมบัติความยาว" เป็นคำสั่งที่ไม่ถูกต้อง คุณสมบัติ Javascript Array เป็นอิสระจากองค์ประกอบ Array อย่างสมบูรณ์ สิ่งที่สร้างความสับสนให้คนที่เชื่อมโยงไวยากรณ์เช่นmyArray["1"] = foo, จะปรากฏขึ้นที่จะได้รับการตั้งค่าคุณสมบัติในขณะที่มันเป็นจริงชุดองค์ประกอบอาร์เรย์ แต่เพียงเพราะ "1" เป็นตัวแทนสตริงของจำนวนเต็มซึ่งเป็นเรื่องไร้สาระที่สมบูรณ์ภาษา - แต่ที่ Javascript
Roamer-1888

4
@ Roamer-1888: "คุณสมบัติของ Javascript Array ไม่ขึ้นอยู่กับองค์ประกอบ Array" เป็นข้อความที่ไม่ถูกต้อง myArray["1"] = fooไม่ได้ดูเหมือนเป็นการตั้งค่าคุณสมบัติเท่านั้น แต่ในความเป็นจริงแล้วการตั้งค่าคุณสมบัติ (ด้วยคีย์ "1") ในทุกแง่มุมของคำจำกัดความของคุณสมบัติ เช่นอัตราผลตอบแทนmyArray.hasOwnProperty("1") trueในทางความหมายคุณสมบัตินี้ยังถือได้ว่าเป็น "องค์ประกอบ" โดยอาศัยการมีคีย์ตัวเลข แต่ไม่มีอะไรเพิ่มเติมที่จะแยก "องค์ประกอบ" อาร์เรย์ออกจากคุณสมบัติอาร์เรย์ อ่านข้อมูลจำเพาะ หากคุณยังไม่เห็นด้วยโปรดอ้างอิงแหล่งที่มาของคุณ
Hans

28

ในวัตถุไม่ แต่ฉันพบว่าแผนที่มีประโยชน์อย่างยิ่งสำหรับแอปพลิเคชันนี้ นี่คือที่ที่ฉันใช้สำหรับคีย์ตัวเลขซึ่งเป็นเหตุการณ์ที่ใช้คีย์

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
รายการLudumdareสุดหรู 101 รายการ! +1
kaiser

11

ดูเหมือนจะเป็นไปตามการออกแบบใน ECMA-262-5:

ประเภท Property Identifier ใช้เพื่อเชื่อมโยงชื่อคุณสมบัติกับ Property Descriptor ค่าของชนิด Property Identifier คือคู่ของฟอร์ม (name, descriptor) โดยที่ name คือ String และ descriptor คือค่า Property Descriptor

อย่างไรก็ตามฉันไม่เห็นข้อกำหนดที่ชัดเจนสำหรับ ECMA-262-3 ไม่ว่าฉันจะไม่พยายามใช้ที่ไม่ใช่สตริงเป็นชื่อคุณสมบัติ



0

ฉันคิดว่าคุณสามารถทำสิ่งต่อไปนี้ได้หากคุณต้องการใช้สิ่งข้างต้นเพื่อเข้าถึงมันเช่นเป็นตัวเลขฉันก็ทำแบบเดียวกันและได้ผล

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

จะใช้ได้เฉพาะเมื่อคีย์ไม่ได้ขึ้นต้นด้วยและอักขระตัวเลขมิฉะนั้นจะถูกแปลงเป็นตัวเลข ดูตัวอย่างต่อไปนี้:

parseInt("45kjghk") === 45

ฉันใช้ jQuery ที่นี่


อัปเดต:

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
}

มันอาจเอาชนะปัญหาข้างต้นได้ โปรดแนะนำให้ดีขึ้นหากมีและมีปัญหากับคำตอบนี้หากมี


0

นี่คือวิธีแก้ปัญหา โปรดบอกการตั้งค่าสภาพแวดล้อมหากไม่ได้ผล

const screens = {
    "768": "large",
    "200": "small"
}

const keys = Object.keys(screens).map(key => parseInt(key))
                                         // OR Number(key)

console.log(keys) // Output [200, 768]

0

ต่อ Mozilla: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax[Spread syntax] 1

let obj1 = { foo: 'bar', x: 42 };
let obj2 = { foo: 'baz', y: 13 };
const merge = ( ...objects ) => ( { ...objects } );

let mergedObj1 = merge (obj1, obj2);
// Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } }

let mergedObj2 = merge ({}, obj1, obj2);
// Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }

เพียงสั่งของก่อนถึงมือคุณก็จะได้ผลลัพธ์ที่คุณต้องการ

ดังนั้นสำหรับกรณีของคุณ:

const merge = (...objects) => ({...objects});

//An object with numeric keys
const values = ["a value", "another value", "and another value"];
        
let merged = merge(...values);

console.log(merged);


-3

ใน JavaScript สตริงตัวเลขและตัวเลขสามารถใช้แทนกันได้

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

ถ้าคุณต้องการให้ตัวเลขเป็นกุญแจสำคัญสำหรับวัตถุคุณอาจต้องการอาร์เรย์ (เช่นสร้างด้วยnew Array()หรือ[])


2
ขอบคุณสำหรับการตอบกลับ แต่สิ่งนี้ไม่ถูกต้องทั้งหมด ตัวเลขจะส่งคืนเป็น 'ตัวเลข' จาก typeof เท่านั้นและในทางกลับกันด้วยสตริง
ปอต

@william 'สตริงตัวเลขและตัวเลขใช้แทนกันได้' นั้นไม่ถูกต้อง Numbers คือตัวเลขและสตริงคือสตริง ดูObject.prototype.toString.call(someObject)ปัญหาคือคุณไม่สามารถใช้ Numbers เป็นกุญแจได้
mikemaccana
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.