Cách sử dụng use strict trong JavaScript

Javascript căn bản | by Học Javascript

Trong JavaScript, chế độ nghiêm ngặt ("use strict") là một tính năng giúp lập trình viên viết mã an toàn hơn bằng cách áp dụng các quy tắc chặt chẽ hơn khi thực thi chương trình. Khi kích hoạt "use strict", JavaScript sẽ hạn chế các lỗi tiềm ẩn, chẳng hạn như khai báo biến không rõ ràng, sử dụng từ khóa bị cấm hoặc trùng lặp tham số trong hàm.

Việc sử dụng "use strict" rất quan trọng vì nó giúp phát hiện lỗi sớm, tránh những hành vi không mong muốn và đảm bảo mã nguồn hoạt động một cách nhất quán hơn. Ngoài ra, chế độ này còn giúp tối ưu hóa hiệu suất khi JavaScript Engine có thể thực thi mã nhanh hơn bằng cách loại bỏ các tính năng lỗi thời.

Bằng cách áp dụng "use strict", lập trình viên có thể viết mã chất lượng cao hơn, giảm thiểu lỗi và đảm bảo ứng dụng hoạt động ổn định hơn. Vậy "use strict" hoạt động như thế nào, và nó ảnh hưởng ra sao đến cách viết mã trong JavaScript? Hãy cùng tìm hiểu chi tiết trong bài viết này.

Khái niệm "use strict" là gì?

"use strict" là một chế độ trong JavaScript giúp thực thi mã với các quy tắc chặt chẽ hơn, nhằm tránh những lỗi tiềm ẩn và hạn chế các hành vi không mong muốn. Khi bật "use strict", JavaScript sẽ không cho phép sử dụng các cú pháp không an toàn và cảnh báo về những lỗi có thể gây ra bug trong mã.

Chế độ "use strict" được giới thiệu từ phiên bản ECMAScript 5 (ES5) để giúp lập trình viên viết mã tốt hơn và hạn chế những lỗi thường gặp trong JavaScript như:

  • Khai báo biến mà không sử dụng var, let hoặc const.
  • Gán giá trị cho các biến chỉ đọc hoặc không thể ghi (read-only).
  • Sử dụng các từ khóa bị cấm hoặc không hợp lệ trong tương lai.
  • Trùng lặp tham số trong một hàm.

Cách kích hoạt chế độ nghiêm ngặt trong JavaScript

Có hai cách để bật chế độ "use strict" trong JavaScript:

  • Kích hoạt cho toàn bộ script
  • Kích hoạt trong phạm vi một hàm cụ thể

Cách 1: Kích hoạt "use strict" cho toàn bộ script

Để bật chế độ nghiêm ngặt cho toàn bộ tệp JavaScript, bạn chỉ cần đặt dòng "use strict"; ở đầu tệp:

"use strict";

x = 10; // Lỗi: x chưa được khai báo
console.log(x);

Giải thích:

  • Dòng "use strict"; đặt ở đầu tệp sẽ áp dụng cho toàn bộ mã JavaScript sau đó.
  • Biến x bị lỗi vì chưa được khai báo với var, let hoặc const.

Cách 2: Kích hoạt "use strict" trong một hàm cụ thể

Nếu chỉ muốn áp dụng "use strict" trong một hàm mà không ảnh hưởng đến toàn bộ chương trình, bạn có thể đặt nó trong phạm vi hàm như sau:

function myFunction() {
    "use strict";
    y = 20; // Lỗi: y chưa được khai báo
    console.log(y);
}

myFunction(); 

Giải thích:

  • Chế độ nghiêm ngặt chỉ áp dụng bên trong hàm myFunction().
  • Khi thực thi, JavaScript phát hiện biến y chưa được khai báo, dẫn đến lỗi.

Ví dụ minh họa về sự khác biệt giữa "use strict" và chế độ mặc định

Ví dụ 1: Không có "use strict" (JavaScript mặc định)
x = 5; // Không có lỗi
console.log(x); // Output: 5
  • JavaScript tự động tạo biến x trong phạm vi toàn cục ngay cả khi không có var, let, hoặc const.
Ví dụ 2: Với "use strict"
"use strict";
x = 5; // Lỗi: x chưa được khai báo
console.log(x);
  • Trình thông dịch JavaScript sẽ báo lỗi ngay lập tức vì x chưa được khai báo đúng cách.

Tác động của "use strict" trong Javacript

Khi bật "use strict", JavaScript áp dụng các quy tắc nghiêm ngặt hơn để hạn chế các lỗi tiềm ẩn trong mã. Dưới đây là những tác động chính của "use strict" và các ví dụ minh họa.

Ngăn chặn khai báo biến không rõ ràng

Trong chế độ bình thường (không có "use strict"), nếu bạn quên khai báo biến bằng var, let hoặc const, JavaScript sẽ tự động tạo một biến toàn cục. Điều này có thể gây ra lỗi khó phát hiện, đặc biệt khi làm việc với các hàm lớn.

Ví dụ không có "use strict" (biến toàn cục được tạo tự động)

function test() {
    x = 10; // Không có lỗi, x tự động trở thành biến toàn cục
    console.log(x);
}

test();
console.log(x); // Vẫn truy cập được x

Lỗi tiềm ẩn: Biến x bị tạo toàn cục mà không có cảnh báo. Điều này có thể dẫn đến xung đột biến và lỗi logic khó phát hiện.

Ví dụ với "use strict" (ngăn chặn khai báo không rõ ràng)

"use strict";

function test() {
    y = 10; // Lỗi: y chưa được khai báo
    console.log(y);
}

test();

Giúp phát hiện lỗi ngay lập tức, yêu cầu khai báo rõ ràng bằng var, let hoặc const.

Không cho phép gán giá trị cho biến chỉ đọc

Trong JavaScript, một số thuộc tính hoặc biến là chỉ đọc (read-only). Khi bật "use strict", bạn không thể thay đổi giá trị của những biến này.

Ví dụ: Gán giá trị cho undefined, NaN hoặc Infinity

"use strict";

undefined = 5; // Lỗi: Không thể gán giá trị cho undefined
NaN = 123; // Lỗi: Không thể thay đổi giá trị của NaN
Infinity = 9; // Lỗi: Không thể thay đổi giá trị của Infinity

Lợi ích: Ngăn chặn việc thay đổi các giá trị hệ thống, giúp chương trình hoạt động đúng như mong đợi.

Cấm trùng lặp tham số trong hàm

Trong chế độ bình thường, JavaScript cho phép khai báo hai tham số trùng tên trong một hàm. Điều này có thể gây lỗi logic và khó bảo trì.

Ví dụ không có "use strict" (trùng lặp tham số hợp lệ nhưng nguy hiểm)

function sum(a, a) { // Không có lỗi
    console.log(a); // Tham số thứ hai sẽ ghi đè tham số thứ nhất
}

sum(1, 2); // Output: 2

Lỗi tiềm ẩn: Giá trị tham số đầu tiên bị ghi đè mà không có cảnh báo.

Ví dụ với "use strict" (ngăn chặn trùng lặp tham số)

"use strict";

function sum(a, a) { // Lỗi: Trùng lặp tham số
    console.log(a);
}

Giúp viết mã rõ ràng, tránh lỗi do ghi đè giá trị tham số.

Ngăn chặn xóa các thuộc tính không thể xóa (non-configurable)

Một số thuộc tính trong JavaScript là không thể xóa (non-configurable). Khi bật "use strict", việc cố gắng xóa các thuộc tính này sẽ gây lỗi.

Ví dụ không có "use strict" (xóa thuộc tính không thể xóa không báo lỗi)

var obj = Object.freeze({ name: "Alice" }); // Đóng băng đối tượng, không thể thay đổi
delete obj.name; // Không có lỗi nhưng không xóa được
console.log(obj.name); // Output: Alice

Lỗi tiềm ẩn: JavaScript không báo lỗi, nhưng thuộc tính vẫn không bị xóa, gây hiểu lầm cho lập trình viên.

Ví dụ với "use strict" (ngăn chặn xóa thuộc tính không thể xóa)

"use strict";

var obj = Object.freeze({ name: "Alice" });
delete obj.name; // Lỗi: Không thể xóa thuộc tính không thể xóa

Ngăn chặn lỗi do cố gắng thao tác với các thuộc tính không thể thay đổi.

Ngăn chặn sử dụng từ khóa bị cấm (reserved keywords)

Một số từ khóa được dự trữ trong JavaScript cho các tính năng trong tương lai. Khi bật "use strict", bạn không thể sử dụng các từ này làm tên biến hoặc hàm.

Ví dụ không có "use strict" (vẫn có thể sử dụng từ khóa bị cấm, nhưng có thể gây lỗi trong tương lai)

var public = "Hello"; // Không có lỗi nhưng không nên sử dụng
console.log(public);

Lỗi tiềm ẩn: Mã có thể hoạt động bây giờ, nhưng sẽ không hoạt động trên các phiên bản JavaScript mới hơn.

Ví dụ với "use strict" (ngăn chặn sử dụng từ khóa bị cấm)

"use strict";

var public = "Hello"; // Lỗi: 'public' là từ khóa bị cấm
Lợi ích: Đảm bảo mã tương thích với các tiêu chuẩn JavaScript mới hơn.

Ứng dụng "use strict" trong thực tế trong Javacript

Chế độ "use strict" không chỉ giúp lập trình viên viết mã JavaScript an toàn hơn mà còn tối ưu hiệu suất của trình thông dịch JavaScript (JavaScript Engine). Dưới đây là một số ứng dụng quan trọng của "use strict" trong thực tế:

Giúp phát hiện lỗi sớm và tránh lỗi tiềm ẩn

Trong JavaScript thông thường, một số lỗi không bị báo lỗi ngay lập tức, dẫn đến lỗi tiềm ẩn khó phát hiện. "use strict" giúp ngăn chặn những lỗi phổ biến này.

Ví dụ: Quên khai báo biến

// Không sử dụng "use strict"
function test() {
    x = 10; // Không có lỗi, nhưng x sẽ là biến toàn cục
    console.log(x);
}

test();
console.log(x); // Vô tình tạo ra một biến toàn cục không mong muốn

Lỗi tiềm ẩn: Biến x bị tạo thành biến toàn cục một cách vô tình, gây khó kiểm soát.

Ví dụ: Với "use strict" sẽ báo lỗi ngay lập tức

"use strict";

function test() {
    x = 10; // Lỗi: x chưa được khai báo
    console.log(x);
}

test();

Phát hiện lỗi ngay từ khi biên dịch, giúp viết mã an toàn hơn.

Tối ưu hiệu suất của JavaScript Engine

Khi bật "use strict", trình thông dịch JavaScript có thể tối ưu hiệu suất tốt hơn vì:

  • Loại bỏ các hành vi không chuẩn trong JavaScript.
  • Giúp trình thông dịch tối ưu bộ nhớ và quản lý biến hiệu quả hơn.
  • Ngăn chặn các lỗi không mong muốn giúp trình thông dịch không cần xử lý các lỗi này trong runtime.

Ví dụ, khi sử dụng "use strict", trình thông dịch có thể bỏ qua một số cơ chế hỗ trợ cho các tính năng lỗi thời như with statement hoặc tự động tạo biến toàn cục. Điều này giúp mã chạy nhanh hơn trên các trình duyệt hiện đại.

Bắt buộc sử dụng trong JavaScript hiện đại và ES6+

Nhiều tính năng mới trong JavaScript ES6 trở lên đã mặc định tuân theo "use strict", chẳng hạn như:

  • Class trong JavaScript: Luôn ở chế độ nghiêm ngặt.
  • Module ES6: Mặc định chạy ở "use strict", dù không cần khai báo.

Ví dụ: class mặc định sử dụng "use strict"

class User {
    constructor(name) {
        this.name = name;
    }

    sayHello() {
        message = "Hello " + this.name; // Lỗi: message chưa được khai báo
        console.log(message);
    }
}

const user = new User("Alice");
user.sayHello();

Không cần khai báo "use strict" nhưng vẫn được hưởng các lợi ích của chế độ nghiêm ngặt.

Những lưu ý khi sử dụng "use strict" trong Javacript

Khi làm việc với "use strict", cần nắm rõ các quy tắc sau để tránh lỗi không mong muốn.

"use strict" áp dụng cho toàn bộ script nếu đặt ở đầu file

Nếu "use strict" được đặt ở đầu file JavaScript, toàn bộ script sẽ chạy ở chế độ nghiêm ngặt.

Ví dụ: Áp dụng cho toàn bộ file

"use strict"; 

var x = 10;
console.log(x);

Toàn bộ mã trong file sẽ tuân theo quy tắc của "use strict".

Lưu ý: Nếu đặt "use strict" không đúng vị trí (ví dụ, sau một dòng mã khác), nó sẽ không có hiệu lực.

Ví dụ sai (Không kích hoạt "use strict")

var x = 10; // Không có lỗi

"use strict"; // Không có tác dụng vì không ở đầu file

y = 20; // Không báo lỗi (do "use strict" không có hiệu lực)
console.log(y);

Nếu sử dụng trong một hàm, chỉ ảnh hưởng trong phạm vi hàm đó

Bạn có thể chỉ kích hoạt "use strict" trong một hàm mà không ảnh hưởng đến toàn bộ file.

Ví dụ: "use strict" chỉ áp dụng trong một hàm

function strictFunction() {
    "use strict";
    z = 30; // Lỗi: z chưa được khai báo
}

function normalFunction() {
    w = 40; // Không lỗi vì không có "use strict"
}

strictFunction();
normalFunction();
console.log(w); // 40

Có thể chọn áp dụng "use strict" chỉ cho một số phần của chương trình mà không ảnh hưởng đến mã cũ.

Một số tính năng mới của ES6 đã mặc định tuân theo "use strict"

Như đã đề cập, classmodule ES6 tự động chạy trong chế độ nghiêm ngặt mà không cần khai báo "use strict".

Ví dụ: Module ES6 không cần "use strict"

File module.js

export function greet(name) {
    message = "Hello " + name; // Lỗi: message chưa khai báo
    console.log(message);
}

File main.js

import { greet } from './module.js';

greet("Alice");

Các module ES6 tự động tuân theo "use strict", giúp viết mã an toàn hơn mà không cần khai báo thủ công.

Kết bài

Chế độ "use strict" trong JavaScript là một công cụ hữu ích giúp lập trình viên phát hiện lỗi sớm, tránh các hành vi không mong muốn và tối ưu hiệu suất của mã nguồn. Bằng cách loại bỏ các lỗi tiềm ẩn như khai báo biến không rõ ràng, trùng lặp tham số hay sử dụng các từ khóa bị cấm, "use strict" giúp cải thiện chất lượng và độ tin cậy của chương trình.

Ngoài ra, "use strict" đã trở thành một phần quan trọng trong JavaScript hiện đại, đặc biệt là với ES6 trở lên, khi các module và class mặc định chạy trong chế độ nghiêm ngặt. Vì vậy, để viết mã an toàn, dễ bảo trì và hiệu quả hơn, các lập trình viên nên áp dụng "use strict" một cách hợp lý trong các dự án của mình.

Bài viết liên quan