Một cuộc phỏng vấn có thể là một công cụ rất hữu ích để nhà tuyển dụng và các lập trình viên JavaScript tài ba tìm thấy nhau, nhưng đôi bên đừng nên lãng phí thời gian cho những câu hỏi đáp khó hiểu về cú pháp, ngôn ngữ hoặc tính năng (khá dễ để tra google). Hãy nhìn ra bức tranh lớn hơn, ví dụ như kiến trúc (architecture) và mô hình (paradigm) là những yếu tố lớn và mang tầm ảnh hưởng lớn đến toàn bộ dự án.

Hơn nữa, JavaScript là một ngôn ngữ đặc biệt và đóng một vai trò quan trọng trong hầu hết mọi ứng dụng lớn. Điều gì làm nên bản chất đó của JavaScript và khiến nó khác biệt so với các ngôn ngữ khác?

Dưới đây là một số câu hỏi mà mọi JavaScript Developer nên chuẩn bị kỹ câu trả lời trước khi bước vào một buổi phỏng vấn.

1. Hãy kể tên hai mô hình lập trình quan trọng đối với các JavaScript Developer

JavaScript là một ngôn ngữ đa mô hình, hỗ trợ lập trình mệnh lệnh/thủ tục cùng với OOP (Object-Oriented Programming - lập trình hướng đối tượng) và functional programming (lập trình chức năng). JavaScript hỗ trợ OOP với sự kế thừa nguyên mẫu (prototypal inheritance).

Trong câu trả lời phải có:

  • Kế thừa nguyên mẫu (hoặc là: prototypes, OLOO).
  • Functional programming (hoặc là: closures, first-class function, lambdas).

Báo động đỏ:

  • Không hề biết paradigm là gì, không đề cập đến prototypal oo hoặc functional programming.

2. Sự khác biệt giữa classical inheritance và prototypal inheritance?

Class Inheritance (tính kế thừa lớp): Nó cho phép xây dựng một lớp mới dựa trên các định nghĩa của lớp đã có. Có nghĩa là lớp cha có thể chia sẻ dữ liệu và phương thức cho các lớp con. Các phiên bản thường được khởi tạo thông qua các hàm khởi tạo với từ khóa “new” . Kế thừa lớp có thể có hoặc không sử dụng từ khóa “class” từ ES6.

Prototypal inheritance (kế thừa nguyên mẫu): Prototype là cơ chế mà các object trong javascript kế thừa các tính năng từ một object khác. Nó thường được thực hiện bằng lệnh “Object.create ()”. Các phiên bản có thể được tạo từ nhiều đối tượng khác nhau, cho phép dễ dàng kế thừa có chọn lọc.

Trong JavaScript, prototypal inheritance – kế thừa nguyên mẫu đơn giản và linh hoạt hơn so với class inheritance – kế thừa lớp.

Câu trả lời nên có:

  • Các lớp (class): tạo khớp nối chặt chẽ hoặc phân cấp / phân loại.
  • Prototype (nguyên mẫu): đề cập đến kế thừa nối, ủy quyền nguyên mẫu, kế thừa chức năng, thành phần đối tượng.

Thẻ đỏ:

  • Không có ưu tiên cho kế thừa nguyên mẫu và thành phần so với kế thừa lớp.

3. Functional programming là gì?

Functional programming tạo ra các chương trình bằng cách soạn các hàm toán học và tránh các shared state & mutable data. Lisp là một trong những ngôn ngữ đầu tiên hỗ trợ functional programming, nó được truyền cảm hứng rất nhiều từ phép tính lambda. Lisp và nhiều ngôn ngữ họ Lisp vẫn được sử dụng phổ biến cho đến ngày nay.

Functional programming là một khái niệm thiết yếu trong JavaScript (một trong hai trụ cột của JavaScript). Một số tiện ích chức năng phổ biến đã được thêm vào JavaScript trong ES5.

Trong câu trả lời phải có:

  • Pure functions
  • Tránh hiệu ứng phụ (avoid side-effects)
  • Thành phần chức năng đơn giản
  • Ví dụ về ngôn ngữ chức năng: Lisp, ML, Haskell, Erlang, Clojure, Elm, F Sharp, OCaml, v.v.
  • Đề cập đến các tính năng hỗ trợ functional programming: first-class function, các function bậc cao hơn, function dưới dạng đối số/giá trị.

Báo động đỏ:

  • Không đề cập đến pure function và tránh hiệu ứng phụ trong JavaScript.
  • Không thể cung cấp ví dụ về ngôn ngữ lập trình chức năng.
  • Không thể xác định các tính năng nào của JavaScript kích hoạt lập trình chức năng.

4. Ưu nhược điểm của functional programming và object-oriented programming là gì?

Ưu điểm của OOP: Dễ hiểu khái niệm cơ bản của đối tượng và dễ hiểu ý nghĩa của các lệnh gọi phương thức. OOP có xu hướng sử dụng kiểu mệnh lệnh hơn là kiểu khai báo, kiểu này giống như một tập hợp các hướng dẫn chuyển tiếp để máy tính làm theo.

Nhược điểm của OOP: OOP Thường phụ thuộc vào trạng thái được chia sẻ. Các đối tượng và hành vi thường được gắn với nhau trên cùng một thực thể, có thể được truy cập ngẫu nhiên bởi bất kỳ số lượng function nào với thứ tự không xác định, có thể dẫn đến hành vi không mong muốn như race condition.

Ưu điểm của FP: Sử dụng mô hình chức năng, các lập trình viên tránh được bất kỳ shared state nào hoặc các hiệu ứng phụ, giúp loại bỏ các lỗi gây ra bởi nhiều chức năng cạnh tranh cho cùng một tài nguyên. Với các tính năng như tính khả dụng của point-free-style (hay còn gọi là lập trình ngầm), các chức năng có xu hướng được đơn giản hóa hoàn toàn và dễ dàng bố cục lại để code có thể tái sử dụng thường xuyên hơn so với OOP.

FP cũng có xu hướng ủng hộ các phong cách khai báo và biểu thị, không viết ra các hướng dẫn từng bước cho các hoạt động, mà thay vào đó, tập trung vào những gì cần làm (what) và để các chức năng cơ bản đảm nhiệm cách thức (how). Điều này mở ra khả năng to lớn cho việc tái cấu trúc và tối ưu hóa hiệu suất, thậm chí cho phép bạn thay thế toàn bộ thuật toán bằng những thuật toán hiệu quả hơn với rất ít thay đổi trong code. (ví dụ: ghi nhớ hoặc sử dụng lazy evaluation thay cho eager evaluation.)

Nhược điểm của FP: Việc khai thác quá mức các tính năng FP như point-free-style và các bố cục lớn có thể làm giảm khả năng đọc (readability) vì result code thường được chỉ định trừu tượng hơn, ngắn gọn hơn và ít cụ thể hơn.

Nhiều người quen thuộc với OOP và lập trình mệnh lệnh hơn là FP, vì vậy ngay cả những thành ngữ phổ biến trong FP cũng có thể gây nhầm lẫn cho người mới.

Ngoài ra, FP có đường cong học tập dốc hơn nhiều so với OOP vì sự phổ biến rộng rãi của OOP đã tạo nên cộng đồng trao đổi sôi động quanh các ngôn ngữ và tài liệu OOP. Trong khi ngôn ngữ của FP có xu hướng học thuật và trang trọng hơn nhiều. Các khái niệm FP thường được viết về cách sử dụng các thành ngữ và ký hiệu từ giải tích lambda, đại số và lý thuyết phạm trù, tất cả đều đòi hỏi một nền tảng kiến ​​thức trước về các lĩnh vực đó để hiểu được.

Trong câu trả lời phải có:

  • Đề cập đến rắc rối với shared state, sự cạnh tranh cho cùng một tài nguyên, v.v.
  • Khả năng của FP trong việc đơn giản hóa hoàn toàn nhiều ứng dụng.
  • Sự khác biệt trong các đường cong học tập.
  • Phân tích các hiệu ứng phụ và cách chúng tác động đến khả năng bảo trì chương trình.

Báo động đỏ:

  • Không thể liệt kê các nhược điểm của hai phong cách lập trình này, vì bất kỳ ai từng trải nghiệm với một trong hai phong cách hẳn sẽ phải đối mặt với một số hạn chế.

5. Two-way data binding (ràng buộc dữ liệu hai chiều) và one-way data flow (luồng dữ liệu một chiều) trong JavaScript là gì và chúng khác nhau như thế nào?

Two-way data binding có nghĩa là các trường giao diện người dùng (UI) được ràng buộc với dữ liệu mô hình động để khi một trường UI thay đổi, dữ liệu mô hình thay đổi theo nó và ngược lại.

One-way data flow có nghĩa là mô hình là nguồn sự thật duy nhất (single source of truth). Những thay đổi trong UI kích hoạt thông báo báo hiệu ý định của người dùng đối với mô hình (hoặc "store" trong React). Chỉ mô hình mới có quyền truy cập để thay đổi trạng thái của ứng dụng. Hệ quả là dữ liệu luôn chảy theo một hướng duy nhất, giúp nó dễ hiểu hơn.

One-way data flow là xác định, trong khi two-way data binding có thể gây ra các hiệu ứng phụ khó theo dõi và nắm bắt hơn.

Câu trả lời nên có:

  • React là ví dụ kinh điển mới về luồng dữ liệu một chiều, vì vậy việc đề cập đến React là một tín hiệu tốt. Cycle.js là một cách triển khai phổ biến khác của luồng dữ liệu đơn hướng.
  • Angular là một khuôn khổ phổ biến sử dụng ràng buộc hai chiều.

Thẻ đỏ:

  • Không có hiểu biết về hai thứ trên hoặc không thể nói rõ sự khác biệt.

6.  Lập trình không đồng bộ là gì và tại sao nó lại quan trọng trong JavaScript?

Lập trình không đồng bộ là loại bỏ các điều kiện và lệnh gọi hàm, mã được thực hiện tuần tự từ trên xuống dưới, chặn các tác vụ chạy dài như yêu cầu mạng và disk I/O. Về bản chất, giao diện người dùng (UI) là không đồng bộ và dành phần lớn thời gian của chúng để chờ thông tin nhập của người dùng để làm gián đoạn vòng lặp sự kiện và kích hoạt trình xử lý sự kiện.

NodeJS cũng không đồng bộ theo mặc định, có nghĩa là máy chủ hoạt động theo cùng một cách. Trong một vòng lặp nó chờ đợi một yêu cầu mạng và chấp nhận nhiều yêu cầu hơn trong khi yêu cầu đầu tiên đang được xử lý.

Lập trình không đồng bộ rất quan trọng trong JavaScript, bởi vì nó rất phù hợp với code UI và rất có lợi cho hiệu suất trên máy chủ.

Câu trả lời nên có:

  • Hiểu biết về ý nghĩa của blocking và tác động của hiệu suất.
  • Hiểu biết về xử lý sự kiện (event) và lý do tại sao sự kiện lại quan trọng đối với code UI.

Thẻ đỏ:

  • Không quen thuộc với các thuật ngữ asynchronous (không đồng bộ) hoặc synchronous (đồng bộ).
  • Không thể nêu rõ các hàm ý về hiệu suất hoặc mối quan hệ giữa asynchronous code và UI code.

Kết luận

Bám sát vào các chủ đề cấp cao. Nếu họ có thể trả lời những câu hỏi này, điều đó thường có nghĩa là họ có đủ kinh nghiệm lập trình để tiếp thu các câu hỏi và cú pháp ngôn ngữ trong vài tuần, ngay cả khi họ không có nhiều kinh nghiệm về JavaScript.



Tổng hợp việc làm IT - Software trên VietnamWorks
VietnamWorks InTECH
Theo Eric Elliott