เหตุใด "สิ่งนี้" ในฟังก์ชันที่ไม่ระบุตัวตนจึงไม่ถูกกำหนดเมื่อใช้อย่างเข้มงวด


86

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

ตัวอย่าง:

(function () {
    "use strict";

    this.foo = "bar"; // *this* is undefined, why?
}());

ทดสอบในซอ: http://jsfiddle.net/Pyr5g/1/ ตรวจสอบคนตัดไม้ (firebug)


4
โปรดทราบว่าสิ่งนี้ไม่เกี่ยวข้องกับฟังก์ชันที่ไม่ระบุชื่อ แต่เป็นวิธีการเรียกใช้ ดูซอที่แก้ไขนี้ (ดูในบันทึกของคอนโซล)
Phrogz

@Phrogz: นี่อาจเป็นที่มาของความสับสน ขอบคุณที่ชี้ให้เห็น
T. Junghans

คำตอบ:


102

เป็นเพราะจนถึง ECMAscript 262 ฉบับที่ 5 มีความสับสนอย่างมากหากผู้ที่ใช้งานอยู่constructor patternลืมใช้newคำหลัก หากคุณลืมใช้newเมื่อเรียกใช้ฟังก์ชันตัวสร้างใน ES3 ให้thisอ้างถึงวัตถุส่วนกลาง (windowในเบราว์เซอร์) และคุณจะโคลนอ็อบเจ็กต์ส่วนกลางด้วยตัวแปร

นั่นคือพฤติกรรมที่น่ากลัวและเพื่อให้คนที่ ECMA ตัดสินใจเพียงเพื่อให้ชุดที่จะthisundefined

ตัวอย่าง:

function myConstructor() {
    this.a = 'foo';
    this.b = 'bar';
}

myInstance     = new myConstructor(); // all cool, all fine. a and b were created in a new local object
myBadInstance  = myConstructor(); // oh my gosh, we just created a, and b on the window object

บรรทัดสุดท้ายจะทำให้เกิดข้อผิดพลาดใน ES5 ที่เข้มงวด

"TypeError: this is undefined"

(ซึ่งเป็นพฤติกรรมที่ดีกว่ามาก)


4
สิ่งนี้สมเหตุสมผล คุณมีข้อมูลอ้างอิงเพื่อสำรองคำสั่งหรือไม่?
Rob W

1
@ RobW: ฉันจะต้องค้นหาตัวเอง แต่ฉันได้ยินดักลาสคร็อกฟอร์ดหลายครั้งที่เขาพูดนี่คือเหตุผลของการตัดสินใจครั้งนั้น
jAndy

1
มีการกล่าวถึงใน JavaScript: ส่วนที่ดีโดย Crockford มีการอธิบายรายละเอียด ไม่เกี่ยวกับการตัดสินใจของ ECMA
madr

1
นี่คือเหตุผลเชิงตรรกะว่าทำไมโหมดที่เข้มงวดจึงกำหนดค่าเริ่มต้นนี้เป็น undefined เหตุผลเชิงตรรกะอื่น ๆ คือประสิทธิภาพเหตุผลเชิงตรรกะอื่น ๆthis === windowคือทำให้เกิดความสับสนและรั่วไหลขอบเขตทั่วโลกเป็นโทเค็นในฟังก์ชัน
Raynos

2
@jAndy: ขอบคุณสำหรับคำตอบ สิ่งนี้สมเหตุสมผล ฉันยังพบคำอธิบายสั้น ๆ เกี่ยวกับการเปลี่ยนแปลงนี้ในjavascriptweblog.wordpress.com/2011/05/03/… : "โดยเฉพาะอย่างยิ่งถ้าอาร์กิวเมนต์แรกที่จะเรียกหรือใช้เป็นค่าว่างหรือไม่ได้กำหนดค่านี้ของฟังก์ชันที่เรียกใช้ จะไม่ถูกแปลงเป็นวัตถุส่วนกลาง "
T. Junghans

15

มีกลไกที่เรียกว่า "มวย" ซึ่งห่อหุ้มหรือเปลี่ยนthisวัตถุก่อนเข้าสู่บริบทของฟังก์ชันที่เรียกว่า ในกรณีของคุณค่าthisควรเป็นundefinedเพราะคุณไม่ได้เรียกใช้ฟังก์ชันเป็นวิธีการของวัตถุ ถ้าโหมดไม่เข้มงวดในกรณีนี้windowวัตถุนี้จะถูกแทนที่ ในstrictโหมดไม่เปลี่ยนแปลงเสมอนั่นคือเหตุผลว่าทำไมจึงเป็นเช่นนั้นundefinedที่มาที่นี่

สามารถดูข้อมูลเพิ่มเติมได้ที่
https://developer.mozilla.org/en/JavaScript/Strict_mode


@samuel เราจะกำหนดตัวแปรให้กับวัตถุหน้าต่างในโหมดเข้มงวดได้อย่างไร?
Null Pointer

8

ตามคำตอบของ Stack Overflowนี้คุณสามารถใช้thisภายในฟังก์ชันที่ไม่ระบุตัวตนได้เพียงแค่เรียก.call(this)ที่ส่วนท้ายของมัน

(function () {
    "use strict";

    this.foo = "bar";
}).call(this);

4
โปรดทราบว่าthisจะเป็นWindowวัตถุในกรณีนี้ซึ่งอาจไม่ต้องการ
Ninjakannon

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