อาร์กิวเมนต์เริ่มต้น Javascript ที่มีการกำหนดขอบเขตบล็อกล้มเหลวบน iOS เท่านั้น


9

try {
  const val = 'correct value';
  (() => {
    ((arg = val) => {
      const val = 'ignored value';
      alert(arg);
    })();
  })();
} catch (err) {
  alert(err.message || 'Unknown error');
}

บน OS X Chrome, OS X Safari, Android Chrome, Windows Chrome, Windows Firefox และแม้แต่ Windows Edge จะแจ้งเตือน "ค่าที่ถูกต้อง" บน iOS Safari และ iOS Chrome จะแจ้งเตือน "ไม่พบตัวแปร: val"

ตัวอย่างต่อไปนี้ทำงานบน iOS:

ไม่ใช้อาร์กิวเมนต์เริ่มต้น (ตัวอย่าง 2):

try {
  const val = 'correct value';
  (() => {
    alert(val);
    (() => {
      const val = 'wrong value';
    })();
  })();
} catch (err) {
  alert(err.message || 'Unknown error');
}

ไม่มีฟังก์ชั่นซ้อนกัน (ตัวอย่างข้อมูล 3):

try {
  const val = 'correct value';
  ((arg = val) => {
    const val = 'ignored value';
    alert(val || 'wrong value');
  })();
} catch (err) {
  alert(err.message || 'Unknown error');
}

ไม่ลบล้างตัวแปร (ตัวอย่างข้อมูล 4):

try {
  const val = 'correct value';
  (() => {
    ((arg = val) => {
      alert(arg);
    })();
  })();
} catch (err) {
  alert(err.message || 'Unknown error');
}

บล็อกขอบเขตแทนฟังก์ชัน (ตัวอย่างข้อมูล 5):

try {
  const val = 'correct value';
  {
    ((arg = val) => {
      const val = 'ignored value';
      alert(arg);
    })();
  }
} catch (err) {
  alert(err.message || 'Unknown error');
}

จากตัวอย่าง 3 เป็นที่ชัดเจนว่าการvalเข้าarg = valควรมาจากขอบเขตหลักไม่ใช่ขอบเขตของฟังก์ชันภายใน

ในตัวอย่างแรกเบราว์เซอร์ไม่สามารถหาได้valในขอบเขตปัจจุบัน แต่แทนที่จะตรวจสอบขอบเขตบรรพบุรุษนั้นจะใช้ขอบเขตลูกซึ่งทำให้โซนตายชั่วคราว

นี่เป็นข้อบกพร่องของ iOS หรือฉันเข้าใจผิดว่าพฤติกรรมของ JS เหมาะสมหรือไม่

ข้อผิดพลาดนี้เกิดขึ้นในผลลัพธ์ Webpack + Babel + Terser ของเราดังนั้นเราจึงไม่สามารถเขียนรหัสซ้ำเพื่อหลีกเลี่ยงข้อบกพร่องนี้

คำตอบ:


3

ผมคิดว่านี่เป็นผลที่ไม่พึงประสงค์ของการดำเนินงานที่รถของค่าเริ่มต้น Param และ TDZs ฉันสงสัยว่า iOS Safari คิดว่าคุณกำลังพยายามมอบหมายสิ่งที่คุณยังไม่ได้เริ่มต้น

สำหรับการอ้างอิง - ตำแหน่งข้อผิดพลาด:

ป้อนคำอธิบายรูปภาพที่นี่


วิธีแก้ปัญหา 1 อย่าเริ่มต้นขอบเขตภายในที่มีชื่อเดียวกันกับพารามิเตอร์เริ่มต้น & ขอบเขตด้านนอก

try {
    const val = 'correct value';
    (() => {
        ((arg = val) => {
            const val_ = 'ignored value';       // <----
            alert(arg);
        })();
    })();
} catch (err) {
    console.error(err);
    console.error('msg', err.message || 'Unknown error');
}

วิธีแก้ปัญหา 2

บังคับconstให้let:

try {
    let val = 'correct value';                 // <----
    (() => {
        ((arg = val) => {
            const val = 'ignored value';
            alert(arg);
        })();
    })();
} catch (err) {
    console.error(err);
    console.error('msg', err.message || 'Unknown error');
}

วิธีแก้ปัญหา 3 อย่าเริ่มต้นใหม่const valในช่วงปิดท้ายสุดเลย:

try {
    const val = 'correct value';
    (() => {
        ((arg = val) => {
            // const val = 'ignored value';      // <--
            alert(arg);
        })();
    })();
} catch (err) {
    console.error(err);
    console.error('msg', err.message || 'Unknown error');
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.