5 điểm bởi GN⁺ 2023-11-12 | 1 bình luận | Chia sẻ qua WhatsApp
  • Nếu có thể sử dụng công cụ dành cho nhà phát triển của trình duyệt ở mức trung cấp trở lên, bạn có thể mở rộng breakpoint có điều kiện không chỉ như điều kiện dừng, mà còn thành công cụ ghi log, truy vết, thay đổi trạng thái và đo thời gian
  • Khi đưa các Console API như console.log, console.count, console.trace, console.time vào breakpoint hoặc Watch Pane, bạn có thể ghi lại luồng thực thi và trạng thái mà không dừng chương trình
  • Bằng cách kết hợp số lượng đối số hàm, thời gian, giá trị CSS đã tính toán, số lần thực thi, lấy mẫu ngẫu nhiên và boolean toàn cục, bạn có thể kiểm soát thời điểm dừng tinh vi hơn nhiều
  • monitor, debug, copy, $0, getEventListeners, monitorEvents của Chrome giúp xử lý nhanh lời gọi hàm, DOM, sự kiện và thao tác clipboard từ console
  • Trên các màn hình mà DOM liên tục thay đổi do JS hoặc sự kiện người dùng, tạm dừng JS, setTimeout(debugger), snapshot DOM và giám sát focus đặc biệt hữu ích cho gỡ lỗi HTML/CSS

Mở rộng breakpoint có điều kiện thành công cụ gỡ lỗi

  • Trong breakpoint có điều kiện, ngoài điều kiện đúng/sai, bạn cũng có thể đưa vào biểu thức JavaScript có side effect

  • Tận dụng điều này, bạn có thể dùng breakpoint cơ bản như công cụ ghi log, truy vết, thay đổi trạng thái hoặc đo thời gian

  • Logpoint và tracepoint

    • Khi gọi console.log trong breakpoint có điều kiện, nó hoạt động như một logpoint, ghi giá trị ra console mà không dừng thực thi
    • Dùng console.count cũng có thể đếm kèm số lần dòng đó đã được thực thi
    • Tính đến bản cập nhật tháng 5/2020, các trình duyệt lớn đã hỗ trợ trực tiếp logpoint/tracepoint
  • Dùng Console API trong Watch Pane

    • Bạn cũng có thể đưa các biểu thức như console.log vào Watch Pane
    • Mỗi lần ứng dụng dừng trong debugger, có thể chụp snapshot localStorage bằng console.table(localStorage)
    • Khi dùng breakpoint thay đổi DOM cùng với biểu thức Watch, có thể lưu snapshot vào mảng sau khi subtree DOM thay đổi
    (window.doms = window.doms || []).push(document.documentElement.outerHTML)
    
    • Không thể làm cho breakpoint thay đổi DOM không dừng thực thi
  • Truy vết call stack

    • Khi cần tìm vấn đề có hàm hiển thị loading spinner và hàm ẩn nó, nhưng chỉ còn lời gọi hiển thị, có thể đưa console.trace vào breakpoint có điều kiện
    • Từ stack trace cuối cùng của hàm hiển thị, nhấp vào caller để chuyển tới vị trí gọi tương ứng
  • Thay đổi hành vi chương trình khi đang chạy

    • Nếu ghi đè đối số hàm trong biểu thức breakpoint có điều kiện, bạn có thể thay đổi tức thì hành vi chương trình ngay trong trình duyệt
    • Ví dụ, có thể thay đổi giá trị id của hàm getPerson
    • Biểu thức được đánh giá là đúng như id=1 sẽ làm debugger dừng lại, nên nếu không muốn dừng, có thể thêm , false
  • Đo hiệu năng nhanh

    • Vì có lẫn thời gian đánh giá breakpoint có điều kiện, cách này không phù hợp để profiling hiệu năng chính xác
    • Khi cần đo nhanh, có thể đặt console.time('label') ở điều kiện tại điểm bắt đầu và console.timeEnd('label') ở điều kiện tại điểm kết thúc để ghi thời gian thực thi ra console

Làm điều kiện dừng tinh vi hơn

  • Tận dụng số lượng đối số hàm

    • Nếu chỉ muốn dừng khi hàm hiện tại được gọi với 3 đối số, có thể dùng điều kiện sau
    arguments.callee.length === 3
    
    • Hữu ích với hàm overload có đối số tùy chọn
    • Nếu chỉ muốn dừng khi số đối số được định nghĩa khác với số đối số thực tế được truyền vào, có thể dùng điều kiện sau
    (arguments.callee.length) != arguments.length
    
    • Giúp tìm lỗi ở vị trí gọi hàm
  • Điều kiện dựa trên thời gian

    • Nếu không muốn dừng trước khi đã qua 5 giây sau khi tải trang, có thể dùng điều kiện sau
    performance.now() > 5000
    
    • Phù hợp khi chỉ quan tâm đến breakpoint sau giai đoạn tải trang ban đầu
    • Nếu muốn sau khi breakpoint được đặt thì không dừng trong 5 giây tiếp theo, rồi sau đó mới dừng, có thể lưu thời điểm mốc vào biến toàn cục
    window.baseline = window.baseline || Date.now(),
    (Date.now() - window.baseline) > 5000
    
    • Có thể khởi động lại bộ đếm từ console bằng window.baseline = Date.now()
  • Điều kiện dựa trên trạng thái CSS

    • Có thể dừng dựa trên giá trị CSS đã tính toán làm điều kiện
    • Ví dụ, nếu chỉ muốn dừng khi màu nền của document.body là màu đỏ, có thể dùng điều kiện sau
    window.getComputedStyle(document.body).backgroundColor === "rgb(255,0,0)"
    
  • Số lần thực thi và lấy mẫu

    • Có thể tăng bộ đếm mỗi khi dòng được thực thi để chỉ dừng một lần trong mỗi hai lần
    window.counter = (window.counter || 0) + 1, window.counter % 2 === 0
    
    • Nếu muốn dừng ngẫu nhiên 1 lần trong 10 lần bằng lấy mẫu ngẫu nhiên, có thể dùng điều kiện sau
    Math.random() < 0.1
    
  • Không bao giờ dừng ở một vị trí cụ thể

    • Trong Chrome, nếu nhấp chuột phải vào gutter và chọn “Never Pause Here”, một breakpoint có điều kiện luôn là false sẽ được tạo, nên không dừng ở dòng đó
    • Có thể dùng khi loại trừ một dòng cụ thể khỏi breakpoint XHR hoặc bỏ qua một ngoại lệ cụ thể
  • Tự động gán ID cho instance

    • Có thể đặt breakpoint có điều kiện trong constructor của class để lưu từng instance vào mảng
    (window.instances = window.instances || []).push(this)
    
    • ID duy nhất của một instance cụ thể có thể được xác định bằng chỉ mục mảng
    window.instances.indexOf(instance)
    
  • Bật/tắt breakpoint toàn cục

    • Có thể điều khiển một hoặc nhiều breakpoint có điều kiện bằng boolean toàn cục
    • Có thể thay đổi trực tiếp từ console, thay đổi từ breakpoint khác, hoặc thay đổi bằng timer
    window.enableBreakpoints = true
    setTimeout(() => (window.enableBreakpoints = true), 5000)
    

Truy vết lời gọi hàm và class

  • Giám sát lời gọi method của class

    • Dùng method dòng lệnh monitor của Chrome có thể dễ dàng truy vết lời gọi method của class
    • Nếu muốn xem lời gọi method cho mọi instance của class Dog, có thể áp dụng monitor cho mọi property của prototype
    var p = Dog.prototype;
    Object.getOwnPropertyNames(p).forEach((k) => monitor(p[k]));
    
    • Console sẽ xuất thông tin lời gọi như function bark called with arguments: 2
    • Nếu muốn dừng thực thi khi được gọi thay vì chỉ ghi log, có thể dùng debug thay cho monitor
  • Truy vết class từ một instance cụ thể

    • Nếu không biết tên class nhưng có instance, có thể giám sát theo cùng cách thông qua prototype của constructor
    var p = instance.constructor.prototype;
    Object.getOwnPropertyNames(p).forEach((k) => monitor(p[k]));
    
    • Hữu ích khi tạo hàm hoạt động với instance bất kỳ mà không cố định vào một class cụ thể
  • Gỡ lỗi ngay trước khi gọi hàm từ console

    • Trước khi gọi hàm muốn gỡ lỗi từ console, chạy debugger, rồi Step into vào lời gọi hàm tiếp theo để đi vào phần triển khai hàm
    debugger; fn(1);
    
    • Hữu ích khi ngại tìm vị trí định nghĩa hàm hoặc khi fn được bind động nên không biết vị trí source
    • Trong Chrome, cũng có thể gọi debug(fn) để mỗi lần fn được gọi thì dừng bên trong hàm

Gỡ lỗi thay đổi URL và đọc property

  • Dừng trước khi SPA routing

    • Để dừng ngay trước khi ứng dụng một trang thay đổi URL, có thể gắn hàm có debugger vào history.pushState, history.replaceState, window.onhashchange, window.onpopstate
    const dbg = () => {
      debugger;
    };
    history.pushState = dbg;
    history.replaceState = dbg;
    window.onhashchange = dbg;
    window.onpopstate = dbg;
    
    • Phiên bản dbg này không bao gồm phần triển khai vừa dừng vừa không làm hỏng điều hướng
    • Trường hợp gọi trực tiếp window.location.replace hoặc window.location.assign, trang sẽ unload ngay sau khi gán nên không thể xử lý bằng cách này
    • Trong Chrome, có thể đặt debug lên các method liên quan để xem source redirect và trạng thái tại thời điểm đó
    debug(window.location.replace);
    debug(window.location.assign);
    
  • Tìm nơi property được đọc

    • Nếu muốn biết thời điểm một property cụ thể của object được đọc, có thể đặt debugger trong getter
    { get configOption() { debugger; return true; } }
    
    • Hữu ích khi kiểm tra đoạn code nào sử dụng option cấu hình và sử dụng như thế nào
    • Có thể áp dụng bằng cách sửa trong source gốc hoặc dùng breakpoint có điều kiện

Sao chép dữ liệu từ console

  • Dùng Console API copy() có thể sao chép thông tin trong trình duyệt vào clipboard mà không bị cắt ngắn chuỗi
  • Có thể dùng khi sao chép snapshot DOM hiện tại, metadata tài nguyên như hình ảnh, JSON blob lớn hoặc dump localStorage
copy(document.documentElement.outerHTML)
copy(performance.getEntriesByType("resource"))
copy(JSON.parse(blob))
copy(localStorage)

Gỡ lỗi HTML/CSS

  • Kiểm tra DOM khi JS đang tạm dừng

    • Trong DOM inspector, trên Chrome/Windows, nhấn ctrl+\ để tạm dừng thực thi JS bất cứ lúc nào
    • Ngay cả khi JS thay đổi DOM hoặc sự kiện như mouseover làm thay đổi DOM, bạn vẫn có thể kiểm tra ổn định snapshot DOM hiện tại
  • Kiểm tra phần tử biến mất

    • Với phần tử DOM có điều kiện biến mất khi di chuyển chuột, có thể đặt timer 5 giây trong console để chạy debugger rồi kiểm tra
    setTimeout(function() { debugger; }, 5000);
    
    • Sau khi hiển thị UI trong 5 giây, nếu thực thi JS dừng lại thì phần tử sẽ không biến mất, nên có thể chuyển sang công cụ dành cho nhà phát triển để kiểm tra
    • Trong khi JS đang dừng, có thể kiểm tra phần tử, chỉnh sửa CSS và chạy lệnh JS console
    • Hiệu quả khi kiểm tra DOM phụ thuộc vào vị trí con trỏ hoặc focus
  • Ghi lại snapshot DOM

    • Để sao chép DOM hiện tại, có thể dùng lệnh sau
    copy(document.documentElement.outerHTML);
    
    • Để lưu chuỗi DOM vào mảng mỗi 1 giây, có thể dùng setInterval như sau
    doms = [];
    setInterval(() => {
      const domStr = document.documentElement.outerHTML;
      doms.push(domStr);
    }, 1000);
    
    • Cũng có thể liên tục in ra console mà không lưu vào mảng
  • Giám sát phần tử đang được focus

    • Có thể định kỳ so sánh document.activeElement để in thay đổi focus ra console
    (function () {
      let last = document.activeElement;
      setInterval(() => {
        if (document.activeElement !== last) {
          last = document.activeElement;
          console.log("Focus changed to: ", last);
        }
      }, 100);
    })();
    
  • Tìm phần tử được hiển thị in đậm

    • Có thể tìm mọi phần tử có fontWeight đã tính toán là "bold" hoặc "700"
    const isBold = (e) => {
      let w = window.getComputedStyle(e).fontWeight;
      return w === "bold" || w === "700";
    };
    Array.from(document.querySelectorAll("*")).filter(isBold);
    
    • Nếu chỉ muốn tìm trong các phần tử con của phần tử hiện được chọn trong inspector, có thể tìm dựa trên $0
    Array.from($0.querySelectorAll("*")).filter(isBold);
    
  • Xử lý phần tử được chọn và sự kiện

    • $0 trong console là tham chiếu tự động trỏ tới phần tử hiện được chọn trong Element Inspector
    • Trong Chrome và Edge, có thể truy cập các phần tử đã kiểm tra trước đó bằng $1, phần tử trước nữa bằng $2, v.v.
    • Trong Chrome, có thể xem event listener của phần tử hiện được chọn
    getEventListeners($0)
    
    • Để gỡ lỗi mọi sự kiện của phần tử được chọn, có thể dùng monitorEvents($0)
    • Nếu chỉ muốn xem một nhóm sự kiện cụ thể, có thể truyền vào mảng
    monitorEvents($0, ["control", "key"])
    

1 bình luận

 
GN⁺ 2023-11-12
Các ý kiến trên Hacker News
  • Trong vài thập kỷ qua, các công cụ gỡ lỗi tích hợp trong trình duyệt đã tiến bộ thật sự rất nhiều
    Với tư cách là người đã dùng JS lâu năm, tôi rất biết ơn những người đã làm cho việc gỡ lỗi mã ngay trong trình duyệt trở nên trực quan đến vậy
    Khi chuyển sang các mảng phát triển khác như backend hay các ngôn ngữ khác, tôi lại nhớ hệ sinh thái công cụ gỡ lỗi mà các trình duyệt hiện đại cung cấp sẵn

    • Cũng muốn vỗ tay tán thưởng những người đã tạo ra tiện ích mở rộng Firebug, thứ đã thực sự nâng tầm công cụ dành cho nhà phát triển trên trình duyệt
    • Tôi tò mò không biết cụ thể điều gì trong trải nghiệm gỡ lỗi JS khiến bạn cảm thấy đặc biệt đến vậy
      Tôi đã gỡ lỗi nhiều năm với Python, Java, C++ nhưng chưa từng cảm thấy thiếu công cụ
      Tất nhiên tôi từng thấy khá nhiều người không biết những lựa chọn có thể dùng trong lĩnh vực này
    • Không hoàn hảo, nhưng vẫn tốt hơn nhiều so với trải nghiệm gỡ lỗi Node.js bằng VS Code mà đồng nghiệp tôi từng cổ xúy
      So với địa ngục đó thì tôi chọn console
  • setTimeout(function() { debugger; }, 5000); thật thông minh
    Rốt cuộc cách duy nhất để thắng được chồng “rùa đệ quy” khi Chrome debugger tự gỡ lỗi chính nó chính là câu lệnh debugger
    sam.pl của sâu Myspace Sammy khét tiếng cũng từng dùng bẫy gỡ lỗi để ngăn khách truy cập đào bới trang chủ HTML đã bị làm rối

    • Một trong những bookmarklet tôi hay dùng: https://darekkay.com/blog/debugging-dynamic-content/
    • Chuyện này xảy ra khi website chặn Console/panel bên DevTools đang mở
      Nó chạy vòng lặp chính, chèn các câu lệnh debugger; phiền phức khắp nơi, rồi thực thi ở 30FPS / mỗi 32ms để khiến DevTools trở nên vô dụng
      Vì không có cách nào để “bỏ qua” câu lệnh debugger
    • Nếu không muốn đợi 5 giây thì có thể dùng phím tắt tạm dừng thực thi script cmd-\
      Trang sẽ dừng ở dòng JS đang chạy hiện tại, và bạn có thể kiểm tra phần tử gây vấn đề như bình thường
    • Tôi mong các nhà làm trình duyệt đặt việc này thành một tùy chọn phải bật rõ ràng trong DevTools, còn mặc định thì bỏ qua câu lệnh debugger
      Phần lớn trường hợp dùng debugger hợp lệ đều có thể thay bằng breakpoint đơn giản nếu đang làm việc trên mã của chính mình
    • Khoan, chỉ vậy thôi sao? Quá đơn giản mà quá hay
  • Việc thiếu queryObjects khá nổi bật
    Đây là một API khá điên rồ, trả về danh sách tất cả đối tượng được tạo bằng một constructor cụ thể
    Ví dụ có thể dùng queryObjects(Function) để lấy danh sách mọi hàm trong heap
    Nó trả về cả các hàm “private” nằm bên trong một module nào đó

    • Thành thật mà nói, nếu không muốn công khai cái này thì cũng có thể hiểu được
      Đây là một tính năng thật sự điên rồ, và có lẽ chỉ có trên Chromium
  • Tôi không tài nào dùng watch variable cho ra hồn được
    Scope và quy tắc cập nhật quá khó hiểu; tưởng như chỉ watch được biến toàn cục, nhưng ngay cả vậy cũng không hoạt động như mong đợi, nên khi test rốt cuộc tôi lại phải rải log giá trị khắp nơi
    Từ nhiều năm nay tôi vẫn nghĩ nên đưa một UI kiểu Data.gui [1] vào console để có thể xem và thử biến cùng giá trị cấu hình
    Có thể xem cách nó hoạt động thực tế trong CodePen này [2]

    1. https://github.com/dataarts/dat.gui
    2. https://codepen.io/russellbeattie/full/kGxaqM
    • Tôi cũng từng cảm thấy bực bội tương tự
      Trình duyệt về lý thuyết có nhiều tính năng gỡ lỗi tuyệt vời, nhưng thực tế dường như chúng không hoạt động ổn định
      Ngay cả breakpoint tôi cũng không làm cho tất cả bắt được một cách ổn định
      Khi mã còn được bung ra thì ổn, nhưng chỉ cần được bundle, dù chưa minify, thì nhiều tính năng debugger dường như đã hỏng
      Tôi không phải kỹ sư frontend nên có lẽ tôi đang làm sai gì đó
    • Nên thử tắt source map trong debugger
      Rất có thể đó là nguyên nhân gây bực bội, và tôi vẫn không hiểu vì sao nó được bật mặc định trong khi trải nghiệm gỡ lỗi chủ động khi bật nó lại tệ đến vậy
    • Trong panel sidebar của Chrome, biến đã minify hiển thị đúng tên, nhưng trong watchpoint lại báo lỗi là chưa được định nghĩa, rất khó chịu
  • Sẽ thật tốt nếu có cách truy cập biến cục bộ của IIFE mà không cần dừng thực thi mã bên trong phạm vi IIFE
    Có cách nào thuyết phục trình gỡ lỗi làm như vậy không?

    • IIFE là biểu thức hàm được gọi ngay lập tức
      https://en.m.wikipedia.org/wiki/Immediately_invoked_function...
    • Nếu đã vào breakpoint trong một hàm do IIFE gọi thì chỉ cần đi ngược lên stack là được
      Nếu đang hoàn toàn ở bên ngoài IIFE thì tôi nghĩ là không thể
      Biến bạn tìm có thể không tồn tại trong bộ nhớ trước hoặc sau khi thực thi
      JavaScript không có biến tĩnh như các ngôn ngữ khác, nên mỗi lần IIFE được gọi, các biến bên trong sẽ bị bỏ đi
      JavaScript có mô hình đơn luồng khá mạnh, trừ khi dùng những thứ như web worker, nên nếu không cố tình tạo race condition trực tiếp bằng lệnh gọi async/await thì bản thân khái niệm một biến như vậy còn nằm trong bộ nhớ bên ngoài phạm vi IIFE đã khó thành lập
      Nếu lạm dụng var để khởi tạo biến bên ngoài phạm vi IIFE, bạn có thể thấy giá trị do lần gọi IIFE cuối cùng tạo ra
    • Khoảng 12 năm trước tôi đã làm một công cụ làm việc đó
      Cần chỉnh sửa một chút, nhưng hiệu quả so với công sức bỏ ra là rất lớn
      https://github.com/kristopolous/_inject
      Bạn có thể đi qua gần như bất kỳ ngữ cảnh hàm nào tại một thời điểm tùy ý để xem chuyện gì đã xảy ra
      Cách làm là lợi dụng bộ đếm tham chiếu để ngăn ngữ cảnh bị hủy
      Hồi còn làm nhiều JS phía client, nó thật sự hữu ích
      Phiên bản killer app được làm tử tế của công cụ này sẽ là mở REPL trong bất kỳ ngữ cảnh nào
      Ngay cả ở trạng thái hiện tại, muốn dùng tốt cũng cần khá nhiều kỹ năng
    • Thứ bạn đang tìm có phải là logpoint không?
      https://firefox-source-docs.mozilla.org/devtools-user/debugg...
      Sửa: Tôi vừa nhận ra đó đúng là nội dung đầu tiên được nói tới trong bài được liên kết
    • Trong Chrome, sau khi kiểm tra closure được mô tả ở https://news.ycombinator.com/item?id=38226743#38231705 bằng Watch panel, hãy xem thuộc tính giả [[Scopes]]
      Có vẻ Firefox không có cách nào
  • Để đầy đủ, có thể khuyên dùng Werkzeug
    Tôi đang dùng nó để phát triển backend Django và nó cực kỳ hữu ích
    Ở bất kỳ đâu, bất cứ lúc nào có exception xảy ra, nó cho phép dùng shell “PDB” ngay trong trình duyệt

    • Rất dễ, chỉ cần đặt 1/0 vào nơi bạn muốn Werkzeug hiện lên trong trình duyệt
    • Tôi muốn có trải nghiệm như vậy ở mọi nơi, kể cả nose.js và trình duyệt
      Rất đơn giản và trực quan
    • Giờ vẫn còn cần django-extension/runserver_plus không?
  • Một mẹo tôi luôn dùng là tìm kiếm các script đã tải bằng chuỗi UI để gỡ lỗi
    Vào Network panel, bắt đầu ghi lại các network request, mở sidebar bên trái rồi tìm kiếm đoạn mã hoặc chuỗi UI muốn tìm
    Thường nó sẽ được tìm thấy trong một file chunk JS bundle kỳ lạ nào đó; khi bấm vào kết quả, network request của file đó sẽ mở ra
    Nhấp chuột phải ở bất kỳ đâu trong file đó và chọn mục kiểu “Open in Sources” để chuyển sang debugger
    Giờ chỉ cần đặt câu lệnh debugger; trong quá trình này source map có lẽ cũng sẽ được tải

  • Là lập trình viên Python/Elixir lâu năm, tôi đã dùng pdb.set_trace()IEx.pry() rất nhiều
    Gần đây tôi thừa hưởng một backend NodeJS cực kỳ lộn xộn, và đang vò nốt chỗ tóc còn lại vì không có công cụ gỡ lỗi tử tế
    Tôi đã quay lại gỡ lỗi bằng console.log, nhưng cảm giác như trở thành người nguyên thủy
    Tôi không thể tin là một hệ sinh thái phổ biến như vậy lại không có REPL gỡ lỗi đúng nghĩa; ai có thể chỉ tôi nên đi đâu không?


    • Hãy dùng node --inspect-brk, rồi kết nối bằng VS Code hoặc Chrome DevTools
      Phần rắc rối là liệu có công cụ build như biến đổi TypeScript đứng trước lệnh nodejs hay không
      Nếu chỉ chạy node thì khá dễ
      REPL gỡ lỗi chính là JavaScript console
    • Dùng VSCode Developer Tools thì cũng có thể gỡ lỗi NodeJS khá vững
      Thêm nó làm tùy chọn gỡ lỗi là có thể đặt breakpoint và step vào trong hàm
      Vì phần lớn được đóng gói trong object, JavaScript khá dễ gỡ lỗi
    • Như người khác đã nói, thứ bạn muốn là --inspect hoặc --inspect-brk
      Trong VSCode cũng có thể dùng lệnh “open JavaScript debug terminal”
      Lệnh này mở một terminal mà bất kỳ lệnh node nào cũng sẽ tự động được khởi chạy với debugger đã gắn vào
    • Có thể chưa đủ, nhưng tôi vừa biết tới python snoop
      https://pypi.org/project/snoop/
      Đây là decorator để trace sâu
    • Điểm hay trong Elixir REPL có vẻ giống Erlang REPL, đó là có thể kết nối vào một process đang chạy
      Tôi chưa thấy tính năng như vậy trong hệ sinh thái Node JS
  • Ở phần “Debugging Property Reads”, tôi tò mò bằng cách nào dùng breakpoint có điều kiện để đổi {configOption: true} thành {get configOption() { debugger; return true; }}

    • Phần đó không nằm dưới tiêu đề breakpoint có điều kiện
      Bạn chỉ cần ghi đè giá trị bằng getter trong console; nếu có quyền ghi, cũng có thể sửa trực tiếp trong mã nguồn
  • Có vẻ đây là thứ nhất định phải học, nên tôi thắc mắc liệu có sách chuyên biệt hay tài liệu học tập nào không
    Hay là chỉ còn cách đào sâu mãi vào phát triển web và frontend?

    • Tôi thật sự khuyên nên theo dõi series “What’s new in DevTools” của đội ngũ Chrome
      Khi đang bận làm việc, việc bấm vào liên kết để đọc release notes có thể không hấp dẫn lắm, nhưng mỗi khi có phiên bản mới, chỉ cần lướt qua 5 phút cũng rất đáng
      Cũng có những video ngắn vài phút, dễ tiếp thu, giúp nắm được tổng quan nhanh
      Mục đích là giới thiệu tính năng mới, nhưng theo kinh nghiệm, bạn cũng thường hiểu được các giới hạn hiện tại của công cụ