Người ta nói rằng để code giỏi hơn, bạn cần code nhiều nhiều hơn nữa để nâng cao tay nghề. Nhưng cá nhân mình nghĩ chừng đó thôi chưa đủ. Cần phải luôn xem xét, cập nhập thêm thông tin về thứ mình đang xài, phải hiểu thứ mình đã xài mới giỏi hơn được chứ phải không nào. Lấy Javascript là một ví dụ, code JS đã lâu, việc cập nhập hiểu biết về các tính năng mới đã giúp mình code ổn hơn khá nhiều, ổn đây là hạn chế số lượng line of code và hạn chế bugs.
Dạo gần đây JS tung ra rất nhiều tính năng mới, phần là để trở nên mạnh mẽ, phần là để bắt kịp xu hướng với các ngôn ngữ khác. Một trong số đó là toán tử optional chaining (?.). Việc thêm nhiều tính năng mỗi năm, khiến mình lười viết bài cập nhập tính năng luôn ấy :v.
Thực ra ngoài JS mình còn kiếm cơm bằng C# nữa, mà C# đã hỗ trợ toán tử này từ rất lâu, và đến bây giờ (thật ra cũng cách đây lâu lâu chút rồi) JS mới hỗ trợ nè. Nên hôm này chúng ta sẽ phân tích xem toán tử này có gì đặc biệt không nhé. Let’s go.
Mục đích tồn tại của optional chaining (?.)
Vậy mục đích của toán tử ?.
là gì, dùng trường hợp nào? Nếu bạn đã code JS chắc hẳn cái lỗi Cannot read property '<tên property>' of undefined
quen lắm đúng không. Lỗi này xảy ra khi bạn gọi một thuộc tính của một object mà object đó bị undefined hoặc null. Trường hợp phổ biến là object lồng nhau và bạn gọi kiểu “liên tục” như student.info.name.middleName....
. Ví dụ:
1 | var student = { |
Vì fullname
không có, nên khi “truy cập” fullname
để lấy giá trị thuộc tính middleName
thì sẽ gặp lỗi.
Ngày xưa để giải quyết vấn đề này người ta sẽ check if, (thường sẽ kết hợp dùng toán tử logical AND (&&)). Giả dụ:
student
là object có thểnull
hoặcundefined
- Nếu student có giá trị thì đó sẽ là một object và object LUÔN có property
info
- Và
info
cũng LUÔN LUÔN có giá trị là một object - Trong
info
CÓ THỂ sẽ có propertyname
, vàname
có thể có chứa các property khác nhưfirstName
,lastName
, vàmiddleName
.
Để đọc giá trị middleName
làm như sau:
1 | var student = { |
Dài dòng đúng không, lê thê dài dòng. Vậy là từ đó người ta quyết định xây dựng một toán tử để khi “truy cập” một object bị null/undefined thì “trình biên dịch” bỏ qua, không “truy cập” nữa tránh bị lỗi. Đó là mục đích của toán tử optional chaining (?.)
Ví dụ:
1 | var student = { |
Đinh nghĩa
Thôi không cần định nghĩa nữa ha, bạn quan tâm thì truy cập MDN để đọc nè.
Giải thích rõ hơn cơ chế
Trên ví dụ trên mình đã có nêu rồi, nhưng nếu bạn cần hiểu rõ hơn, hãy đọc đoạn này nha.
Đầu tiên hãy xem xét dòng code này student?.address?.street?.name
. Trình biên dịch sẽ check giá trị của biến đằng trước dấu ?
xem có giá trị không, nếu có tiếp tục “truy cập” (truy cập là dùng dấu .
đó) tới property tiếp theo. Trình biên dịch ra như sau:
1 | // mã giả thôi nha |
Nó sẽ đi theo từng bậc như vậy. Nếu biến đằng trước dấu ?
không có giá trị thì chương trình sẽ không .
(truy cập) đằng sau nữa, chương trình trả về undefined
.
Tất cả các bước này gói gọi lại ở hai dấu ?.
thần thánh. Tránh để lỗi xảy ra.
Ngoài ra (phần quan trọng)
Ngoài giúp truy cập biến object an toàn tránh bị lỗi. Nó còn hỗ trợ array
và function
nữa nha. Cơ chế cũng tương tự. Check array
có, thì cho truy cập index
. Check function
có tồn tại thì gọi. Ví dụ:
1 | var obj = { |
Nhưng lưu ý, nó chỉ check giá trị của biến đằng trước ?
khác null hoặc undefined thôi nha, chứ không check đó là kiểu gì có phải typeof === 'function'
hoặc array
hay không đâu nha.
Bạn thử obj.arr?.()
sẽ bị lỗi obj.arr is not a function
liền à.
Toán tử ?. với delete
Ngoài ra ?. còn sử dụng được với toán tử delete. Cũng giống khi “truy cập”, delete
sẽ check property đó có tồn tại không, nếu có thì xóa cho property. Ví dụ:
1 | delete student?.address?.street; // xóa thuộc tính street nếu student.address tồn tại |
Một lưu ý nữa là toán tử ?.
chỉ có thể đọc và xóa không thể set giá trị. Ví dụ:
1 | var obj = { |
Tóm lại
Mình nghĩ đây là cải tiến quan trọng mà JS có được, đây là toán tử cool ngầu mà khi code mình hay dùng nhất. Nó mà kết hợp với toán tử nullish coalescing (??) thì rất xịn. Về toán tử toán tử nullish coalescing (??) mình sẽ giới thiệu ở bài sau nha. Bye bye.