การเสริมหรือปรับปรุงตัวแปร ECMAScript
- หน้าก่อนหน้า โดยสายวัตถุ
- หน้าต่อไป แก้ไขวัตถุ
การใช้สิ่งที่กำหนดมาก่อนเป็นส่วนหนึ่งของความสามารถของภาษาที่มีทฤษฎีโอปเปอร์เรียน แต่ความแข็งแกร่งที่แท้จริงของมันนั้นอยู่ที่สามารถสร้างชนิดและออบเจกต์ที่เป็นส่วนบุคคลของตัวเอง:
ECMAScript มีวิธีหลายวิธีที่สามารถสร้างออบเจกต์หรือชนิด:
วิธีโรงงาน
วิธีที่เดิม
เพราะคุณสมบัติของออブเจกต์สามารถถูกกำหนดได้ทางด้านนอกของการสร้างออบเจกต์ ดังนั้น ผู้พัฒนาหลายคนได้เขียนโค้ดที่คล้ายกันเมื่อ JavaScript ถูกนำเข้าใช้ครั้งแรก:
var oCar = new Object; oCar.color = "blue"; oCar.doors = 4; oCar.mpg = 25; oCar.showColor = function() { alert(this.color); };
ในโค้ดด้านบน สร้างอ็อบเจกต์ car และกำหนดคุณสมบัติเกี่ยวกับมัน: สีของมันคือสีฟ้า มีประตูสี่ และสามารถวิ่งได้ 25 ไมล์ต่อแกลลอน คุณสมบัติสุดท้ายเป็นความหมายของตัวชี้แห้งไปยังฟังก์ชัน ซึ่งหมายความว่าคุณสมบัตินี้เป็นวิธี หลังจากที่ปฏิบัติการนี้เสร็จสิ้น จึงสามารถใช้อ็อบเจกต์ car
อย่างไรก็ตาม มีปัญหาหนึ่งที่อาจจะต้องสร้างหลายตัวอย่างของ car
แนวทางแก้ปัญหา: วิธีโรงงาน
เพื่อแก้ปัญหานี้ ผู้พัฒนาได้สร้างฟังก์ชันโรงงานที่สามารถสร้างและส่งผ่านอ็อบเจกต์ประเภทเฉพาะเจาะจง
ตัวอย่างเช่น ฟังก์ชัน createCar() สามารถใช้ปิดกลอบปฏิบัติการที่เรียกว่าการสร้างอ็อบเจกต์ car ที่อยู่ด้านบน
function createCar() { var oTempCar = new Object; oTempCar.color = "blue"; oTempCar.doors = 4; oTempCar.mpg = 25; oTempCar.showColor = function() { alert(this.color); }; return oTempCar; } var oCar1 = createCar(); var oCar2 = createCar();
ที่นี่ ทุกๆ โค้ดในตัวอย่างแรกที่อยู่ด้วยฟังก์ชัน createCar() และมีโค้ดเพิ่มเติมหนึ่งบรรทัด ซึ่งกลับค่าอ็อบเจกต์ car (oTempCar) ในฐานะค่าฟังก์ชัน การเรียกฟังก์ชันนี้จะสร้างอ็อบเจกต์ใหม่ และกำหนดคุณสมบัติทั้งหมดที่จำเป็น และสำเร็จการสำเนาอ็อบเจกต์ car ที่เราเคยชี้แจงไปแล้ว ดังนั้น ด้วยวิธีนี้เราสามารถสร้างอ็อบเจกต์ car สองรุ่น (oCar1 และ oCar2) ที่มีคุณสมบัติทั้งหมดเหมือนกันได้ง่าย
ส่งผ่านพารามิเตอร์แก่ฟังก์ชัน
เรายังสามารถแก้ไขฟังก์ชัน createCar() ให้ส่งผ่านค่าเริ่มต้นของคุณสมบัติ แทนที่จะใส่ค่าเริ่มต้นในคุณสมบัติ
function createCar(sColor,iDoors,iMpg) { var oTempCar = new Object; oTempCar.color = sColor; oTempCar.doors = iDoors; oTempCar.mpg = iMpg; oTempCar.showColor = function() { alert(this.color); }; return oTempCar; } var oCar1 = createCar("red",4,23); var oCar2 = createCar("blue",3,25); oCar1.showColor(); //ออก "red" oCar2.showColor(); //ออก "blue"
ให้ค่าเพื่อพารามิเตอร์ต่อฟังก์ชัน createCar() ก็สามารถกำหนดค่าของอัตราแบบ ประตูและ mpg ของอ็อบเจกต์ car ที่จะสร้าง ซึ่งทำให้สองอ็อบเจกต์มีคุณสมบัติเดียวกัน แต่มีค่าคุณสมบัติที่แตกต่างกัน
กำหนดวิธีของอ็อบเจกต์นอกจากฟังก์ชันโรงงาน
แม้ว่า ECMAScript จะกลายเป็นที่เกี่ยวข้องมากขึ้น แต่วิธีที่ทำการสร้างอ็อบเจกท์นั้นถูกละเลย และการมีมาตรฐานของมันยังเจอกับการคัดค้านจนถึงทุกวันนี้ ส่วนหนึ่งเกี่ยวข้องกับสาเหตุทางประโยคศัพท์ (มันดูไม่เป็นที่เกี่ยวข้องเท่ากับการใช้นักแบบบันทึก new อย่างเป็นทางการ) ส่วนหนึ่งเกี่ยวข้องกับสาเหตุทางฟังก์ชัน สาเหตุทางฟังก์ชันนี้เกี่ยวข้องกับการต้องสร้างอ็อบเจกต์ด้วยวิธีนี้ ในตัวอย่างก่อนหน้านี้ ในทุกครั้งที่เรียกฟังก์ชัน createCar() ก็ต้องสร้างฟังก์ชัน showColor() ใหม่ ซึ่งหมายความว่าแต่ละอ็อบเจกต์มีฟังก์ชัน showColor() ของตนเอง แต่ที่เร็ว ๆ นี้ แต่ละอ็อบเจกต์ยังคงแบ่งปันฟังก์ชันเดียวกัน
บางนักพัฒนากำหนดวิธีดำเนินการด้านวัตถุนอกจากฟังก์ชันสร้างโรงงาน แล้วทำให้ฟังก์ชันนี้มีความหมายผ่านทางอนุญาตด้วยนามว่าง ดังนั้นจึงเป็นทางแก้ปัญหานี้
function showColor() { alert(this.color); } function createCar(sColor,iDoors,iMpg) { var oTempCar = new Object; oTempCar.color = sColor; oTempCar.doors = iDoors; oTempCar.mpg = iMpg; oTempCar.showColor = showColor; return oTempCar; } var oCar1 = createCar("red",4,23); var oCar2 = createCar("blue",3,25); oCar1.showColor(); //ออก "red" oCar2.showColor(); //ออก "blue"
ในรหัสที่ถูกแก้ไขใหม่นี้ ฟังก์ชัน showColor ถูกกำหนดก่อนฟังก์ชัน createCar() ภายใน createCar() มีการสร้างวัตถุโดยอนุญาตให้วัตถุมีความหมายต่อฟังก์ชัน showColor() จากทางฟังก์ชันนี้ ด้วยทางทฤษฎีนี้ นี่แก้ปัญหาที่สร้างวัตถุฟังก์ชันเมื่อเปิดเผย แต่จากทางหลักความหมายนั้น ฟังก์ชันนี้ไม่เหมือนว่าจะเป็นฟังก์ชันของวัตถุ
ทั้งหมดนี้ทำให้เกิดที่มีการกำหนดโดยนักพัฒนาการปรากฎของฟังก์ชันสร้างคลาส
วิธีการสร้างคลาส
การสร้างฟังก์ชันสร้างวัตถุมีความง่ายเหมือนกับฟังก์ชันสร้างโรงงาน ขั้นตอนแรกคือการเลือกชื่อคลาส หรือชื่อฟังก์ชันสร้างวัตถุ ตามแบบกำหนดไว้ชื่อดังกล่าวควรจะมีคำตั้งแต่ต้นใหญ่เพื่อที่จะแยกจากชื่อตัวแปรที่ตั้งชื่อด้วยต้นเล็ก นอกจากความแตกต่างนี้แล้ว ฟังก์ชันสร้างวัตถุมีลักษณะคล้ายกับฟังก์ชันสร้างโรงงาน ให้จำเป็นต้องจับตามองตัวอย่างด้านล่าง
function Car(sColor,iDoors,iMpg) { this.color = sColor; this.doors = iDoors; this.mpg = iMpg; this.showColor = function() { alert(this.color); }; } var oCar1 = new Car("red",4,23); var oCar2 = new Car("blue",3,25);
ลงรายละเอียดการแตกต่างระหว่างรหัสด้านบนและวิธีทางโรงงาน ต้นทาง ไม่มีการสร้างวัตถุด้วยคำสั่ง construct แต่ใช้คำสั่ง this ในนามว่าง ในขณะที่ใช้ประกาศสร้างวัตถุด้วยนัยนี้ สร้างวัตถุก่อนเริ่มทำการแบบ first สำหรับเรียกใช้วัตถุด้วย this มีสามารถเข้าถึงวัตถุนี้ได้ หลังจากนั้นสามารถสร้างค่าทางยัยของ this ได้ โดยมาตรฐานนั้นเป็นค่าที่กลับมาจากฟังก์ชันสร้างวัตถุ ไม่จำเป็นต้องใช้สัญญาณ return โดยชัดเจน
ตอนนี้ การสร้างออปเจกต์ด้วยนัท new และชื่อประเภท Car จะเหมือนกับวิธีที่สร้างออปเจกต์ทั่วไปใน ECMAScript
คุณอาจจะถามว่ามีปัญหาเกี่ยวกับการจัดการฟังก์ชันที่เหมือนกับวิธีที่ก่อนหน้านี้หรือไม่? ใช่แล้ว
เหมือนกับฟังก์ชันที่ทำงานเหมือนโรงงาน ฟังก์ชันสร้างจะสร้างฟังก์ชันตามลำดับ แต่เช่นเดียวกับฟังก์ชันที่ทำงานเหมือนโรงงาน สามารถเขียนฟังก์ชันนอกฟังก์ชันสร้างได้ แต่ทางศัพท์มันไม่มีหมายมากนั้น นี่คือเหตุผลที่ทำให้วิธีโปรโตไทป์มีความดีของมัน
วิธีโปรโตไทป์
วิธีโปรโตไทป์นี้ใช้ประโยชน์จากตัวแปร prototype ของออปเจกต์ และสามารถเห็นว่ามันเป็นตัวแปรที่สร้างออปเจกต์ใหม่
ที่นี่ จะใช้ฟังก์ชันสร้างว่างเพื่อตั้งชื่อประเภท หลังจากนั้นจะกำหนดตัวแปรและฟังก์ชันให้กับโปรโตไทป์ จึงเราจะทดลองรหัสของตัวอย่างก่อนหน้านี้อีกครั้ง รหัสด้านล่างนี้:
function Car() { } Car.prototype.color = "blue"; Car.prototype.doors = 4; Car.prototype.mpg = 25; Car.prototype.showColor = function() { alert(this.color); }; var oCar1 = new Car(); var oCar2 = new Car();
ในรหัสนี้ หลังจากนั้นได้ประกาศฟังก์ชันสร้าง (Car) โดยไม่มีรหัสใดๆ หลังจากนั้นได้กำหนดตัวแปรให้กับโปรโตไทป์ของ Car เพื่อกำหนดตัวแปรของออปเจกต์ Car โดยที่เมื่อเรียก new Car() ตัวแปรทั้งหมดของโปรโตไทป์จะถูกจัดสรรให้กับออปเจกต์ที่ถูกสร้าง หมายความว่าทุกตัวออปเจกต์ของ Car จะมีการจุดหน้าไปยังฟังก์ชัน showColor() จากนั้นทางสำหรับศัพท์นั้นดูเหมือนว่าทั้งหมดเป็นของออปเจกต์ ซึ่งแก้ปัญหาทั้งสองอย่างที่กล่าวข้างต้น
นอกจากนี้ ด้วยวิธีนี้ ยังสามารถตรวจสอบประเภทของออปเจกต์ที่ใช้สัญญาณ instanceof ได้ ดังนั้น รหัสด้านล่างจะออก TRUE:
alert(oCar1 instanceof Car); //ออก "true"
ปัญหาของวิธีโปรโตไทป์
วิธีโปรโตไทป์ดูเหมือนเป็นวิธีแก้ปัญหาที่ดี แต่สำหรับนี้มันไม่สมบูรณ์ในที่สุด
ต้นตอนนี้ ฟังก์ชันสร้างนี้ไม่มีตัวแปรของพิเศษ ไม่สามารถตั้งค่าค่าตัวแปรด้วยวิธีโปรโตไทป์ เพราะ ค่าตัวแปร color ของ Car1 และ Car2 ต่างกัน ค่าตัวแปร doors ต่างกัน ค่าตัวแปร mpg ต่างกัน มันหมายความว่าต้องเปลี่ยนค่าตัวแปรค่าปริยายหลังจากที่สร้างออปเจกต์ นี่เป็นสิ่งที่ไม่น่าพอใจ แต่ยังไม่จบทุกอย่าง ปัญหาที่แท้จริงเกิดขึ้นเมื่อตัวแปรหนี้คู่ตัวแปรที่ไม่ใช่ฟังก์ชัน ฟังก์ชันเฉพาะจะไม่สร้างปัญหา แต่ทั้งนี้ที่มีตัวแปรนั้นไม่ได้ถูกแบ่งปันอย่างหนาแน่นกัน โปรดคิดถึงตัวอย่างด้านล่าง:
function Car() { } Car.prototype.color = "blue"; Car.prototype.doors = 4; Car.prototype.mpg = 25; Car.prototype.drivers = new Array("Mike","John"); Car.prototype.showColor = function() { alert(this.color); }; var oCar1 = new Car(); var oCar2 = new Car(); oCar1.drivers.push("Bill"); alert(oCar1.drivers); //แสดง "Mike,John,Bill" alert(oCar2.drivers); //แสดง "Mike,John,Bill"
ในรหัสดังนี้ คุณสมบัติ drivers คือสายบวกที่บอกไปยังตัวแปร Array ที่มีชื่อ "Mike" และ "John". เพราะ drivers คือสายบวก แถวทั้งสองของ Car จะบอกไปยังตัวแปรเดียวกัน. ซึ่งหมายความว่าการเพิ่มค่า "Bill" ไปยัง oCar1.drivers จะทำให้เห็นใน oCar2.drivers ด้วย. การแสดงสายบวกทั้งสองจะแสดงข้อความ "Mike,John,Bill".
เนื่องจากมีหลายปัญหาเกี่ยวกับการสร้างองค์ประกอบ คุณอาจคิดว่า จะมีวิธีที่เหมาะสมสำหรับการสร้างองค์ประกอบหรือไม่? ตอบคำถามคือ มีแล้ว และต้องการใช้คอนสตรัคเตอร์และโปรโตไทป์ด้วยกัน.
การผสมกันของคอนสตรัคเตอร์/โปรโตไทป์
การผสมกันของคอนสตรัคเตอร์และโปรโตไทป์ สามารถสร้างองค์ประกอบอย่างเหมือนภาษาการออกแบบโปรแกรมอื่นได้. ความคิดนี้เป็นสิ่งที่ง่ายและง่ายต่อการเข้าใจ คือ ใช้คอนสตรัคเตอร์เพื่อกำหนดทุกคุณสมบัติที่ไม่ใช่ฟังก์ชันขององค์ประกอบ และใช้โปรโตไทป์เพื่อกำหนดฟังก์ชัน (วิธี) ขององค์ประกอบ. ผลลัพธ์คือ ฟังก์ชันทั้งหมดถูกสร้างเพียงครั้งเดียว และแต่ละองค์ประกอบมีตัวอย่างของคุณสมบัติของตนเอง.
เราเปลี่ยนแปลงตัวอย่างก่อนหน้านี้ โดยรหัสดังนี้:
function Car(sColor,iDoors,iMpg) { this.color = sColor; this.doors = iDoors; this.mpg = iMpg; this.drivers = new Array("Mike","John"); } Car.prototype.showColor = function() { alert(this.color); }; var oCar1 = new Car("red",4,23); var oCar2 = new Car("blue",3,25); oCar1.drivers.push("Bill"); alert(oCar1.drivers); //แสดง "Mike,John,Bill" alert(oCar2.drivers); //แสดง "Mike,John"
ตอนนี้มันเหมือนกับการสร้างองค์ประกอบทั่วไปมากขึ้นแล้ว. ทุกคุณสมบัติที่ไม่ใช่ฟังก์ชันถูกสร้างในคอนสตรัคเตอร์ หมายความว่าสามารถใช้ตัวแปรในคอนสตรัคเตอร์เพื่อกำหนดคุณสมบัติที่มีค่าเริ่มต้นได้. เพราะเราสร้างเพียงตัวอย่างเดียวของฟังก์ชัน showColor() ดังนั้นจึงไม่มีการเสียเวลาในการใช้ความจำ. นอกจากนี้ การเพิ่มค่า "Bill" ไปยังแถว drivers ของ oCar1 จะไม่ส่งผลกระทบต่อ oCar2 ดังนั้นเมื่อแสดงค่าแถวทั้งสอง แถว oCar1.drivers จะแสดง "Mike,John,Bill" และแถว oCar2.drivers จะแสดง "Mike,John". เพราะใช้วิธีโปรโตไทป์ ดังนั้นยังสามารถใช้เครื่องมือ instanceof ในการตรวจสอบประเภทขององค์ประกอบ.
This is the main method adopted by ECMAScript, which has the characteristics of other methods without their side effects. However, some developers still think that this method is not perfect.
dynamic prototype method
For developers accustomed to using other languages, using the mixed constructor/proto pattern may not feel harmonious. After all, when defining a class, most object-oriented languages visually encapsulate properties and methods. Consider the following Java class:
class Car { public String color = "blue"; public int doors = 4; public int mpg = 25; public Car(String color, int doors, int mpg) { this.color = color; this.doors = doors; this.mpg = mpg; } public void showColor() { System.out.println(color); } }
Java has well-packed all properties and methods of Car class, so seeing this code knows what it is supposed to achieve, it defines the information of an object. Critics of the mixed constructor/proto pattern argue that it is illogical to find properties inside the constructor and methods outside of it. Therefore, they designed dynamic prototype method to provide a more friendly coding style.
dynamic prototype method's basic idea is the same as mixed constructor/proto pattern, that is, define non-function properties inside the constructor, and define function properties using prototype properties. The only difference is the position where the object methods are assigned. Below is the Car class rewritten using dynamic prototype method:
function Car(sColor,iDoors,iMpg) { this.color = sColor; this.doors = iDoors; this.mpg = iMpg; this.drivers = new Array("Mike","John"); if (typeof Car._initialized == "undefined"}) { Car.prototype.showColor = function() { alert(this.color); }; Car._initialized = true; } }
จนกว่าจะตรวจสอบ typeof Car._initialized ไม่เท่ากับ "undefined" ก่อน ฟังก์ชันตั้งค่านี้ยังไม่เปลี่ยนแปลง บรรทัดนี้เป็นส่วนที่สำคัญที่สุดในวิธีเรียกใช้วิธีแรกของตัวเริ่มต้น หากค่านี้ไม่มีค่า (มีค่าเท่ากับ true ในการตรวจสอบ typeof) ฟังก์ชันตั้งค่าจะกำหนดวิธีในโปรโตไทป์ต่อไป แล้วกำหนด Car._initialized ให้เป็น true หากค่านี้มีค่า (มีค่าเท่ากับ true ในการตรวจสอบ typeof) ก็จะไม่สร้างวิธีนี้ สรุปแล้ว วิธีนี้ใช้สัญญาณ (_initialized) ในการตรวจสอบว่ามีวิธีใดๆ ที่ได้กำหนดให้กับโปรโตไทป์หรือไม่ วิธีนี้จะสร้างและกำหนดค่าเฉพาะครั้งเดียว นักพัฒนาโอเอ็มแวร์ที่ดูแลรหัสจะพบว่ารหัสนี้ดูเหมือนจะเป็นการกำหนดหน้ามากขึ้นเท่ากับหน้าในภาษาอื่น
วิธีผสมโรงงาน
วิธีนี้มักถูกใช้เป็นวิธีอีกต่อไป เมื่อไม่สามารถใช้วิธีที่แรกได้ มันมีวัตถุประสงค์ที่จะสร้างฟังก์ชันตั้งค่าแท้ๆ ที่มีความหมายเพียงแค่สร้างตัวแปรใหม่ๆ
รหัสนี้ดูเหมือนว่าจะเป็นฟังก์ชันโรงงานมาก:
function Car() { var oTempCar = new Object; oTempCar.color = "blue"; oTempCar.doors = 4; oTempCar.mpg = 25; oTempCar.showColor = function() { alert(this.color); }; return oTempCar; }
ต่างจากวิธีทางโครงสร้างเก่า วิธีนี้ใช้นักด้าน new ทำให้มันดูเหมือนเป็นฟังก์ชันตั้งค่าที่แท้จริง:
var car = new Car();
เนื่องจากการเรียกใช้นักด้าน new ในฟังก์ชันตั้งค่า Car() ดังนั้นจะละเลยการเรียกใช้นักด้าน new ครั้งที่สอง (ที่อยู่นอกฟังก์ชันตั้งค่า) วัตถุที่สร้างขึ้นด้วย new จะถูกส่งกลับมายังตัวแปร car
วิธีนี้มีปัญหาเดียวกับวิธีทางโครงสร้างเก่าในการจัดการกับวิธีของวัตถุ แนะนำอย่างแข็งขันว่า หากไม่มีทางอื่น ๆ แล้ว ก็เปิดใจให้หลีกเลี่ยงใช้วิธีนี้
ใช้วิธีใด
เหมือนที่กล่าวไปแล้ว ที่ถูกใช้งานที่สุดในปัจจุบันคือวิธีผสมของฟังก์ชันตั้งค่า/โปรโตไทป์。นอกจากนี้ วิธีเรียกใช้วิธีแรกของตัวเริ่มต้นยังเป็นที่นิยม เช่นเดียวกับวิธีฟังก์ชันตั้งค่า/โปรโตไทป์ ในเชิงทางฟังก์ชันนี้ คุณสามารถใช้วิธีทั้งสองได้
ตัวอย่าง
ข้อน่าสนใจของวัตถุคือวิธีที่พวกมันแก้ปัญหา。ปัญหาที่ทั่วไปใน ECMAScript คือ การผสมผสานระดับสตริง。เหมือนกับภาษาอื่น ๆ สตริงใน ECMAScript ไม่สามารถเปลี่ยนแปลงได้ คือ ค่าของมันไม่สามารถเปลี่ยนแปลงได้。โปรดพิจารณารหัสด้านล่าง:
var str = "hello "; str += "world";
ในต้นทางรหัสนี้ทำงานขั้นตอนดังนี้
- สร้างตัวแปรข้อความเก็บ "hello "
- สร้างตัวแปรข้อความเก็บ "world"
- สร้างตัวแปรข้อความเก็บผลลัพธ์ของการเชื่อมโยง
- คัดลอกสิ่งที่อยู่ใน str ให้ที่ผลลัพธ์
- คัดลอก "world" ไปที่ผลลัพธ์
- ปรับปรุง str ให้ไปที่ผลลัพธ์
ในการเชื่อมต่อตัวแปรข้อความแล้วจะทำงานขั้นตอน 2 ถึง 6 ทุกครั้ง ทำให้ปฏิบัติการนี้เสียเวลามาก หากทำการเรียกใช้ครั้งหลายร้อยหรือหลายพันครั้ง จะทำให้เกิดปัญหาประสิทธิภาพ แนะนำวิธีแก้ปัญหาดังกล่าวคือใช้ตัวแปร Array ในการเก็บตัวแปรข้อความแล้วใช้ join() ด้วยตัวแปรว่าง
var arr = new Array(); arr[0] = "hello "; arr[1] = "world"; var str = arr.join(" ");
ดังนั้น ไม่ว่าจะมีตัวแปรข้อความเข้าไปในตัวแปรแถวเท่าไรก็ไม่เป็นปัญหา เพราะการเชื่อมโยงตัวแปรจะทำงานเมื่อเรียกใช้ join() แล้วเท่านั้น ขณะนี้ ขั้นตอนที่ทำงานคือ
- สร้างตัวแปรข้อความเก็บผลลัพธ์
- คัดลอกแต่ละตัวแปรข้อความเข้าไปในตำแหน่งที่เหมาะสมในผลลัพธ์
ถึงแม้ว่ายุทธวิธีนี้ดีมาก แต่ยังมีวิธีที่ดีขึ้น ปัญหาคือรหัสนี้ไม่สามารถแสดงความตั้งใจของมันได้อย่างเห็นชัดเจน ในการทำให้ง่ายต่อการเข้าใจ สามารถบรรจุความสำคัญดังกล่าวด้วยชั้น StringBuffer ได้
function StringBuffer () { this._strings_ = new Array(); } StringBuffer.prototype.append = function(str) { this._strings_.push(str); }; StringBuffer.prototype.toString = function() { return this._strings_.join(" "); };
นี่คือรหัสที่ต้องจำหนดความสำคัญก่อนที่จะเข้าสู่คุณสมบัติ strings ซึ่งเป็นคุณสมบัติเปิดเผยด้านหลัง มีเมธอดสองเมธอดคือ append() และ toString() โดยเมธอด append() มีตัวแปรค่าหนึ่งซึ่งใส่ค่านี้เข้าไปในตัวแปรแถวซึ่งเป็นแถวของค่าตัวแปรตัวเดียว โดยเมธอด toString() ทำการเรียกใช้ join() ของตัวแปรแถวแล้วกลับค่าที่เป็นแถวที่เชื่อมโยงกันตัวเดียว สำหรับการเชื่อมต่อตัวแปร StringBuffer โดยตัวแปร StringBuffer ใช้รหัสดังนี้
var buffer = new StringBuffer (); buffer.append("hello "); buffer.append("world"); var result = buffer.toString();
สามารถทดสอบประสิทธิภาพของ StringBuffer และวิธีเชื่อมต่อของตัวอักษรโดยใช้รหัสด้านล่างนี้
var d1 = new Date(); var str = ""; for (var i=0; i < 10000; i++) { str += "text"; } var d2 = new Date(); document.write("Concatenation with plus: ") + (d2.getTime() - d1.getTime()) + " milliseconds"); var buffer = new StringBuffer(); d1 = new Date(); for (var i=0; i < 10000; i++) { buffer.append("text"); } var result = buffer.toString(); d2 = new Date(); document.write("<br />Concatenation with StringBuffer: ") + (d2.getTime() - d1.getTime()) + " milliseconds");
รหัสนี้ทำการทดสอบการผสมผสานของตัวอักษรสองครั้ง ครั้งแรกใช้เครื่องหมายบวก ครั้งที่สองใช้ชั้น StringBuffer แต่ละการปฏิบัติเชื่อมต่อ 10000 ตัวอักษร ค่าของ Date คือ d1 และ d2 ใช้ในการตรวจสอบเวลาที่ต้องใช้ในการปฏิบัติการ โปรดจำได้ว่า เมื่อสร้างวัตถุ Date โดยไม่มีตัวเลือก จะมีค่าของวัตถุเป็นวันและเวลาปัจจุบัน ในการคำนวณเวลาที่ใช้ในการปฏิบัติการเชื่อมต่อ จะต้องการหาค่ามิลลิเซกันด์ของวันที่ (ด้วยกำหนดการกลับค่าโดยใช้ getTime() กำหนดค่ากลับ) และหาค่าที่ต่างกัน นี่เป็นวิธีที่มักใช้เพื่อวัดประสิทธิภาพของ JavaScript ผลที่ได้จากการทดสอบนี้จะช่วยให้คุณเปรียบเทียบประสิทธิภาพระหว่างการใช้ StringBuffer กับการใช้เครื่องหมายบวก
- หน้าก่อนหน้า โดยสายวัตถุ
- หน้าต่อไป แก้ไขวัตถุ