ภาพรวมแนวคิดนี้
เมื่อมีการสร้างฟังก์ชั่นคำหลักนี้จะถูกสร้างขึ้น (ในพื้นหลัง) ซึ่งเชื่อมโยงกับวัตถุและฟังก์ชั่นทำงานในวัตถุนี้ กล่าวอีกนัยหนึ่งคำหลักที่สามารถใช้ในฟังก์ชั่นการอ้างอิงถึงวัตถุและฟังก์ชั่นคือคุณสมบัติหรือวิธีการของวัตถุนั้น
ลองดูที่วัตถุนี้:
<! doctype html> <html lang = "en"> <body> <body> <script> var code = {Living: true, อายุ: 23, เพศ: 'ชาย', getGender: function () {return cody.gender;}}; console.log (cody.getgender ()); // logs 'male' </script> </body> </html>โปรดทราบว่าในฟังก์ชั่น getGender เนื่องจากภายในวัตถุ Cody เราสามารถรับแอตทริบิวต์เพศ (นั่นคือ Cody.gender) ผ่าน นอกจากนี้คุณยังสามารถใช้สิ่งนี้เพื่อรับวัตถุ Cody เพราะจุดนี้ไปยังวัตถุ Cody
<! doctype html> <html lang = "en"> <body> <body> <script> var code = {Living: true, อายุ: 23, เพศ: 'ชาย', getGender: function () {return.gender;}}; console.log (cody.getgender ()); // logs 'male' </script> </body> </html>ในนี้เพศนี้ชี้ไปที่วัตถุ Cody และฟังก์ชั่น getGender สามารถทำงานบนวัตถุ Cody
หัวข้อเกี่ยวกับเรื่องนี้อาจทำให้สับสนเล็กน้อย แต่ก็ไม่จำเป็นต้องเป็น เพียงจำไว้ว่าโดยปกติวัตถุที่ชี้ไปที่เป็นวัตถุที่มีฟังก์ชั่นไม่ใช่ฟังก์ชันเอง (แน่นอนว่ามีข้อยกเว้นเช่นการใช้คำหลักใหม่หรือการโทร () และใช้ ())
เคล็ดลับสำคัญ
- คำหลักนี้เป็นเหมือนตัวแปรอื่น ๆ ความแตกต่างเพียงอย่างเดียวคือคุณไม่สามารถเปลี่ยนแปลงได้
- แตกต่างจากพารามิเตอร์และตัวแปรอื่น ๆ ที่ส่งผ่านไปยังฟังก์ชันนี่เป็นคำหลัก (ไม่ใช่คุณสมบัติ) ในวัตถุที่เรียกฟังก์ชัน
จะกำหนดมูลค่าของสิ่งนี้ได้อย่างไร?
สิ่งนี้จะถูกส่งผ่านไปยังฟังก์ชั่นทั้งหมดและค่าของมันขึ้นอยู่กับว่าฟังก์ชันถูกเรียกเมื่อทำงาน โปรดทราบที่นี่เพราะนี่เป็นสถานที่ที่พิเศษมากที่คุณต้องจดจำ
ในรหัสต่อไปนี้วัตถุ MyObject มีคุณสมบัติ SaysFoo ซึ่งชี้ไปที่ฟังก์ชั่น SaysFoo เมื่อฟังก์ชั่น Sayfoo ถูกเรียกในโดเมนทั่วโลกสิ่งนี้ชี้ไปที่วัตถุหน้าต่าง เมื่อ MyObject เรียกฟังก์ชันสิ่งนี้ชี้ไปที่ myObject
เนื่องจาก MyObject มีคุณสมบัติที่เรียกว่า Foo จึงใช้ที่นี่
<! doctype html> <html lang = "en"> <body> <body> <script> var foo = 'foo'; var myObject = {foo: 'ฉันคือ myobject.foo'}; var sayfoo = function () {console.log (นี้ ['foo']); - // ให้คุณสมบัติ myObject เป็น sayfoo และให้มันชี้ไปที่ฟังก์ชัน sayfoo myobject.sayfoo = sayfoo; myobject.sayfoo (); // logs 'ฉันเป็น myobject.foo' 12 sayfoo (); // logs 'foo' </script> </body> </html>เป็นที่ชัดเจนว่าค่าของสิ่งนี้ขึ้นอยู่กับว่าฟังก์ชันถูกเรียกเมื่อใด myobject.sayfoo และ sayfoo ทั้งสองชี้ไปที่ฟังก์ชั่นเดียวกัน แต่บริบทของการโทร sayfoo () แตกต่างกันดังนั้นค่าของสิ่งนี้จึงแตกต่างกัน ด้านล่างเป็นรหัสที่คล้ายกันวัตถุหัว (หน้าต่าง) ถูกใช้อย่างชัดเจนโดยหวังว่ามันจะเป็นประโยชน์กับคุณ
<! doctype html> <html lang = "en"> <body> <body> <pristr> window.foo = 'foo'; window.myObject = {foo: 'ฉันคือ myobject.foo'}; window.sayfoo = function () {! console.log (this.foo); - window.myobject.sayfoo = window.sayfoo; window.myobject.sayfoo (); window.sayfoo (); </script> </body> </html>ตรวจสอบให้แน่ใจว่าเมื่อคุณมีการอ้างอิงหลายครั้งที่ชี้ไปที่ฟังก์ชั่นเดียวกันคุณรู้ได้อย่างชัดเจนว่าค่าของการเปลี่ยนแปลงนี้ขึ้นอยู่กับบริบทของฟังก์ชั่นการโทร
เคล็ดลับสำคัญ
- ตัวแปรและพารามิเตอร์ทั้งหมดยกเว้นสิ่งนี้เป็นของขอบเขตตัวแปรสแตติก
สิ่งนี้ชี้ไปที่วัตถุหัวภายในฟังก์ชันฝังตัว
คุณอาจสงสัยว่าจะเกิดอะไรขึ้นเมื่อใช้สิ่งนี้ในฟังก์ชั่นที่ฝังอยู่ในฟังก์ชั่นอื่น น่าเสียดายที่ ECMA 3 สิ่งนี้ไม่เป็นไปตามกฎ แต่ไม่ได้ชี้ไปที่วัตถุที่ฟังก์ชั่นเป็นของ แต่ไปยังวัตถุหัว (วัตถุหน้าต่างของเบราว์เซอร์)
ในรหัสต่อไปนี้สิ่งนี้ใน func2 และ func3 ไม่ได้ชี้ไปที่ myObject อีกต่อไป แต่เป็นวัตถุหัว
<! doctype html> <html lang = "en"> <body> <body> <script> var myObject = {func1: function () {console.log (นี่); // บันทึก myObject varfunc2 = function () {console.log (นี่); // หน้าต่างบันทึกและจะทำเช่นนั้นจากจุดนี้ใน varfunc3 = function () {console.log (นี่); // บันทึกหน้าต่างเนื่องจากเป็นวัตถุหัว} (); - - myobject.func1 (); </script> </body> </html>อย่างไรก็ตามใน ECMASCript 5 ปัญหานี้จะได้รับการแก้ไข ตอนนี้คุณควรตระหนักถึงปัญหานี้โดยเฉพาะอย่างยิ่งเมื่อคุณผ่านค่าของฟังก์ชั่นหนึ่งไปยังอีกฟังก์ชัน
ดูรหัสด้านล่างส่งฟังก์ชันที่ไม่ระบุชื่อไปยัง foo.func1 เมื่อมีการเรียกฟังก์ชันที่ไม่ระบุชื่อใน foo.func1 (ฟังก์ชั่นซ้อนกันในฟังก์ชั่นอื่น) สิ่งนี้จะชี้ไปที่วัตถุหัวในฟังก์ชันที่ไม่ระบุชื่อ
<! doctype html> <html lang = "en"> <body> <body> <script> var foo = {func1: ฟังก์ชั่น (bar) {bar (); // หน้าต่างบันทึกไม่ใช่ foo console.log (นี่); // คำหลักนี้ที่นี่จะเป็นการอ้างอิงถึงวัตถุ foo}}; foo.func1 (function () {console.log (นี่)}); </script> </body> </html>ตอนนี้คุณจะไม่ลืมว่าถ้าฟังก์ชั่นที่มีอยู่ในฟังก์ชั่นอื่นหรือเรียกโดยฟังก์ชั่นอื่นค่าของสิ่งนี้จะชี้ไปที่วัตถุหัว (อีกครั้งสิ่งนี้จะถูกแก้ไขใน ECMASCript 5)
แก้ปัญหาฟังก์ชั่นซ้อนกัน
เพื่อป้องกันไม่ให้สิ่งนี้หายไปคุณสามารถใช้โซ่ขอบเขตในฟังก์ชั่นหลักเพื่อบันทึกการอ้างอิงถึงสิ่งนี้ ในรหัสต่อไปนี้การใช้ตัวแปรที่เรียกว่าโดยใช้ขอบเขตเราสามารถบันทึกบริบทฟังก์ชันได้ดีขึ้น
<! doctype html> <html lang = "en"> <body> <body> <script> var myObject = {myProperty: 'icanseeHelight', myMethod: function () {var that = this; // เก็บข้อมูลอ้างอิงถึง (IEMyObject) นี้ในฟังก์ชัน MyMethod ขอบเขต VarhelperFunction () {// childfunction var function ฟังก์ชัน helperfunction () {// childfunction // logs 'ฉันสามารถเห็นแสง' ผ่านโซ่ขอบเขตเพราะ // logs 'ฉันสามารถเห็น Light' console.log (นี่); // บันทึกวัตถุหน้าต่างถ้าเราไม่ใช้ "นั่น"} (); }} myObject.mymethod (); // เรียกใช้ mymethod </script> </body> </html>ควบคุมค่าของสิ่งนี้
ค่าของสิ่งนี้มักขึ้นอยู่กับบริบทที่เรียกใช้ฟังก์ชัน (เว้นแต่จะใช้คำหลักใหม่ซึ่งจะถูกนำมาใช้ในภายหลัง) แต่คุณสามารถใช้ใช้ () หรือการโทร () เพื่อระบุวัตถุที่ชี้ไปที่เมื่อฟังก์ชันถูกเรียกให้เปลี่ยน/ควบคุมค่าของสิ่งนี้ การใช้สองวิธีนี้ก็เหมือนกับการพูดอีกครั้ง: "เฮ้เรียกฟังก์ชัน X แต่ให้วัตถุ Z สร้างค่านี้" การทำเช่นนั้นค่าเริ่มต้นของ JavaScript นี้จะมีการเปลี่ยนแปลง
ด้านล่างเราสร้างวัตถุและฟังก์ชั่นจากนั้นเราเรียกใช้ฟังก์ชันผ่านการโทร () ดังนั้นในฟังก์ชั่นจะชี้ไปที่ myojbect ฟังก์ชัน myfunction นี้ทำงานบน myObject แทนวัตถุหัวดังนั้นเราจึงเปลี่ยนวัตถุที่ชี้ไปที่สิ่งนี้ใน myfunction
<! doctype html> <html lang = "en"> <body> <body> <script> var myObject = {}; var myfunction = function (param1, param2) {// setViacall () 'this'points ไปยังวัตถุของฉันเมื่อฟังก์ชั่นถูกเรียกใช้ this.foo = param1; this.bar = param2; console.log (นี่); // บันทึกวัตถุ {foo = 'foo', bar = 'bar'}}; myfunction.call (myobject, 'foo', 'bar'); // revoke function ตั้งค่านี้เป็น myObject console.log (myObject) // logs object {foo = 'foo', bar = 'bar'} </script> </body> </html>ในตัวอย่างข้างต้นเราใช้การโทร (), ใช้ () สามารถนำไปใช้กับการใช้งานเดียวกัน ความแตกต่างระหว่างทั้งสองคือวิธีที่พารามิเตอร์ถูกส่งผ่านไปยังฟังก์ชัน ใช้การโทร () พารามิเตอร์จะถูกคั่นด้วยเครื่องหมายจุลภาคและใช้ () และพารามิเตอร์จะถูกส่งผ่านในอาร์เรย์ ต่อไปนี้เป็นรหัสเดียวกัน แต่ใช้ใช้ ()
<! doctype html> <html lang = "en"> <body> <body> <script> var myObject = {}; var myfunction = function (param1, param2) {// ตั้งค่าผ่านการใช้งาน () ซึ่งชี้ไปที่วัตถุของฉันเมื่อฟังก์ชั่นถูกเรียกใช้ this.foo = param1; this.bar = param2; console.log (นี่); // บันทึกวัตถุ {foo = 'foo', bar = 'bar'}}; myfunction.apply (myobject, ['foo', 'bar']); // เรียกใช้ฟังก์ชันตั้งค่า console.log (myObject); // บันทึกวัตถุ {foo = 'foo', bar = 'bar'} </script> </body> </html>ใช้สิ่งนี้ในตัวสร้างที่กำหนดเอง
เมื่อฟังก์ชั่นถูกทริกเกอร์ด้วยคำหลักใหม่ค่าของสิ่งนี้จะถูกประกาศในคอนสตรัคเตอร์เพื่อชี้ไปที่อินสแตนซ์เอง กล่าวอีกนัยหนึ่ง: ในตัวสร้างเราสามารถใช้สิ่งนี้เพื่อระบุวัตถุก่อนที่มันจะถูกสร้างขึ้นจริง สิ่งนี้ดูเหมือนจะเปลี่ยนค่านี้เป็นโทร () หรือใช้ ()
ด้านล่างเราสร้างบุคคลที่สร้างขึ้นซึ่งชี้ไปที่วัตถุที่สร้างขึ้น เมื่อวัตถุของบุคคลถูกสร้างขึ้นสิ่งนี้ชี้ไปที่วัตถุนี้และใส่ชื่อคุณสมบัติในวัตถุและค่าคือค่าพารามิเตอร์ (ชื่อ) ที่ส่งไปยังตัวสร้างนี้
<! doctype html> <html lang = "en"> <body> <body> <script> var person = function (ชื่อ) {this.name = name || 'Johndoe'; // สิ่งนี้จะอ้างถึงรหัสที่สร้างขึ้นทันที} var code = บุคคลใหม่ ('Cody Lindley'); // สร้างอินสแตนซ์ขึ้นอยู่กับผู้สร้างคอนโซลคอนโซล log (cody.name); // logs 'Cody Lindley' </script> </body> </html>ด้วยวิธีนี้เมื่อตัวสร้างถูกทริกเกอร์ด้วยคำหลักใหม่จุดนี้ชี้ไปที่ "วัตถุที่จะสร้าง" จากนั้นหากเราไม่ใช้คำหลักใหม่ค่าของสิ่งนี้จะชี้ไปที่บริบทที่กระตุ้นให้บุคคล - นี่คือวัตถุหัว มาดูรหัสด้านล่าง
<! doctype html> <html lang = "en"> <body> <body> <script> var person = function (ชื่อ) {this.name = name || 'johndoe'; } var code = person ('Cody Lindley'); // ประกาศว่าเราไม่ได้ใช้ 'ใหม่' console.log (cody.name); // ไม่ได้กำหนดค่าจะถูกตั้งค่าจริงที่ window.name console.log (window.name); // logs 'Cody Lindley' </script> </body> </html>สิ่งนี้ชี้ไปที่อินสแตนซ์ตัวสร้างภายในวิธีการต้นแบบ
เมื่อใช้วิธีการเป็นคุณสมบัติต้นแบบของตัวสร้างสิ่งนี้ในวิธีนี้จะชี้ไปที่อินสแตนซ์ของวิธีทริกเกอร์ ที่นี่เรามีบุคคล () ตัวสร้างซึ่งต้องการชื่อเต็มของบุคคล เพื่อให้ได้ชื่อเต็มเราได้เพิ่มวิธี atismyfullname ให้กับบุคคล prototype และอินสแตนซ์ของบุคคลทั้งหมดสืบทอดวิธีนี้ ในวิธีนี้ชี้ไปที่อินสแตนซ์ (และคุณสมบัติ) ที่เรียกใช้วิธีนี้
ด้านล่างฉันสร้างวัตถุสองคน (โคดี้และลิซ่า) และวิธีการที่สืบทอดมาจากสิ่งที่สืบทอดมานั้นมีจุดนี้ในอินสแตนซ์นี้
<! doctype html> <html lang = "en"> <body> <body> <script> var person = function (x) {ถ้า (x) {this.fullname = x}; - person.prototype.whatismyfullname = function () {return this.fullname; // 'นี่' หมายถึงอินสแตนซ์ที่สร้างจากบุคคล ()} var code = บุคคลใหม่ ('Cody Lindley'); var lisa = คนใหม่ ('Lisa Lindley'); // เรียกเมธอด Whatismyfullname ที่สืบทอดมาซึ่งใช้สิ่งนี้เพื่ออ้างถึงอินสแตนซ์คอนโซลล็อก (cody.whatismyfullname (), lisa.whatismymyfullname ()); /* ห่วงโซ่ต้นแบบยังคงมีผลอยู่ดังนั้นหากอินสแตนซ์ไม่มีคุณสมบัติ FullName มันจะมองหามันในห่วงโซ่ต้นแบบ ด้านล่างเราเพิ่มคุณสมบัติ FullName ให้กับทั้งต้นแบบของบุคคลและต้นแบบวัตถุ ดูหมายเหตุ */object.prototype.fullName = 'John doe'; var John = คนใหม่ (); // ไม่มีการโต้แย้งใด ๆ ดังนั้นจึงไม่ได้เพิ่ม FullName ลงใน Instance Console.log (John.whatismyfullname ()); // logs 'John Doe' </script> </body> </html>ใช้สิ่งนี้ในวิธีการภายในวัตถุต้นแบบและสิ่งนี้ชี้ไปที่อินสแตนซ์ หากอินสแตนซ์ไม่มีคุณสมบัติการค้นหาต้นแบบจะเริ่มขึ้น
คำใบ้
- หากวัตถุที่ชี้ไปที่สิ่งนี้ไม่มีคุณสมบัติที่คุณต้องการค้นหากฎหมายที่ใช้กับแอตทริบิวต์ใด ๆ ก็มีผลบังคับใช้ที่นี่นั่นคือแอตทริบิวต์จะ "ค้นหา" ตามห่วงโซ่ต้นแบบ ดังนั้นในตัวอย่างของเราหากอินสแตนซ์ไม่มีคุณสมบัติ FullName ดังนั้น FullName จะค้นหา person.prototype.fullName แล้ว Object.prototype.fullname
หากต้องการดูไวยากรณ์ JavaScript เพิ่มเติมคุณสามารถติดตาม: "คำแนะนำอ้างอิง JavaScript" และ "คู่มือสไตล์รหัส JavaScript" ฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น