Strict mode và sloppy mode

Từ phiên bản ECMAScript 5, JavaScript có hai chế độ làm việc:

  • Chế độ thông thường (sloppy mode) là chế độ hoạt động mặc định của các script.
  • Chế độ nghiêm ngặt (strict mode) được dùng mặc định trong các module và các lớp, và cũng có thể kích hoạt trong các script.

Hiện nay, bạn hiếm khi sử dụng sloppy mode trong mã JavaScript, bởi hầu hết mã JavaScript được viết trong các module.

Chuyển sang strict mode

Trong một file script và CommonJS module, bạn chuyển sang strict mode bằng cách đặt dòng sau ở vị trí đầu tiên:

'use strict';

Bạn cũng có thể chuyển sang strict mode chỉ trong một hàm:

function functionInStrictMode() {
  'use strict';
}

Những điểm cải thiện trong strict mode

Đầu tiên, trong sloppy mode, ghi giá trị cho những biến chưa khai báo sẽ tạo ra biến toàn cục:

function sloppyFunc() {
  undeclaredVar1 = 123;
}
sloppyFunc();
// Tạo biến toàn cục 'undeclaredVar1'
assert.equal(undeclaredVar1, 123);

Trong strict mode, bạn không được phép làm điều này. Nếu vẫn thực hiện, lỗi ReferenceError được tạo ra:

function strictFunc() {
  'use strict';
  undeclaredVar2 = 123;
}
assert.throws(
  () => strictFunc(),
  {
    name: 'ReferenceError',
    message: 'undeclaredVar2 is not defined',
  }
);

Thứ hai, trong strict mode, hàm được tạo qua khai báo hàm chỉ tồn tại bên trong khối lệnh chứa khai báo và các khối lệnh bên trong khối lệnh này (nếu có):

function strictFunc() {
  'use strict';
  {
    function foo() { return 123; }
  }
  return foo(); // ReferenceError
}
assert.throws(
  () => strictFunc(),
  {
    name: 'ReferenceError',
    message: 'foo is not defined',
  }
 );

Trong sloppy mode, hàm tạo qua khai báo hàm tồn tại bên trong hàm chứa nó và các hàm bên trong hàm này (nếu có):

function sloppyFunc() {
  {
    function foo() { return 123 }
  }
  return foo(); // works
}
assert.equal(sloppyFunc(), 123);

Thứ ba, strict mode tạo ra lỗi nếu bạn thay đổi dữ liệu không thể thay đổi:

function strictFunc() {
  'use strict';
  true.prop = 1; // TypeError
}
assert.throws(
  () => strictFunc(),
  {
    name: 'TypeError',
    message: "Cannot create property 'prop' on boolean 'true'",
   }
);

Trong sloopy mode, lỗi này bị bỏ qua:

function sloppyFunc() {
  true.prop = 1; // fails silently
  return true.prop;
}
assert.equal(sloppyFunc(), undefined);