Tag Archives: chrome debugger

Làm chủ Google Chrome DevTools và các chức năng Call Stack, Watch, Scope

1. Giới thiệu và cách mở công cụ DevTools

Kỹ năng debug là một kỹ năng nền tảng không thể thiếu của bất kỳ một lập trình viên nào. Debug không chỉ để tìm và sửa lỗi, mà còn giúp lập trình viên hiểu rõ hơn luồng của chương trình. Qua đó cải thiện kỹ năng code của mình và chất lượng chương trình thông qua các lỗi đã được sửa.

Google Chrome là một trình duyệt web được giới lập trình viên ưa chuộng vì nhanh, tiện lợi, đồng bộ và sở hữu công cụ Developer Tools vô cùng mạnh mẽ. Bài viết này sẽ giới thiệu cơ bản về công cụ DevTools, cách sử dụng các chức năng Call Stack, Watch, Scope trong công cụ này.

Một vài cách mở DevTools dễ thực hiện như sau:

  • Ctrl + Shift + I.
  • F12.
  • Chuột phải => Kiểm tra phần tử (Inspect).

Bạn chuyển qua Tab Sources sẽ là nơi bạn thực hành debug sau này.

  1. List các Source files (HTML, Javascript, CSS, …).
  2. Hiển thị nội dung file source hiện tại.
  3. Control buttons và thông tin trong quá trình debug.

2. Các chức năng cơ bản

Break points:

Break point màu xanh

Breakpoints là vị trí mà chương trình sẽ dừng lại để lập trình viên xem xét sự thay đổi qua từng biến, qua từng dòng lệnh, từ đó phát hiện ra vị trí dòng code lỗi.

Có thể đặt nhiều Breakpoint trong chương trình. Trên Chrome Developer Tools, để đặt breakpoints, đơn giản chỉ cần click vào line number. Hoặc bạn có thể đặt debugger trong JavaScript

Các lệnh điều khiển cơ bản:

  • Resume F8: Chương trình sẽ tiếp tục chạy cho đến khi gặp 1 breakpoint khác (nếu có).
  • Step over F10: Chạy từng dòng lệnh, nhưng sẽ không nhảy vào trong các hàm khác.
  • Step into F11: Chạy từng dòng lệnh như Step over, nhưng sẽ nhảy vào từng dòng lệnh trong các hàm khác.
  • Step out Shift+F11: Thoát khỏi hàm hiện tại đang debug.
  • Step F9: Chạy từng dòng lệnh.
  • Deactive breakpoint: Tắt hêt các điểm breakpoint.
  • Pause on exception: Tự động dừng khi xảy ra ngoại lệ.

Bây giời, mình sẽ cùng tìm hiểu về phần chính của bài viết này.

3. Call Stack

JavaScript là một ngôn ngữ đơn luồng, cũng có nghĩa là nó chỉ có một Call Stacklà một cấu trúc dữ liệu dạng ngăn xếp (stack) dùng để chứa thông tin về hoạt động của chương trình, danh sách các hàm được gọi lúc thực thi chương trình.
Khi bạn chạy debug code theo cách nhảy từng dòng lệnh, thì Chrome DevTools cung cấp cho bạn 1 Call Stack pane. Do đó khi bạn debug/step đến một function A, thì A sẽ được push (on top) vào Call Stack. Sau khi thực thi hàm A xong và trả về kết quả thì A sẽ bị pop ra khỏi stack.

Ví dụ cơ bản giúp thông não:

Có đoạn code sau:

Khi selector ‘.TruongBatBuoc’ thoả mãn sự kiện thì sẽ chạy hàm CheckInput(). Mình đặt break point vào hàm CheckInput() thì ta được Call Stack như sau:

Call Stack

Tiếp tục F11 để chạy từng dòng và quan sát của hàm CheckInput(), vì trong hàm CheckInput() có gọi hàm validateEmail() nên con trỏ chuyển vào hàm này và nó được push vào top của Call Stack:

Con trỏ chuyển vào hàm validateEmail()
Hàm validateEmail() được push vào Call Stack

Và giống như những Stack, sau khi thực hiện hàm phía trên cùng xong thì nó sẽ bị pop ra khỏi Call Stack. Khi nhìn vào Call Stack ta còn biết được hàm đó nằm ở file JS nào, dòng thứ bao nhiêu. VD: ảnh trên hàm dispatch() nằm ở file jquery.js và ở dòng thứ 5226 trong file.

4. Watch

Watch là một chức năng của Chrome DevTools cho phép bạn dễ dàng quản lý biến trong chương trình của mình. Bạn sẽ không phải dùng đến Tab Console để kiểm tra các biến khi đang debug ở Tab Sources vì Watch sẽ giúp bạn quản lý dễ dàng hơn, tiện lợi và không cần chuyển qua lại giữa các Tab.

Thêm biến

Để thêm một biến vào Watch list, bạn chọn vào biểu tượng thêm phía bên phải của khung Watch. Sau đó nhập tên biến và ấn Enter để thêm.

Trình theo dõi sẽ cho bạn thấy giá trị cụa biến được thêm vào. Nếu biến chưa được đặt hoặc không thể tìm thấy thì nó sẽ hiển thị <not availiable> ở phần giá trị.

Cập nhật biến

Khi bạn đang thực hiện debug trên Chrome, các giá trị biến sẽ tự động cập nhập trong khung Watch. Bạn cũng có thể cập nhật lại trị thủ công giá trị của các biến bằng cách nhấn nút refresh cạnh nút thêm biến.

Xóa các biến khỏi danh sách

Sẽ có thể có những biến bạn không muốn quản lý nữa. Bạn có thể cần xóa các biến ra khỏi Watch list để tối ưu và làm việc nhanh hơn. Bạn có thể xóa bằng cách di chuột vào biến, sau đó nhấp vào icon loại bỏ ở bên phải. Hoặc chuột phải rồi chọn Delete watch expression.

5. Scope

Khi bạn debug, khung Scope hiển thị cho bạn các thuộc tính, biến được xác định tại thời điểm đó.

Khung Scope chỉ hiển thị dữ liệu khi đang ở trong chế độ debug. Khi chương trình chạy bình thường thì khung Scope trống.

Khung Scope hiển thị các thuộc tính và các biến xác định ở phạm vi Local, Closure và Global.

Có thể quản lý các đối tượng được tạo ra nếu viết JS OOP.

Scope và Watch đều rất hữu ích, tiện dụng. Theo mình điểm khác nhau của 2 chức năng này là:

  • Scope: thì chỉ có thể theo dõi được các thuộc tính, biến và đối tượng không cần thêm thủ công.
  • Watch: có thể theo dõi được các hàm, nhưng cần thêm thủ công. Nhưng khi dừng debug, trong một số trường hợp giá trị vẫn được lưu lại ở khung Watch.

Bài viết dựa trên những rì mình từng trải và tham khảo ở https://developers.google.com.

Mình là Hùng, sinh viên năm 3 của UET. Số đo 4 vòng của mình là 50-100-50-20cm=)). Mong mọi người xem sẽ không cà khịa mình vì bài viết quá hay :3 Bye!!!

Những điều thú vị về console API trong Java Script

Console API

Trong quá trình học tập cũng như làm việc chắc hẳn những lập trình viên như chúng ta cũng sẽ gặp phải lỗi, không ít thì nhiều =)) Mỗi lúc như vậy thì các coder tài ba lại dùng mọi cách để debug xem lỗi ở đâu mà sửa, việc debug đã gắn liền với các lập trình viên trở thành một phần không thể thiếu trong cuộc sống cũng như đặc trưng của cái nghề “việc nhẹ lương cao” này rồi.

Nếu đem so sánh các công cụ debugger chuyên nghiệp của các IDE hay browser với console.log() của chúng ta thì đó là một cuộc chiến không cân sức. Tuy nhiên console API còn nhiều điểu hay ho hơn chứ không chỉ có mỗi console.log() đâu nhé. Hơn nữa chúng ta cũng cần biết cách debug với console API vì mỗi lập trình viên chuyên nghiệp không thể thiếu được kĩ năng quan trọng này. Trong bài viết này các bạn và mình sẽ cùng nhau tìm hiểu xem console API có những gì thú vị nhé!

Console.log()

Chắc hẳn ai làm lập trình cũng biết làm log() huyền thoại này. console.log() sẽ in ra chuỗi, số, object được truyền vào nó. Bạn có thể truyền bất kỳ object nào trong JS vào console.log() và nó sẽ in ra màn hình console cho bạn.

Sử dụng log() để in ra các đối tượng khác nhau

Tuy nhiên các tham số trong nó thì chưa chắc tất cả mọi người đã biết, bảng dưới là thông tin một số tham số trong console.log()

Cú phápÝ nghĩa
%o / %OThay thế object
%d / %iThay thế số nguyên
%sThay thế chuỗi
%fThay thế số thực
%cThay đổi style

Một số ví dụ:

console.log('Hello %o',{name:'Nguyen Tuan Quang', department:'blockchain'},'!' );

Kết quả:

Sử dụng tham số trong console.log()

Tương tự với %d,%s,%f. Với %c thì hơi đặc biệt hơn khi ta có thể chèn thêm css vào đây:

let css = "text-shadow: -1px -1px hsl(0,100%,50%),1px 1px hsl(27, 100%, 50%),3px 2px hsl(54, 100%, 50%),5px 3px hsl(81, 100%, 50%),7px 4px hsl(135, 100%, 50%),9px 5px hsl(162, 100%, 50%),11px 6px hsl(189, 100%, 50%),13px 7px hsl(243, 100%, 50%),14px 8px hsl(270, 100%, 50%),16px 9px hsl(297, 100%, 50%); font-size: 40px;";
console.log("%c Style: Sun*", css);
Tham số %c trong console.log()

Có phải bạn thấy sặc sỡ đúng không nào? Khi vào cửa sổ console khi đang sử dụng Facebook bạn sẽ thấy dòng chữ STOP to và màu đỏ, cũng như những dòng cảnh báo ở dưới. Và chúng được tạo ra bằng cách console.log() với %c đó.

Console.dir()

Hàm dir() này lúc đầu mình định không chia sẻ chi tiết nhưng thấy khá hay nên mình đặt ngay sau console.log(). Với console.dir() bạn có thể hiển thị dữ liệu theo dạng cây phân cấp, bạn có thể tương tác để xem các thuộc tính bên trong. Ví dụ:

console.dir() giúp hiển thị các thuộc tính bên trong

Rất tiện lợi phải không nào, khi làm việc với bất kì đối tượng nào bạn chỉ cần dir() ra là có thể lấy được các giá trị thuộc tính của nó một cách dễ dàng.

Khi sử dụng với một đối tượng HTML, bạn sẽ thấy console.log() hiển thị dạng cấu trúc HTML của đối tượng đó, còn console.dir() sẽ hiển thị các thuộc tính của đối tượng.

console-log-vs-dir
Khác biệt giữa log() và dir()

Chắc hẳn bạn đã nghi ra cần sử dụng dir() vào lúc nào rồi chứ?

Console.table()

Ngoài việc in ra màn hình console bằng console.log() thì chúng ta có thể dùng console.table(). Hàm này rất hữu ích khi làm việc với mảng, object, và dữ liệu dạng JSON. Chẳng hạn như ví dụ sau:

var car1 = { name : "Audi", model : "A4" }
var car2 = { name : "Volvo", model : "XC90" }
var car3 = { name : "Ford", model : "Fusion" }

console.table([car1, car2, car3]);
In thông tin với console.table()

Các phần tử đối tượng hay mảng sẽ được in ra trên một dòng với số cột là tên các key, thuộc tính và giá trị của phần tử. Chắc hẳn nhìn sẽ trực quan hơn log() rất nhiều đúng không nào.

Console.clear()

Khi chúng ta viết quá nhiều lệnh thì màn hình console sẽ có một mớ hỗn độn và trông rất rối mắt. Cũng giống như lệnh xóa màn hình trong C thì console.clear() sẽ xóa sạch màn hình console của bạn giúp bạn thực hiện những lệnh tiếp theo với không gian làm việc sạch sẽ. Có lẽ bạn sẽ thích hàm này khi làm việc đó.

Xóa màn hình với console.clear()

Console.count()

Hàm console.count([label]) trả về số lần được gọi của đối tượng truyền vào trong count(). Nếu không có tham số sẽ mặc định trả về số lần được gọi với label default.

Ví dụ:

for (i = 0; i < 10; i++) {
  console.count();
}

Kết quả sẽ là:

console.count() với tham số mặc định

Nếu truyền tham số vào hàm count() sẽ trả về số lần gọi function với label đã truyền vào, lưu ý là tuy cùng truyền vào một function nhưng với các giá trị label khác nhau thì hàm count() sẽ thực hiện độc lập, không cộng dồn.

Có thể truyền label vào console.count()

Console.group()

console.group() cho biết là sẽ bắt đầu một nhóm các phương thức trong màn hình console. Tất cả các câu lệnh hay thông bào tiếp theo sẽ nằm trong nhóm này. Để kết thúc nhóm ta sử dụng lệnh console.groupEnd()

console.group() nhóm các phương thức tiếp theo được gọi

Còn nữa, phương thức console.groupCollapsed(label) biểu thị sự bắt đầu của một nhóm thông báo bị thu gọn. Tất cả những hàm được gọi tiếp theo sẽ được nhóm vào một label, chúng ta có thể nhấn vào label để mở rộng hay thu gọn nhóm.

console.groupCollapsed() giúp tạo một nhóm có thể thu gọn

Console.trace()

Đây là một hàm rất hữu ích trong việc debug. console.trace() sẽ in ra nguồn gốc đối tượng mà dẫn đến câu lệnh gọi này. Sẽ rất hữu ích khi truy code flow. Câu này nếu thử ngay vào browser console thì sẽ không có ý nghĩa lắm. Để hiểu rõ hơn bạn cần cho nó vào trong code của mình để xem.

Đây là một ví dụ:

Sử dụng console.trace()

Console.warn(), Console.error()

Hai hàm này chức năng cũng giống như console.log() thôi nhưng sẽ hiển thị với màu và kiểu đặc trưng. warn() là cảnh báo nên sẽ có màu vàng còn error() sẽ có màu đỏ để hiển thị lỗi. Các bạn hãy tự thử trên console để xem nó thế nào nhé!

console.warn("This is a warning!");
console.error("This is an error!");

Console. assert()

Với hàm assert() tham số đầu tiên của nó phải là boolean. Nếu tham số đầu tiên trả về true thì nó cũng ko làm gì luôn. Tuy nhiên nếu ngược lại thì các tham số tiếp theo sẽ được in ra giống console.error().

Ví dụ:

Console.assert()

Timing

Hàm này khá hay ho, giúp bạn đo lường thời gian thực thi (một cách “chân tay”). Cũng dễ hiểu thôi nên các bạn có thể tự thử nhé.

console.time();
// code snippet 1
console.timeLog(); // default: [time] ms
// code snippet 2
console.timeEnd(); // default: [time] ms

Mở rộng

Ngoài ra còn một số hàm nữa trong console API mà mình liệt kê ở dưới mà không diễn giải chi tiết cho các bạn. Các bạn có thể tham khảo và nếu phù hợp có thể áp dụng cho công việc của mình:

  1. countReset()
  2. debug()
  3. dirxml()
  4. info()
  5. profile()
  6. profileEnd()

Kết luận

Vậy là chúng ta đã đi qua một lượt những thứ quan trọng về console api trong Java Script. Với những kiến thức trên hi vọng các bạn sẽ tự tin hơn trong lập trình cũng như debug code với console, hiểu các hàm trong console dùng vào mục đích gì. Mình xin kết thúc bài viết ở đây và cảm ơn các bạn đã đọc đến phần cuối cùng này!

Mọi thông tin tham khảo về console API các bạn có thể truy cập tại: https://developer.mozilla.org/en-US/docs/Web/API/Console