การนับจำนวนหมายถึงอะไร


151

ฉันถูกนำไป MDN ของหน้า for..inเมื่อมันกล่าวว่า "for..in iterates กว่าคุณสมบัติที่นับของวัตถุ."

จากนั้นฉันไปที่หน้าEnumerability และเป็นเจ้าของคุณสมบัติซึ่งกล่าวว่า "คุณสมบัติที่นับได้คือคุณสมบัติที่สามารถวนซ้ำโดย for..in loop"

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


คุณเข้าใจในสิ่งที่for-inทำ?

จากคำตอบที่ผมมีที่ for..in ช่วยให้ทุกคุณสมบัตินับของวัตถุจะสามารถใช้ได้สำหรับใช้กับงบ
แพทริค

6
ความหมายที่ง่ายที่สุดคือ: ไม่ว่าทรัพย์สินจะถูกสร้างโดยfor inลูปหรือไม่ (สำหรับผู้ที่ไม่ต้องการทราบรายละเอียดหรือเพียงแค่ไม่สนใจ))
Tomasz Racia

คำตอบ:


158

คุณสมบัติที่นับได้คือคุณสมบัติที่สามารถรวมอยู่ในและเยี่ยมชมได้ในระหว่างการfor..inวนรอบ (หรือการวนซ้ำของคุณสมบัติที่คล้ายกันObject.keys())

ถ้าคุณสมบัติไม่ถูกระบุว่านับได้ลูปจะไม่สนใจว่ามันอยู่ในวัตถุ

var obj = { key: 'val' };

console.log('toString' in obj); // true
console.log(typeof obj.toString); // "function"

for (var key in obj)
    console.log(key); // "key"

คุณสมบัติถูกระบุว่าเป็นนับหรือไม่ได้โดยตัวของมันเองแอตทริบิวต์[[Enumerable]] คุณสามารถดูสิ่งนี้เป็นส่วนหนึ่งของตัวบอกคุณสมบัติ :

var descriptor = Object.getOwnPropertyDescriptor({ bar: 1 }, 'bar');

console.log(descriptor.enumerable); // true
console.log(descriptor.value);      // 1

console.log(descriptor);
// { value: 1, writable: true, enumerable: true, configurable: true }

for..inห่วงแล้ว iterates ผ่านชื่อคุณสมบัติของวัตถุ

var foo = { bar: 1, baz: 2};

for (var prop in foo)
    console.log(prop); // outputs 'bar' and 'baz'

แต่จะประเมินเฉพาะคำสั่งของ - console.log(prop);ในกรณีนี้ - สำหรับคุณสมบัติของผู้ที่มีแอตทริบิวต์[[Enumerable]]true

เงื่อนไขนี้เกิดขึ้นเนื่องจากวัตถุมีคุณสมบัติมากมายโดยเฉพาะจากการสืบทอด :

console.log(Object.getOwnPropertyNames(Object.prototype));
// ["constructor", "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", /* etc. */]

แต่ละคุณสมบัติเหล่านี้ยังคงมีอยู่บนวัตถุ :

console.log('constructor' in foo); // true
console.log('toString' in foo);    // true
// etc.

แต่พวกเขาถูกข้ามโดยfor..inวงเพราะพวกเขาไม่นับ

var descriptor = Object.getOwnPropertyDescriptor(Object.prototype, 'constructor');

console.log(descriptor.enumerable); // false

ดังนั้นคุณสมบัติคอนสตรัคชันนั้นไม่สามารถแจกแจงได้เพราะมันไม่ปรากฏในลูป for..in ในขณะที่ชื่อของคุณสมบัติเช่นแถบหรือ Baz นับได้เพราะคุณสามารถ console.log แต่ละคนจากวัตถุ?
แพทริค

5
สิ่งนี้ไม่ถูกต้องทั้งหมด: But, they are skipped (or not counted) by the for..in loop because they are not enumerable. Object.prototypeในความเป็นจริงคุณสมบัติที่ถูกละเว้นเพราะพวกเขาขึ้นห่วงโซ่ต้นแบบไม่ได้เพราะพวกเขาจะไม่นับ ไม่ใช่getOwnPropertyNames()หรือkeys()แสดงคุณสมบัติที่ไม่ใช่ของตัวเอง ในฐานะที่เป็นหมายเหตุด้านข้างมันเป็นความจริงที่คุณสมบัติในตัวจำนวนมากไม่สามารถนับได้และจะไม่แสดงด้วยkeys()แต่คุณจะต้องเขียนโค้ดเพิ่มเติมหากคุณต้องการสำรวจสายโซ่ต้นแบบ
แมกนัส

แท้จริงหมายถึงนับได้นับได้
Christian Matthew

49

หากคุณสร้างวัตถุผ่านmyObj = {foo: 'bar'}หรือบางสิ่งบางอย่างในบริเวณนั้นคุณสมบัติทั้งหมดจะนับได้ ดังนั้นคำถามที่ง่ายกว่าในการถามคืออะไรที่นับไม่ได้? วัตถุบางอย่างมีคุณสมบัติที่ไม่นับจำนวนตัวอย่างเช่นถ้าคุณเรียกใช้Object.getOwnPropertyNames([])(ซึ่งส่งกลับอาร์เรย์ของคุณสมบัติทั้งหมดที่นับได้หรือไม่บน []) มันจะส่งคืน['length']ซึ่งรวมถึงคุณสมบัติที่ไม่นับได้ของอาร์เรย์ 'ความยาว' .

คุณสามารถสร้างคุณสมบัติที่ไม่นับได้ด้วยตนเองโดยโทรObject.defineProperty:

var person = { age: 18 };
Object.defineProperty(person, 'name', { value: 'Joshua', enumerable: false });

person.name; // 'Joshua'
for (prop in person) {
  console.log(prop);
}; // 'age'

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

และมีคำถามเกี่ยวกับสแต็คโอเวอร์โฟลว์เกี่ยวกับสาเหตุที่คุณต้องการทำให้คุณสมบัติไม่สามารถนับได้


หืมทั้ง upvotes และ downvotes แน่นอนถ้ามีอะไรเกี่ยวกับคำตอบนี้ที่คุ้มค่าการลงโปรดเพิ่มความคิดเห็นที่นี่
carpeliam

1
คำตอบอื่นเขียนสิ่งนี้: var o = {}; o ['foo'] = 0; // นับจำนวนได้ปกติ Object.defineProperty (o, 'bar', {value: 1}); // ไม่ใช่ตัวเลข, แปลกทำไมเพิ่มอย่างชัดเจนถึงนับได้: false?
แพทริค

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

@carpeliam ขอบคุณสำหรับคำอธิบายที่สั้นและชัดเจนนี้ฉันไม่สามารถรับคำตอบได้จนกว่าฉันจะผ่านคุณ: D
sandeepKumar

37

มันน่าเบื่อมากกว่าสิ่งที่ควรมองเห็น

มีคุณสมบัติอย่างแท้จริงในคุณสมบัติทั้งหมดที่เรียกว่า "นับได้" เมื่อมีการตั้งค่าเป็นเท็จfor..inวิธีการจะข้ามคุณสมบัตินั้นทำท่าว่าไม่มีอยู่

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

คุณสามารถสร้างคุณสมบัติที่ไม่นับได้ของคุณเองโดยใช้Object.definePropertyวิธีการ:

  var car = {
    make: 'Honda',
    model: 'Civic',
    year: '2008',
    condition: 'bad',
    mileage: 36000
  };

  Object.defineProperty(car, 'mySecretAboutTheCar', {
    value: 'cat pee in back seat',
    enumerable: false
  });

ตอนนี้ความจริงที่ว่ามีความลับเกี่ยวกับรถซ่อนอยู่ แน่นอนว่าพวกเขายังคงสามารถเข้าถึงอสังหาริมทรัพย์ได้โดยตรงและรับคำตอบ:

console.log(car.mySecretAboutTheCar); // prints 'cat pee in back seat'

แต่พวกเขาจะต้องรู้ว่าทรัพย์สินมีอยู่ก่อนเพราะหากพวกเขาพยายามที่จะเข้าถึงมันผ่านfor..inหรือObject.keysมันจะยังคงเป็นความลับอย่างสมบูรณ์:

console.log(Object.keys(car)); //prints ['make', 'model', 'year', 'condition', 'mileage']

พวกเขาควรจะเรียกมันว่า "forInAble"


5
โหวตขึ้นสำหรับบรรทัดสุดท้ายนั้น - ฉันคิดว่าจริง ๆ แล้วมันถูกเรียกใช้สำหรับภายในไม่มีใครจะถามเกี่ยวกับมันเลย ซึ่งนำคำถามของฉัน - เหตุผลที่จะให้คุณ (หรือคุณจะทำไมต้อง) การตั้งค่าคุณสมบัติที่จะไม่ได้นับ? คุณสมบัติความยาวของอาเรย์นั้นมักใช้เป็นตัวอย่างของคุณสมบัติที่ไม่นับจำนวน แต่ทำไมคุณไม่ตั้งค่าให้เป็นแบบนับไม่ได้ (ไม่ใช่ข้อ จำกัด JavaScript ฉันหมายถึงเหตุใดจึงตั้งให้ไม่นับใน JavaScript ใน สถานที่แรก)
คริส

เพื่อชี้แจงคำถามของฉันทำไมจึงตัดสินใจว่าสิ่งต่อไปนี้ไม่ใช่ตัวเลือก: สร้าง: Honda model: Civic secret: Cat pee length: 12
Chris

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

การตอบคำถามแรกของคุณการตั้งค่าคุณสมบัติที่ไม่นับจำนวนบนวัตถุนั้นเป็นเรื่องเล็กน้อยเนื่องจากวิธีเดียวที่คุณจะสามารถค้นหาสิ่งที่อยู่บนวัตถุนั้นคือการดูรหัสและเป็นรหัสฐาน พัฒนามันอาจถูกฝังอยู่ ดังนั้นโดยทั่วไปคุณไม่ต้องการใช้มัน เกี่ยวกับ '.length' ซึ่งให้จำนวนอักขระในสตริงหรือองค์ประกอบในอาร์เรย์เป็นเพียงสิ่งที่สันนิษฐานว่าเราไม่ต้องการรวมถ้าเราใช้ 'for ... in' ไม่สามารถตอบได้ว่าทำไมเทพเจ้าของ Js จึงต้องทำแบบนั้น พวกเขามีเหตุผล ( ahem ) ความคิดเห็นที่เกินความเข้าใจของเรา
Gabriel Kunkel

... และฉันไม่คิดว่าฉันสามารถตอบคำถามที่สองของคุณเกี่ยวกับประเภทข้อมูลที่แจกแจงถึงแม้ว่ามันจะดูเหมือนว่าบางสิ่งที่ฉันสามารถเคี้ยวได้นานพอสมควรถ้าฉันมีเวลา :-)
Gabriel Kunkel

9

หากคุณมีปัญหาในการมองเห็นภาพ "การนับจำนวนหมายความว่าอะไร? ทำไมไม่ถามตัวเองว่าสิ่งที่ไม่ได้หมายความว่าจะnonenumerable ?

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

var o = {};
o['foo'] =  0;                               // enumerable, normal
Object.defineProperty(o, 'bar', {value: 1}); // nonenumerable, weird

ในตอนนี้for..inลองจินตนาการว่ามันเหมือนpseudocode

for property in o:
    if not property enumerable continue // skip non-enumerable, "bar"
    else do /* whatever */              // act upon enumerable, "foo"

ตำแหน่งที่ร่างกายของลูปที่คุณพิมพ์ในJavaScriptอยู่ในตำแหน่ง/* whatever */


8

ฉันจะเขียนนิยามหนึ่งบรรทัดของENUMERABLE

Enumerable:ระบุว่าคุณสมบัติสามารถส่งคืนได้ใน for / in loop

var obj = {};
Object.defineProperties(obj, {
    set1: {enumerable: true},
    set2: {enumerable: false},
});
Object.keys(obj); // ["set1"]
Object.getOwnPropertyNames(obj); // ["set1", "set2"]

0

วิธีการไม่นับจำนวน หรือค่อนข้างสร้างขึ้นในวิธีการไม่ .. tho หลังจากค้นหาสิ่งที่นับความ หมายจาวาสคริปต์; มันหมายถึงคุณสมบัติของคุณสมบัติ .. วัตถุที่สร้างขึ้นทั้งหมดใน ecma3 นั้นนับได้และ ecma5 คุณสามารถกำหนดได้ .... แค่นั้นแหละ .. : D: ฉันใช้เวลาเล็กน้อยในการหาคำตอบ แต่ฉันเชื่อว่ามันพูดถึงในหนังสือของเดวิดฟลานาแกน .. ดังนั้นฉันเดาว่ามันหมายถึง "ซ่อนเร้น" หรือไม่ "ซ่อนเร้น" ในวิธีการที่ไม่ปรากฏในการวนรอบและจึง "ซ่อน"


0

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


0

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.