แรงจูงใจในการนำสัญลักษณ์ไป ES6 คืออะไร?


368

อัปเดต : เมื่อเร็ว ๆ นี้บทความยอดเยี่ยมจาก Mozillaขึ้นมา อ่านถ้าคุณอยากรู้

ดังที่คุณอาจทราบว่าพวกเขากำลังวางแผนที่จะรวม Symbol แบบดั้งเดิมใหม่ใน ECMAScript 6 (ไม่ต้องพูดถึงสิ่งที่บ้าอื่น ๆ ) ฉันมักจะคิดว่าความ:symbolคิดในทับทิมนั้นไม่จำเป็น เราสามารถใช้สตริงธรรมดาได้อย่างง่ายดายแทนเช่นที่เราทำใน JavaScript และตอนนี้พวกเขาตัดสินใจที่จะทำให้สิ่งต่าง ๆ ใน JS ซับซ้อนขึ้น

ฉันไม่เข้าใจแรงจูงใจ มีคนอธิบายให้ฉันฟังว่าเราต้องการสัญลักษณ์ใน JavaScript จริงหรือ


6
ผมไม่ทราบว่าเป็นของแท้คำอธิบายนี้เป็น แต่มันเป็นจุดเริ่มต้น: tc39wiki.calculist.org/es6/symbols
เฟลิกซ์คลิง

8
สัญลักษณ์เปิดใช้งานมากและอนุญาตให้มีตัวระบุเฉพาะบนวัตถุ ตัวอย่างเช่นการมีคุณสมบัติบนวัตถุที่สามารถเข้าถึงได้ในที่เดียวเท่านั้น
Benjamin Gruenbaum

5
ไม่แน่ใจเกี่ยวกับสิ่งนั้นเนื่องจากคุณสามารถใช้ Object.getOwnPropertySymbols (o)
Yanis

4
มันเป็นเอกลักษณ์มากกว่าความเป็นส่วนตัว
แควนตัส 94 หนัก

2
พวกเขากำลังจะมีการใช้คลาสที่ซับซ้อนยิ่งขึ้นprivateและpublicคีย์เวิร์ดแอ็ตทริบิวต์คลาสที่พวกเขาตัดสินใจที่จะใช้เพื่อการใช้คลาสที่ง่ายขึ้น แทนการthis.x = xที่คุณควรจะทำและสำหรับตัวแปรส่วนตัวpublic x = x private y = yพวกเขาตัดสินใจทิ้งไว้ว่าเพื่อการใช้งานในชั้นเรียนที่น้อยที่สุด สัญลักษณ์จะเป็นวิธีแก้ปัญหาที่จำเป็นเพื่อให้ได้คุณสมบัติส่วนตัวในการนำไปใช้งานน้อยที่สุด
lyschoening

คำตอบ:


224

แรงจูงใจดั้งเดิมสำหรับการแนะนำสัญลักษณ์ให้กับ Javascript คือการเปิดใช้งานคุณสมบัติส่วนตัว

น่าเสียดายที่พวกเขาถูกปรับลดลงอย่างรุนแรง พวกเขาไม่ได้เป็นส่วนตัวอีกต่อไปเนื่องจากคุณสามารถค้นหาพวกเขาผ่านการสะท้อนเช่นใช้Object.getOwnPropertySymbolsหรือพร็อกซี่

ตอนนี้พวกเขารู้จักกันในชื่อสัญลักษณ์ที่ไม่ซ้ำใครและการใช้งานเพียงอย่างเดียวเพื่อหลีกเลี่ยงการปะทะกันของชื่อระหว่างคุณสมบัติ ตัวอย่างเช่นขณะนี้ ECMAScript สามารถแนะนำ hook ส่วนขยายผ่านวิธีการบางอย่างที่คุณสามารถวางไว้บนวัตถุ (เช่นเพื่อกำหนดโปรโตคอลการทำซ้ำ) โดยไม่ต้องเสี่ยงกับการปะทะกับชื่อผู้ใช้

ไม่ว่าจะมีความแข็งแกร่งเพียงพอที่จะเพิ่มสัญลักษณ์ให้กับภาษานั้นเป็นที่ถกเถียงกันหรือไม่


93
ภาษาส่วนใหญ่ (ทุกภาษาหลัก afaik) ให้กลไกบางอย่างซึ่งมักจะสะท้อนให้เห็นถึงการเข้าถึงส่วนตัวอย่างไรก็ตาม
Esailija

19
@Eailija ฉันไม่คิดว่ามันเป็นเรื่องจริง - โดยเฉพาะอย่างยิ่งเนื่องจากภาษาต่าง ๆ ไม่ได้มีการสะท้อนในตอนแรก การรั่วไหลของสถานะส่วนตัวผ่านการสะท้อน (เช่นใน Java) ควรได้รับการพิจารณาว่าเป็นข้อบกพร่องไม่ใช่คุณลักษณะ โดยเฉพาะอย่างยิ่งในหน้าเว็บที่มีสถานะส่วนตัวที่เชื่อถือได้สามารถเกี่ยวข้องกับความปลอดภัย ปัจจุบันวิธีเดียวที่จะทำให้สำเร็จใน JS คือผ่านการปิดซึ่งอาจเป็นเรื่องที่น่าเบื่อและเสียค่าใช้จ่าย
Andreas Rossberg

38
กลไกไม่จำเป็นต้องสะท้อนออกมา - C ++, Java, C #, Ruby, Python, PHP, Objective-C ทั้งหมดอนุญาตให้เข้าถึงหนึ่งทางหรืออีกทางหนึ่งหากต้องการจริงๆ มันไม่ได้เกี่ยวกับความสามารถ แต่เป็นการสื่อสาร
Esailija

4
@plalx บนเว็บ encapsulation บางครั้งก็เกี่ยวกับความปลอดภัยด้วย
Andreas Rossberg

3
@RolandPihlakas น่าเสียดายที่Object.getOwnPropertySymbolsไม่ใช่แค่การรั่วไหลเท่านั้น สิ่งที่ยากกว่าคือความสามารถในการใช้พร็อกซีเพื่อสกัดกั้นการเข้าถึงคุณสมบัติ "ส่วนตัว"
Andreas Rossberg

95

สัญลักษณ์ไม่รับประกันความเป็นส่วนตัวที่แท้จริง แต่สามารถใช้เพื่อแยกคุณสมบัติสาธารณะและภายในของวัตถุ ลองมาตัวอย่างที่เราสามารถใช้Symbolสำหรับการมีคุณสมบัติส่วนตัว

ลองมาตัวอย่างที่คุณสมบัติของวัตถุไม่ส่วนตัว

var Pet = (function() {
  function Pet(type) {
    this.type = type;
  }
  Pet.prototype.getType = function() {
    return this.type;
  }
  return Pet;
}());

var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Modified outside
console.log(a.getType());//Output: null

ด้านบนPetสถานที่ให้บริการชั้นtypeไม่เป็นส่วนตัว เพื่อให้เป็นส่วนตัวเราต้องสร้างการปิด ตัวอย่างด้านล่างแสดงวิธีที่เราสามารถทำให้เป็นtypeส่วนตัวโดยใช้การปิด

var Pet = (function() {
  function Pet(type) {
    this.getType = function(){
      return type;
    };
  }
  return Pet;
}());

var b = new Pet('dog');
console.log(b.getType());//dog
b.type = null;
//Stays private
console.log(b.getType());//dog

ข้อเสียของวิธีการข้างต้น: เราขอแนะนำการปิดพิเศษสำหรับแต่ละPetอินสแตนซ์ที่สร้างขึ้นซึ่งอาจเป็นอันตรายต่อประสิทธิภาพการทำงาน

Symbolตอนนี้เราแนะนำ สิ่งนี้สามารถช่วยเราสร้างที่พักส่วนตัวโดยไม่ต้องใช้การปิดที่ไม่จำเป็นเป็นพิเศษ ตัวอย่างรหัสด้านล่าง:

var Pet = (function() {
  var typeSymbol = Symbol('type');
  function Pet(type) {
    this[typeSymbol] = type;
  }
  Pet.prototype.getType = function(){
    return this[typeSymbol];
  }
  return Pet;
}());

var a = new Pet('dog');
console.log(a.getType());//Output: dog
a.type = null;
//Stays private
console.log(a.getType());//Output: dog

15
ขอให้สังเกตว่าคุณสมบัติสัญลักษณ์ไม่ได้เป็นส่วนตัว ! สัญลักษณ์การปะทะกันฟรี คุณอาจต้องการอ่านคำตอบที่ยอมรับได้
Bergi

3
ใช่สัญลักษณ์ไม่รับประกันความเป็นส่วนตัวที่แท้จริง แต่สามารถใช้เพื่อแยกคุณสมบัติสาธารณะและภายในของวัตถุ ขออภัยลืมเพิ่มจุดนี้ในคำตอบของฉัน จะอัปเดตคำตอบของฉันตาม
Samar Panda

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

10
ฉันจะไม่บอกว่าไม่มีจุดหมายเนื่องจากสัญลักษณ์โดยค่าเริ่มต้นนั้นไม่สามารถนับได้และยังไม่สามารถเข้าถึงได้โดย 'ความผิดพลาด' ในขณะที่ปุ่มอื่นสามารถทำได้
Patrick

5
ฉันค้นหาคำตอบของคุณคนเดียวที่มีตัวอย่างที่เข้าใจได้ง่ายว่าทำไมคุณถึงต้องการกำหนดแอตทริบิวต์ส่วนตัวของวัตถุเป็น Symbol แทนที่จะเป็นแค่คุณสมบัติปกติ
Luis Lobo Borobia

42

Symbolsเป็นวัตถุชนิดใหม่ชนิดพิเศษที่สามารถใช้เป็นชื่อคุณสมบัติเฉพาะในวัตถุ การใช้Symbolแทนstringจะอนุญาตให้โมดูลต่าง ๆ สร้างคุณสมบัติที่ไม่ขัดแย้งกัน นอกจากนี้ยังสามารถทำให้เป็นส่วนตัวเพื่อให้คุณสมบัติของพวกเขาไม่สามารถเข้าถึงได้โดยทุกคนที่ไม่ได้มีการเข้าถึงโดยตรงไปSymbolsSymbol

Symbolsเป็นใหม่ดั้งเดิม เช่นเดียวกับnumber, stringและboolean, Symbolมีฟังก์ชันที่สามารถใช้สร้างมันได้ ไม่เหมือนดั้งเดิมอื่น ๆSymbolsไม่มีไวยากรณ์ที่แท้จริง (เช่นstringมี'') - วิธีเดียวที่จะสร้างพวกเขาคือกับSymbolนวกรรมิกในทางต่อไปนี้:

let symbol = Symbol();

ในความเป็นจริงSymbol's เป็นเพียงวิธีการที่แตกต่างกันเล็กน้อยเพื่ออายัดทรัพย์สินไปยังวัตถุ - คุณสามารถให้ที่รู้จักกันดีSymbolsว่าเป็นวิธีการมาตรฐานเช่นเดียวกับที่ปรากฏในทุกสิ่งที่สืบทอดจากObject.prototype.hasOwnPropertyObject

นี่คือบางส่วนของประโยชน์ของSymbolประเภทดั้งเดิม

Symbols มี debuggability ในตัว

Symbols สามารถให้คำอธิบายซึ่งจริงๆแล้วใช้สำหรับการดีบักเพื่อทำให้ชีวิตง่ายขึ้นเล็กน้อยเมื่อเข้าสู่คอนโซล

Symbolsสามารถใช้เป็นObjectกุญแจได้

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

Symbols สามารถใช้เป็นค่าที่ไม่ซ้ำกัน

สมมติว่าคุณมีการเข้าสู่ระบบห้องสมุดซึ่งรวมถึงระดับการเข้าสู่ระบบหลายอย่างเช่นlogger.levels.DEBUG, logger.levels.INFO, logger.levels.WARNและอื่น ๆ ในรหัส ES5 คุณต้องการสร้างstrings (ดังกล่าวlogger.levels.DEBUG === 'debug') หรือnumbers ( logger.levels.DEBUG === 10) ทั้งสองอย่างนี้ไม่เหมาะเนื่องจากค่าเหล่านั้นไม่ใช่ค่าที่ไม่ซ้ำกัน แต่Symbols! ดังนั้นlogger.levelsเพียงกลายเป็น:

log.levels = {
  DEBUG: Symbol('debug'),
  INFO: Symbol('info'),
  WARN: Symbol('warn'),
};
log(log.levels.DEBUG, 'debug message');
log(log.levels.INFO, 'info message');

อ่านเพิ่มเติมในนี้บทความดีดี


10
ผมไม่แน่ใจว่าผมเข้าใจตัวอย่างของคุณและเหตุผลที่คุณจะต้องและไม่เพียงlog.levels = {DEBUG: Symbol('debug') log.levels = {DEBUG:'debug'}ในตอนท้ายมันก็เหมือนกัน ฉันคิดว่ามันคุ้มค่าที่จะกล่าวถึงสัญลักษณ์ที่มองไม่เห็นเมื่อวนคีย์ของวัตถุ นั่นคือ "สิ่งของ" ของพวกเขา
vsync

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

หมายเหตุเมื่อใช้เป็นค่าที่ไม่ซ้ำกันวัตถุตามตัวอักษรมีdebuggability ในตัวเช่นSymbol("some message")จะกลายเป็น{message:'some message'}วัตถุที่วัตถุทำได้ดีกว่าที่นี่เพราะคุณสามารถเพิ่มหลายฟิลด์
apple apple

38

โพสต์นี้เกี่ยวกับ Symbol() , มาพร้อมกับตัวอย่างจริงที่ฉันสามารถหา / ทำและข้อเท็จจริง & คำจำกัดความที่ฉันสามารถหาได้

TLDR;

นี่Symbol()คือชนิดข้อมูลที่แนะนำพร้อมกับการเปิดตัว ECMAScript 6 (ES6)

มีข้อเท็จจริงที่น่าสงสัยเกี่ยวกับสัญลักษณ์สองอย่าง

  • ชนิดข้อมูลแรกและชนิดข้อมูลเท่านั้นใน JavaScript ซึ่งไม่มีตัวอักษร

  • ตัวแปรใด ๆ ที่กำหนดไว้กับSymbol()ได้รับเนื้อหาที่ไม่ซ้ำกัน แต่มันไม่ได้จริงๆส่วนตัว

  • ข้อมูลใด ๆ ที่มีของตัวเองสัญลักษณ์และสำหรับข้อมูลเดียวกันสัญลักษณ์จะเป็นแบบเดียวกัน ข้อมูลเพิ่มเติมในย่อหน้าต่อไปนี้มิฉะนั้นจะไม่ใช่ TLRD :)

ฉันจะเริ่มต้นสัญลักษณ์ได้อย่างไร

1. เพื่อให้ได้ตัวระบุที่ไม่ซ้ำกับค่าที่ debuggable

คุณสามารถทำได้ด้วยวิธีนี้:

var mySymbol1 = Symbol();

หรือด้วยวิธีนี้:

var mySymbol2 = Symbol("some text here");

"some text here"สตริงไม่สามารถสกัดได้จากสัญลักษณ์มันเป็นเพียงคำอธิบายสำหรับการดีบักวัตถุประสงค์ มันไม่ได้เปลี่ยนพฤติกรรมของสัญลักษณ์ในทางใดทางหนึ่ง แม้ว่าคุณจะทำได้console.log(ซึ่งยุติธรรมเนื่องจากค่าสำหรับการดีบักเพื่อไม่ให้เกิดข้อผิดพลาดในการบันทึกที่มีรายการบันทึกอื่น ๆ ):

console.log(mySymbol2);
// Symbol(some text here)

2. เพื่อรับสัญลักษณ์สำหรับข้อมูลสตริงบางอย่าง

ในกรณีนี้มูลค่าของสัญลักษณ์ถูกนำมาพิจารณาจริงและวิธีนี้สองสัญลักษณ์อาจไม่ซ้ำกัน

var a1 = Symbol.for("test");
var a2 = Symbol.for("test");
console.log(a1 == a2); //true!

มาเรียกสัญลักษณ์เหล่านี้ว่า "second-type" พวกเขาจะไม่ตัดกับสัญลักษณ์ "ประเภทแรก" (เช่นที่กำหนดด้วยSymbol(data) ) ในทางใดทางหนึ่ง

สองย่อหน้าถัดไปเกี่ยวข้องเฉพาะกับประเภทแรกเท่านั้นสัญลักษณ์เท่านั้น

ฉันจะได้รับประโยชน์จากการใช้ Symbol แทนประเภทข้อมูลที่เก่ากว่าได้อย่างไร

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

var persons = {"peter":"pan","jon":"doe"};
console.log(persons.peter);
// pan

ถ้าเรามีสองคนที่มีชื่อปีเตอร์ล่ะ

ทำสิ่งนี้:

var persons = {"peter":"first", "peter":"pan"};

จะไม่สมเหตุสมผล

ดังนั้นดูเหมือนจะเป็นปัญหาของคนสองคนที่แตกต่างกันอย่างสิ้นเชิงที่มีชื่อเหมือนกัน Symbol()ลองมาแล้วดูออกใหม่ มันเหมือนคนในชีวิตจริง - บุคคลใดมีเอกลักษณ์แต่ชื่อของพวกเขาจะเท่ากัน มานิยาม "คน" สองคนกัน

 var a = Symbol("peter");
 var b = Symbol("peter");

ตอนนี้เรามีคนสองคนที่มีชื่อเหมือนกัน บุคคลของเราแตกต่างกันหรือไม่? พวกเขาคือ; คุณสามารถตรวจสอบสิ่งนี้:

 console.log(a == b);
 // false

เราจะได้ประโยชน์อย่างไรที่นั่น?

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

 var firstPerson = Symbol("peter");
 var secondPerson = Symbol("peter");
 var persons = {[firstPerson]:"first", [secondPerson]:"pan"};

หมายเหตุ:
มันมีค่าที่จะสังเกตเห็นว่าการ stringing วัตถุด้วยJSON.stringifyจะวางคู่ทั้งหมดที่เริ่มต้นด้วยสัญลักษณ์เป็นคีย์
การดำเนินการObject.keysจะไม่ส่งคืนSymbol()->valueคู่ดังกล่าว

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

 console.log(persons[a]);
 // first
 console.log(persons[b]);
 // pan

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

แท้จริงแล้วมีวิธีการกำหนดคุณสมบัติที่จะซ่อนObject.keysและการแจงนับ นี่มันคือ:

var anObject = {};
var fruit = "apple";    

Object.defineProperty( anObject, fruit, {
    enumerable: false,
    value: "green"
});

มีความแตกต่างอะไรบ้างSymbol()? ความแตกต่างคือคุณยังสามารถรับคุณสมบัติที่กำหนดด้วยObject.definePropertyวิธีปกติ:

console.log(anObject[fruit]); //green
console.log(anObject["apple"]); //green
console.log(anObject.apple); //green

และหากนิยามด้วย Symbol ตามวรรคก่อนหน้า:

fruit = Symbol("apple");

คุณจะมีความสามารถในการรับค่าของมันเฉพาะเมื่อรู้ว่าตัวแปรคือ

console.log(anObject[fruit]); //green
console.log(anObject["apple"]); //undefined
console.log(anObject.apple); //undefined

ยิ่งไปกว่านั้นการกำหนดคุณสมบัติอื่นภายใต้คีย์"apple"จะทำให้วัตถุวางอันเก่า (และหากฮาร์ดโค้ดมันอาจทำให้เกิดข้อผิดพลาด) ดังนั้นไม่มีแอปเปิ้ลอีกต่อไป! ที่น่าเสียดาย. อ้างถึงย่อหน้าก่อนหน้าสัญลักษณ์ที่ไม่ซ้ำกันและการกำหนดคีย์ที่Symbol()จะทำให้มันเป็นเอกลักษณ์

การแปลงและตรวจสอบประเภท

  • ไม่เหมือนกับชนิดข้อมูลอื่น ๆ เป็นไปไม่ได้ที่จะแปลงเป็นSymbol()ชนิดข้อมูลอื่น

  • มันเป็นไปได้ที่จะ "ให้" Symbol(data)สัญลักษณ์ขึ้นอยู่กับชนิดข้อมูลดั้งเดิมโดยการเรียก

  • ในแง่ของการตรวจสอบประเภทไม่มีอะไรเปลี่ยนแปลง

    function isSymbol ( variable ) {
        return typeof someSymbol === "symbol";
    }
    
    var a_Symbol = Symbol("hey!");
    var totally_Not_A_Symbol = "hey";
    
    console.log(isSymbol(a_Symbol)); //true
    console.log(isSymbol(totally_Not_A_Symbol)); //false


สิ่งนี้ถูกย้ายจากเอกสารประกอบ SO หรือไม่
Knu

1
@KNU มันไม่ได้; ฉันได้รวบรวมข้อมูลและเขียนคำตอบนี้ด้วยตัวเอง
นิก้า

คำตอบที่สวยงามจริงๆ!
Mihai Alexandru-Ionut

1
คำตอบที่ยอดเยี่ยมเกี่ยวกับ Symbol แต่ฉันก็ยังไม่รู้ว่าทำไมฉันถึงใช้วัตถุที่มีปุ่มสัญลักษณ์แทนอาเรย์ ถ้าฉันมีหลายคนเช่น {"peter": "pan"} {"john": "doe"} มันทำให้ฉันรู้สึกแย่ที่จะเอามันไปใส่ในวัตถุชิ้นเดียว ด้วยเหตุผลเดียวกับที่ฉันไม่ได้สร้างคลาสที่มีคุณสมบัติที่ซ้ำกันเช่น personFirstName1, personFirstName2 เมื่อรวมกับการไร้ความสามารถที่จะทำให้เป็นจริงฉันไม่เห็นประโยชน์ที่จะเสียไป
eldo

18

นี่คือวิธีที่ฉันเห็น สัญลักษณ์มีระดับความเป็นส่วนตัวที่เพิ่มขึ้นโดยป้องกันไม่ให้คีย์ / คุณสมบัติของวัตถุถูกเปิดเผยด้วยวิธีที่นิยมเช่น Object.keys () และ JSON.stringify ()

var age = Symbol();  // declared in another module perhaps?
class Person {
   constructor(n,a){
      this.name = n;
      this[age] = a;  
   }
   introduce(){
       console.log(`My name is ${this.name}. I am ${this[age]-10}.`);
   }
}
var j = new Person('Jane',45);
j.introduce();  // My name is Jane. I am 35.
console.log(JSON.stringify(j)); // {"name":"Jane"}
console.log(Object.keys(j)); // ["name"]
console.log(j[age]); // 45   (well…only if you know the age in the first place…)

แม้ว่าจะได้รับอ็อบเจกต์ต่อคุณสมบัติดังกล่าวยังสามารถสัมผัสผ่านการสะท้อนพร็อกซี Object.getOwnPropertySymbols () ฯลฯ ไม่มีวิธีการที่เป็นธรรมชาติในการเข้าถึงพวกเขาผ่านวิธีการโดยตรงไม่กี่ซึ่งอาจเพียงพอจากมุมมองของ OOP


2

สัญลักษณ์ JS เป็นชนิดข้อมูลดั้งเดิมใหม่ พวกเขาเป็นราชสกุลที่ทำหน้าที่เป็นรหัสที่ไม่ซ้ำกัน สามารถสร้างสัญลักษณ์ได้โดยใช้SymbolConstructor ยกตัวอย่างข้อมูลนี้จาก MDN:

// The symbol constructor takes one optional argument, 
// the descriptions which is used for debugging only.
// Here are two symbols with the same description
let Sym1 = Symbol("Sym");
let Sym2 = Symbol("Sym");
  
console.log(Sym1 == Sym2); // returns "false"
// Symbols are guaranteed to be unique.
// Even if we create many symbols with the same description,
// they are different values.

บ่อยครั้งที่มีประโยชน์ในการใช้สัญลักษณ์เป็นคีย์คุณสมบัติวัตถุที่ไม่ซ้ำกันเช่น:

let obj = {};
let prop = Symbol();

obj[prop] = 123;  // the symbol prop is assigned 123
obj.prop  = 456;  // the string prop is assigned 456

console.log(obj.prop, obj[prop]); // logs 456, 123


0

สัญลักษณ์มีสองกรณีการใช้งานหลัก:

  1. คุณสมบัติวัตถุ“ ซ่อน” หากเราต้องการเพิ่มคุณสมบัติลงในวัตถุที่“ เป็น” ในสคริปต์หรือไลบรารีอื่นเราสามารถสร้างสัญลักษณ์และใช้เป็นรหัสคุณสมบัติได้ คุณสมบัติสัญลักษณ์ไม่ปรากฏขึ้นfor..inดังนั้นจะไม่ถูกประมวลผลโดยไม่ได้ตั้งใจพร้อมกับคุณสมบัติอื่น ๆ และจะไม่สามารถเข้าถึงได้โดยตรงเนื่องจากสคริปต์อื่นไม่มีสัญลักษณ์ของเรา ดังนั้นคุณสมบัติจะได้รับการปกป้องจากการใช้งานโดยไม่ตั้งใจหรือเขียนทับ

    ดังนั้นเราจึงสามารถ "ซ่อนเร้น" ซ่อนสิ่งที่เป็นวัตถุที่เราต้องการ แต่คนอื่นไม่ควรมองเห็นโดยใช้คุณสมบัติเชิงสัญลักษณ์

  2. มีสัญลักษณ์ระบบจำนวนมากที่ใช้โดย JavaScript Symbol.*ซึ่งสามารถเข้าถึงได้เช่นเดียวกับ เราสามารถใช้พวกมันเพื่อปรับเปลี่ยนพฤติกรรมที่มีในตัว ตัวอย่างเช่น ...... Symbol.iteratorสำหรับ iterables Symbol.toPrimitiveเพื่อตั้งค่าการแปลง object-to-primitive และอื่น ๆ

แหล่ง

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