ฉันจะกำหนดหมายเลขบรรทัดปัจจุบันใน JavaScript ได้อย่างไร


96

JavaScript มีกลไกในการกำหนดหมายเลขบรรทัดของคำสั่งที่กำลังดำเนินการอยู่หรือไม่ (และถ้าเป็นเช่นนั้นมันคืออะไร)?


คำตอบ:


69

var thisline = new Error().lineNumber

หากไม่ได้ผลในทุกสภาพแวดล้อมที่คุณใช้คุณสามารถลอง:

var stack = new Error().stack

จากนั้นล่าผ่านสแต็กสำหรับหมายเลขบรรทัด


3
จะไม่ทำงานใน IE lineNumberไม่มีคุณสมบัติในวัตถุข้อผิดพลาด ไม่stack:-)
Andy E

1
มีหมายเลขบรรทัดอยู่ที่ไหนสักแห่งบน IE ฉันรู้สิ่งนี้เพราะเมื่อจาวาสคริปต์ของฉันแสดงข้อผิดพลาดจะบอกว่ามันอยู่ในบรรทัดที่มีตัวเลขมากกว่า 100 ล้าน
Malfist

ฉันไม่ได้รับหมายเลขที่ถูกต้อง 1350 เมื่อมันควรจะเป็น 1250
Fzs2

1
ปัญหา: หากคุณใช้ PHP "ซอร์สโค้ด" ที่จาวาสคริปต์เห็นไม่ใช่ซอร์สโค้ดเดิมดังนั้นจึงมีหมายเลขบรรทัดที่ไม่ถูกต้อง (นั่นอาจเป็นสิ่งที่เกิดขึ้นกับ Hermann) มีใครรู้วิธีทำให้ javascript ดูหมายเลขบรรทัดซอร์สโค้ด PHP ดั้งเดิมหรือไม่? วิธีแก้ปัญหาอาจเกี่ยวข้องกับการสร้าง "แผนที่ต้นทาง" บางประเภท แต่ฉันหาวิธีทำไม่ได้ แน่นอนว่านี่คือปัญหาที่แก้ไขได้ใช่ไหม ??
Dave Burton

หมายเหตุ: บางครั้งหมายเลขสแต็ก / บรรทัดจะไม่พร้อมใช้งานเมื่อสร้างวัตถุข้อผิดพลาดเฉพาะเมื่อถูกโยนออกไปตัวอย่างเช่นใน Google Apps Script - ในกรณีนี้โปรดดูคำตอบสำหรับวิธีแก้ไข
user202729


27

พกพาสะดวกขึ้นเล็กน้อยระหว่างเบราว์เซอร์และเบราว์เซอร์เวอร์ชันต่างๆ (ควรทำงานใน Firefox, Chrome และ IE10 +):

function ln() {
  var e = new Error();
  if (!e.stack) try {
    // IE requires the Error to actually be throw or else the Error's 'stack'
    // property is undefined.
    throw e;
  } catch (e) {
    if (!e.stack) {
      return 0; // IE < 10, likely
    }
  }
  var stack = e.stack.toString().split(/\r\n|\n/);
  // We want our caller's frame. It's index into |stack| depends on the
  // browser and browser version, so we need to search for the second frame:
  var frameRE = /:(\d+):(?:\d+)[^\d]*$/;
  do {
    var frame = stack.shift();
  } while (!frameRE.exec(frame) && stack.length);
  return frameRE.exec(stack.shift())[1];
}

ขอบคุณ. ฉันปรับคำแนะนำของคุณเป็นสิ่งนี้: stackoverflow.com/a/37081135/470749
Ryan

1
หากคุณปรับนิพจน์ทั่วไปคุณสามารถส่งคืนได้ทั้งหมายเลขบรรทัดและคอลัมน์var frameRE = /:(\d+:\d+)[^\d]*$/;ซึ่งมีประโยชน์กว่ามากโดยเฉพาะเมื่อย่อ JS เป็นหนึ่งบรรทัดยาว
Quinn Comendant

คำเตือนใช้ไม่ได้กับสคริปต์ ViolentMonkey สำหรับ Chrome คุณจะได้รับหมายเลขปลอมไม่ทราบสาเหตุ
hanshenrik

5

คุณสามารถลองแยกวิเคราะห์แหล่งที่มาของฟังก์ชันเพื่อค้นหาเครื่องหมาย
นี่คือตัวอย่างสั้น ๆ (ใช่มันยุ่งเล็กน้อย)

function foo()  
{       
    alert(line(1));
    var a;
    var b;      
    alert(line(2));
}   
foo();

function line(mark)
{
    var token = 'line\\(' + mark + '\\)';       
    var m = line.caller.toString().match(
        new RegExp('(^(?!.*' + token + '))|(' + token + ')', 'gm')) || [];
    var i = 0;
    for (; i < m.length; i++) if (m[i]) break;
    return i + 1;
}

3

ใส่ข้อมูลโค้ดต่อไปนี้ลงในโค้ดของคุณ:

console.debug("line:", /\(file:[\w\d/.-]+:([\d]+)/.exec(new Error().stack)[1]);

แทนที่ชื่อโปรโตคอลตามต้องการ (เช่น "http:")
crishushu

1
ฉันไม่สามารถทำงานนี้ได้ ฉันเข้าใจTypeError: /\(http:[\w\d/.-]+:([\d]+)/.exec(...) is nullแล้ว
Ryan

2

คุณสามารถลอง:

window.onerror = handleError;
function handleError(err, url, line){
    alert(err + '\n on page: ' + url + '\n on line: ' + line);
}

จากนั้นโยนข้อผิดพลาดที่คุณต้องการทราบ (ไม่ต้องการมากเกินไป แต่อาจช่วยคุณได้หากคุณกำลังแก้ไขข้อบกพร่อง

หมายเหตุ: window.onerrorไม่ได้กำหนด / จัดการในWebKitหรือOpera (ครั้งล่าสุดที่ฉันตรวจสอบ)


1
โปรดทราบว่า window.onerror ใช้ไม่ได้ใน webkit: bugs.webkit.org/show_bug.cgi?id=8519
Annie

1
น่าสนใจ. คุณยังสามารถสร้างฟังก์ชันพิเศษthrowAndResume(resumeFunction);ที่จะจัดเก็บ resumeFunction โยนข้อผิดพลาดและในตัวจัดการข้อผิดพลาดของคุณบันทึกรายละเอียดจากนั้นเรียก resumeFunction เพื่อดำเนินการต่อโปรแกรมของคุณ
z5h

0

ไม่มีใครสามารถดึงหมายเลขบรรทัดออกจาก Error.stack ได้เนื่องจากใน Angular หมายเลขบรรทัดคือหมายเลขบรรทัดของรหัสที่คอมไพล์ แต่เราสามารถรับข้อมูลในวิธีการสร้างข้อผิดพลาด Class Logger ในส่วนโค้ดนี้จะเพิ่มข้อมูลส่วนนี้ในรายการสมุดบันทึกใหม่

https://stackblitz.com/edit/angular-logger?file=src/app/Logger/logger.ts


-2

หากโค้ดของคุณคือ JavaScript + PHP หมายเลขบรรทัด PHP ปัจจุบันจะมีอยู่ใน JavaScript เป็นค่าคงที่ตามตัวอักษรเนื่องจากมีให้ใน PHP เป็น   <?= __LINE__ ?>

(สมมติว่าคุณเปิดใช้งานแท็กสั้น ๆ ของ PHP แล้ว)

ตัวอย่างเช่นใน JavaScript คุณสามารถพูดว่า:

this_php_line_number = <?= __LINE__ ?>;

อย่างไรก็ตามหากคุณไม่ระวังหมายเลขบรรทัด PHP อาจแตกต่างจากหมายเลขบรรทัด JavaScript เนื่องจาก PHP "กิน" ซอร์สไลน์ก่อนที่เบราว์เซอร์จะเห็น ดังนั้นปัญหาจึงเกิดขึ้นเพื่อให้แน่ใจว่าหมายเลขบรรทัด PHP และ JavaScript ของคุณเหมือนกัน หากแตกต่างกันจะทำให้การใช้ดีบักเกอร์ JavaScript ของเบราว์เซอร์ไม่ค่อยน่าพอใจนัก

คุณสามารถตรวจสอบให้แน่ใจว่าหมายเลขบรรทัดเหมือนกันโดยรวมคำสั่ง PHP ที่เขียนจำนวนบรรทัดใหม่ที่ถูกต้องที่จำเป็นในการซิงโครไนซ์หมายเลขบรรทัดฝั่งเซิร์ฟเวอร์ (PHP) และเบราว์เซอร์ (JavaScript)

นี่คือลักษณะของรหัสของฉัน:

<!DOCTYPE html>
<html lang="en">
<!-- Copyright 2016, 2017, me and my web site -->
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, user-scalable=yes">

<?php

...lots of PHP stuff here, including all PHP function definitions ...

echo str_repeat("\n",__LINE__-6); # Synchronize PHP and JavaScript line numbers
?>
<!-- *** this is line <?php echo __LINE__ . ' of ' . basename(__FILE__); ?> *** -->

  <title>My web page title</title>

...lots of HTML and JavaScript stuff here...

</body>
</html>
<!-- *** this is line <?php echo __LINE__ . ' of ' . basename(__FILE__); ?> *** -->

ที่สำคัญคือคำสั่ง PHP นี้:

echo str_repeat("\n",__LINE__-6);

นั่นเป็นการพ่นบรรทัดใหม่มากพอที่จะทำให้หมายเลขบรรทัดที่ JavaScript เห็นนั้นเหมือนกับหมายเลขบรรทัด PHP คำจำกัดความของฟังก์ชัน PHP และอื่น ๆ ทั้งหมดจะอยู่ด้านบนสุดข้างหน้าบรรทัดนั้น

หลังจากบรรทัดนั้นฉัน จำกัด การใช้ PHP ของฉันไว้ที่โค้ดที่ไม่เปลี่ยนหมายเลขบรรทัด

"-6" แสดงถึงความจริงที่ว่าโค้ด PHP ของฉันเริ่มต้นที่บรรทัดที่ 8 หากคุณเริ่มโค้ด PHP ก่อนหน้านี้คุณจะลดจำนวนนั้นลง บางคนวาง PHP ไว้ที่ด้านบนสุดแม้แต่ DOCTYPE ด้วยซ้ำ

(บรรทัดเมตาวิวพอร์ตจะปิดใช้งาน "การเร่งแบบอักษร" ของ Android Chrome สำหรับคำถาม & คำตอบ Stack Overflow นี้: Chrome บน Android จะปรับขนาดแบบอักษรให้พิจารณาว่าเป็นแบบสำเร็จรูปที่ทุกหน้าเว็บต้องการ

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

<!-- *** this is line <?php echo __LINE__ . ' of ' . basename(__FILE__); ?> *** -->

กลายเป็น:

<!-- *** this is line 1234 of my_file.php *** -->

ตอนนี้ทุกที่ที่ฉันเห็นหมายเลขบรรทัดไม่ว่าจะอยู่ในข้อความแสดงข้อผิดพลาดหรือในตัวแก้ไขข้อบกพร่อง JavaScript ก็ถูกต้อง หมายเลขบรรทัด PHP และหมายเลขบรรทัด JavaScript จะสอดคล้องและเหมือนกันเสมอ

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