ในจาวาสคริปต์สามารถสร้างอาร์เรย์ได้โดยใช้ตัวสร้างอาร์เรย์หรือสร้างขึ้นอย่างรวดเร็วโดยใช้ [] ซึ่งเป็นวิธีที่ต้องการ อาร์เรย์เป็นต้นแบบที่สืบทอดมาจากวัตถุและไม่มีค่าส่งคืนพิเศษสำหรับ typeof แต่จะส่งคืน 'วัตถุ' เท่านั้น
ใน JS อาจกล่าวได้ว่าทุกอย่างเป็นวัตถุและอาร์เรย์ก็เป็นอาร์เรย์
วัตถุจำนวนมากมีวิธีการที่สะดวกมากมายเช่นการกด, concat, slice, ฯลฯ ของอาร์เรย์ แต่ถ้าวัตถุบางอย่างไม่ใช้วิธีเหล่านี้เรายังต้องการใช้ฟังก์ชั่นเหล่านี้ แล้วฉันควรทำอย่างไร?
1. วิธีการหลายอย่างให้การใช้งานที่มีประสิทธิภาพมากและเราสามารถจำลองการใช้งานได้
ตัวอย่างเช่นเบราว์เซอร์ด้านล่าง IE8 ไม่รองรับวิธีดัชนีอาร์เรย์ เพื่อให้ดัชนีสนับสนุนอาร์เรย์เราสามารถเขียนวิธีการของเราเองเพื่อใช้วิธีการดัชนีของวิธีการ:
(กด F12 เพื่อแก้ไขข้อบกพร่องด้วย IE Browser เพื่อเลือกรุ่นเบราว์เซอร์เป็น IE5)
var arr = [,,]; if (array.prototype.indexof) {แจ้งเตือน ("เบราว์เซอร์ของคุณรองรับวิธีการดัชนี");} else {alert ("เบราว์เซอร์ของคุณไม่สนับสนุนวิธีการดัชนี"); i ++) {ถ้า (นี่ [i] == รายการ) {return i;}} return -;}} การแจ้งเตือน (arr.indexof ()); แจ้งเตือน (arr.indexof ());แน่นอนว่าวิธีนี้เป็นขยะมาก ฉันจะไม่น่าเกลียดในการใช้งานที่เฉพาะเจาะจงที่นี่และจัดทำสำเนาเวอร์ชันบน Baidu:
หากคุณสนใจคุณสามารถดูว่าเครื่องมือ V8 ถูกนำไปใช้อย่างไร: https://github.com/v8/v8/blob/master/src/js/array.js
if (! array.prototype.indexof) {array.prototype.indexof = function (elt /*, จาก* /) {var len = this.length >>>; var จาก = number (อาร์กิวเมนต์ []) || ; จาก = (จาก <)? math.ceil (จาก): math.floor (จาก); ถ้า (จาก <) จาก+= len; สำหรับ (; จาก <len; จาก ++) {ถ้า (จากใน && this [จาก] === elt) กลับจาก;} return -;};};2. การสืบทอดการโทรและใช้วิธีการ
หากเรามีวัตถุมันไม่ยากเลยที่จะเขียนวัตถุแต่ละชิ้นเพื่อนำไปใช้ด้วยตัวเอง?
ในภาษาระดับสูงเราสามารถใช้การสืบทอดเพื่อแก้ปัญหาเช่นรหัส Java ต่อไปนี้:
คลาสสาธารณะ Mylist <E> ขยาย ArrayList <E> {โมฆะสาธารณะ myAdd (e e) {super.add (e); system.out.println ("เพิ่ม:"+e);}}แต่ไม่มีแนวคิดเรื่องการสืบทอดใน JS เราสามารถใช้การโทรและสมัครเพื่อแก้ปัญหาดังกล่าว
รหัสข้างต้นสามารถเขียนใหม่เป็น:
var myObject = function () {} myObject.prototype.add = function () {array.prototype.push.call (สิ่งนี้, อาร์กิวเมนต์); // output อาร์กิวเมนต์สำหรับ (var i =; i <arguments.length; i ++) {console.log myObject (); obj.add (,,);ที่นี่เราสามารถเห็นได้: แม้ว่าวิธี MYADD จะถูกนำไปใช้ในวิธีการสืบทอดของภาษาระดับสูง แต่วิธี MYADD สามารถผ่านพารามิเตอร์เดียวได้ในขณะนี้ หากคุณต้องการผ่านพารามิเตอร์หลายพารามิเตอร์คุณต้องเขียนโมฆะสาธารณะอื่น ๆ วิธี MyADD (e [] e) หรือแม้แต่โมฆะสาธารณะ MyADD (รายการ <E> e) JS สามารถทำได้ด้วยวิธีเดียวโดยใช้วัตถุอาร์กิวเมนต์เพื่อแสดงอินพุตพารามิเตอร์ทั้งหมดซึ่งเป็นเรื่องยากสำหรับภาษาระดับสูงที่ต้องทำ
(ในความเป็นจริง PS คุณสามารถเขียนโมฆะสาธารณะ myadd (e ... e) ใน Java นี่เป็นพารามิเตอร์ที่ไม่แน่นอนการใช้โมฆะสาธารณะ myadd (e [] e) เหมือนกัน)
การโทรและใช้วิธีการใช้เพื่อเปลี่ยนตัวชี้ของตัวชี้นี้ในฟังก์ชั่น การโทรมีพารามิเตอร์เพียงสองพารามิเตอร์และใช้โดยปกติจะใช้หลังจากทราบจำนวนพารามิเตอร์ ต่อไปนี้เป็นตัวอย่าง:
var obj = ฟังก์ชัน (ชื่อ) {this.name = name;} obj.prototype.getName = function () {return this.name;} var obj1 = ใหม่ obj ("zou"); var obj2 = {ชื่อ: 'Andy'}; var name = obj1.getName.callข้อมูลอ้างอิงคือ:
ใช้ (วัตถุ, arg1, arg2, ... )
โทร (วัตถุ, [arg1, arg2, ...... ])
สามารถติดตาม "อาร์เรย์" ได้เพียงครั้งเดียวรวมถึงพารามิเตอร์ทั้งหมด ใช้เป็นน้ำตาลวากยสัมพันธ์ หากคุณรู้จำนวนพารามิเตอร์มันจะสะดวกมากในการใช้งาน
วัตถุด้านบนสามารถเป็นโมฆะหรือไม่ได้กำหนดดังนั้นวัตถุนี้เป็นวัตถุทั่วโลก (หน้าต่าง) ตัวอย่างเช่นตัวอย่างด้านบนจะถูกติดตาม:
var name = 'goo'; แจ้งเตือน (obj1.getName.call (null)); (ในโหมดที่เข้มงวดเนื่องจากวัตถุทั่วโลกเป็นโมฆะข้อยกเว้นจะถูกโยนลง: uncaught typeError: ไม่สามารถอ่านคุณสมบัติ 'ชื่อ' ของ NULL)
3. Object.defineProperty
(หมายเหตุ: อย่าใช้คุณสมบัติประเภทนี้ด้านล่าง IE8)
Microsoft: เพิ่มคุณสมบัติให้กับวัตถุหรือแก้ไขคุณสมบัติของคุณสมบัติที่มีอยู่
getters, setters,
ในความเป็นจริงยังมีฟังก์ชั่น getters และ setter สำหรับคุณสมบัติของวัตถุใน JS แต่โดยส่วนตัวแล้วฉันคิดว่า getters และ setters ใน JS เป็นเหมือน C#
ตัวอย่างเช่นรหัสต่อไปนี้กำหนด getter/setter:
ฟังก์ชั่น myobj () {} object.defineProperty (myobj.prototype, 'ความยาว', {get: function () {return this.length_; // สิ่งนี้ไม่สามารถเป็นความยาว}, set: function (value) {return.length_ = value;}});สถานที่ที่แสดงความคิดเห็นไม่สามารถมีความยาวไม่เช่นนั้นจะถูกเรียกซ้ำอย่างไม่สิ้นสุด
คุณยังสามารถลบชุดและทำให้ตัวแปรความยาวอ่านอย่างเดียว
Object.defineProperty (myobj.prototype, 'ความยาว', {get: function () {return this.length_; // สิ่งนี้ไม่สามารถเป็นความยาว}, /*set: function (value) {return this.length_ = value;}* /}); myobj.length = 3;รหัสนี้จะโยนข้อยกเว้น: uncaught typeError: ไม่สามารถตั้งค่าความยาวคุณสมบัติของ #<myobj> ซึ่งมีเพียง getter
ในการทำให้คุณสมบัติของวัตถุอ่านอย่างเดียวคุณสามารถใช้งานเขียนได้: เท็จ
Object.defineProperty (myobj.prototype, 'ความยาว', {writable: false});เขียนได้: False ไม่สามารถอยู่ร่วมกันได้กับ Get Set มิฉะนั้นจะมีข้อผิดพลาดประเภท
สามารถกำหนดค่าได้: สามารถลบได้ด้วยคำสั่งลบ แต่คุณสมบัติที่กำหนดค่าได้ดูเหมือนจะถูกต้องในโหมดเข้มงวด รหัสดังกล่าวยังคงสามารถดำเนินการในโหมดที่ไม่ใช่ Strict: (รายงานข้อผิดพลาดในโหมดเข้มงวด)
Object.defineProperty (myobj.prototype, 'ความยาว', {กำหนดค่าได้: false}); var obj = ใหม่ myobj (); ลบ obj.length;ค่า: ระบุค่าคงที่ของวัตถุ ค่า: 10, ระบุว่าค่าเริ่มต้นของวัตถุนี้คือ 10
ในโหมดที่ไม่ใช่การ จำกัด รหัสดังกล่าวจะไม่รายงานข้อผิดพลาดและในโหมดที่เข้มงวดจะรายงานข้อผิดพลาด:
Object.defineProperty (myobj.prototype, 'ความยาว', {เขียนได้: เท็จ, ค่า: '10 '}); var obj = ใหม่ myobj (); obj.length = 100;คุณสามารถใช้ GetOwnPropertyDescriptor เพื่อรับและแก้ไขค่าเหล่านี้ ตัวอย่างเช่นตอนนี้คุณสมบัติความยาวของฉันอ่านได้อย่างเดียว
การรันรหัสดังกล่าว แต่เกิดข้อผิดพลาด:
Object.defineProperty (myobj.prototype, 'ความยาว', {ค่า:, เขียนได้: false,}); var descriptor = object.getownpropertydescriptor (myobj.prototype, "ความยาว"); uncaught typeerror: ไม่สามารถกำหนดคุณสมบัติใหม่: ความยาวนี่เป็นเพราะค่าเริ่มต้นของการกำหนดค่าเป็นเท็จ หลังจากเรียก DEFINEPROPERTY แล้วกำหนดค่าได้มีคุณสมบัติเท็จดังนั้นจึงไม่สามารถย้อนกลับได้ ไม่สามารถเปลี่ยนแปลงได้ในอนาคต
ดังนั้นคุณต้องใช้การกำหนดค่า: จริงและคุณสมบัติของวัตถุนี้สามารถแก้ไขได้ รหัสที่สมบูรณ์มีดังนี้:
Object.defineProperty (myobj.prototype, 'ความยาว', {ค่า:, เขียนได้: เท็จ, กำหนดค่า: จริง}); var descriptor = object.getOwnPropertyDescriptor (myobj.prototype, "length"); true; object.defineproperty (myobj.prototype, 'ความยาว', descriptor); myobj.prototype.length =; var obj = ใหม่ myobj (); แจ้งเตือน (obj.length);คุณสามารถเพิ่มคำอธิบายประโยคที่กำหนดค่าได้ = false;
หมายความว่าฉันได้แก้ไขคุณสมบัตินี้แล้วและคุณไม่สามารถแก้ไขได้ในอนาคต
คุณสมบัตินี้ยังมีประโยชน์ในหลายกรณี หากคุณใช้การโทรและใช้วิธีการความยาวของวัตถุจะต้องเป็นตัวแปร หากแอตทริบิวต์ความยาวของวัตถุเป็นแบบอ่านอย่างเดียวข้อยกเว้นจะถูกโยนลงเมื่อมีการโทรและสมัคร
ตัวอย่างเช่นความยาวของวัตถุ DomtokenList ไม่สามารถเปลี่ยนแปลงได้ ฉันมีวัตถุ DOM DomtokenList
แต่มันสามารถกำหนดค่าได้นั้นเป็นจริงเราสามารถแก้ไขได้เพื่อให้สามารถเปลี่ยนแปลงคุณสมบัติความยาวได้:
ดูที่การกำหนดค่านี้เป็นจริงและตัวตั้งค่าไม่ได้กำหนด มาเขียนวิธีการสำหรับมันกันเถอะใช่มั้ย
var descriptor = object.getOwnPropertyDescriptor (domtokenlist.prototype, 'length'); descriptor.set = function (value) {this.length = value;} object.defineproperty (domtokenlist.prototype, 'ความยาว', descriptor);จากนั้นเรียกใช้
มีข้อยกเว้นอีกประการหนึ่งที่ถูกโยนออกไป arnerorror: ขนาดสแต็คการโทรสูงสุดเกิน (…)
นี่เป็นเพราะเมื่อเราตั้งค่าสิ่งนี้ความยาวมันจะกลับมาอีกครั้งในวิธีการชุดนั้นที่เราเขียน
ดังนั้นเราจำเป็นต้องใช้ลบเพื่อกำจัดอิทธิพลของแอตทริบิวต์ความยาวนั่นคือ:
var descriptor = object.getOwnPropertyDescriptor (domtokenlist.prototype, 'ความยาว'); descriptor.set = ฟังก์ชั่น (ค่า) {ลบ domtokenlist.prototype.length; this.length = value;} object.defineProperty (domtokenlist.prototype, 'ความยาว', descriptor);ด้วยวิธีนี้ DomtokenList ยังสนับสนุนการผลักดันป๊อปและการดำเนินการอื่น ๆ
array.prototype.push.call (document.body.classlist, 'abc')
จากนั้นห่อหุ้ม
domtokenlist.prototype.push = function () {array.prototype.push.call (document.body.classlist, array.prototype.slice.call (อาร์กิวเมนต์));}วิธี array.prototype.slice.call (อาร์กิวเมนต์) ใช้เพื่อแปลงอาร์กิวเมนต์วัตถุเป็นอาร์เรย์