Một số lỗi khi sử dụng Strict mode JavaScript

Posted on July 16th, 2017

Trong bài viết trước, mình có đề cập tới việc sử dụng Strict mode trong việc giảm thiểu những lỗi ngớ ngẩn của lập trình viên khi lập trình JavaScript. Như đã hứa, mình sẽ đưa ra một số lỗi phổ biến khi sử dụng chế độ này.

Sử dụng biến không khai báo

Bình thường khi bạn đưa ra một biến mà không khai báo thì mặc định biến đó sẽ trở thành một thuộc tính của đối tượng global. Đối với browser thì đối tượng global đó chính là window.

x = 10;
console.log(window.x);
// => 10

Ở chế độ strict mode, bạn sẽ bị lỗi x chưa được định nghĩaUncaught ReferenceError: x is not defined

x = 10;
console.log(window.x);
// => Uncaught ReferenceError: x is not defined

Gán giá trị cho biến global, thuộc tính chỉ đọc, thuộc tính getter

Ở chế độ bình thường, việc gán giá trị cho biến Global như Infinity, NaN,... hay những thuộc tính chỉ đọc,... sẽ không có thông báo lỗi. Mặc dù việc gán giá trị này là hoàn toàn sai và không có ý nghĩa.

var undefined = 5;
console.log(undefined);
// => undefined

var NaN = 10;
console.log(NaN);
// => NaN

var Infinity = 11;
console.log(Infinity);
// => Infinity

var obj = {};
Object.defineProperty(obj, 'x', {value: 42, writable: false});
obj.x = 9;
console.log(obj.x);
// => 42

var obj = {get x(){return 15;}};
obj.x = 10;
console.log(obj.x);
// => 15

var fixed = {};
Object.preventExtensions(fixed);
fixed.x = 10;
console.log(fixed.x);
// => undefined

Khi ở strict mode, bạn chắc chắn sẽ nhận được lỗi như:

  • Uncaught TypeError: Cannot assign to read only property 'undefined' of object '#<Window>'
  • Uncaught TypeError: Cannot assign to read only property 'NaN' of object '#<Window>'
  • Uncaught TypeError: Cannot assign to read only property 'Infinity' of object '#<Window>'
  • Uncaught TypeError: Cannot assign to read only property 'x' of object '#<Object>'
  • Uncaught TypeError: Cannot set property x of #<Object> which has only a getter
  • Uncaught TypeError: Cannot add property x, object is not extensible
var undefined = 5;
console.log(undefined);
// => Uncaught TypeError: Cannot assign to read only property 'undefined' of object '#<Window>'

var NaN = 10;
console.log(NaN);
// => Uncaught TypeError: Cannot assign to read only property 'NaN' of object '#<Window>'

var Infinity = 11;
console.log(Infinity);
// => Uncaught TypeError: Cannot assign to read only property 'Infinity' of object '#<Window>'

var obj = {};
Object.defineProperty(obj, 'x', {value: 42, writable: false});
obj.x = 9;
console.log(obj.x);
// => Uncaught TypeError: Cannot assign to read only property 'x' of object '#<Object>'

var obj = {get x(){return 15;}};
obj.x = 10;
console.log(obj.x);
// => Uncaught TypeError: Cannot set property x of #<Object> which has only a getter

var fixed = {};
Object.preventExtensions(fixed);
fixed.x = 10;
console.log(fixed.x);
// => Uncaught TypeError: Cannot add property x, object is not extensible

Xoá thuộc tính của đối tượng Global

Bình thường, bạn sẽ không thể xoá thuộc tính của một đối tượng Global, mặc dù không có thông báo lỗi nào. Khi ở strict mode, bạn sẽ bị lỗi nếu cố gắng xoá một thuộc tính của đối tượng Global:

Ví dụ: Uncaught TypeError: Cannot delete property 'prototype' of function Object() { [native code] }

'use strict';
delete Object.prototype;
// Uncaught TypeError: Cannot delete property 'prototype' of function Object() { [native code] }

Tên tham số trùng nhau ở khai báo hàm

Strict mode yêu cầu các tham số phải có tên khác nhau. Ngược lại thì bạn sẽ gặp lỗi:

Uncaught SyntaxError: Duplicate parameter name not allowed in this context

function sum(a, a, c){
  'use strict'
  return a + b + c;
}
// => Uncaught SyntaxError: Duplicate parameter name not allowed in this context

Thêm thuộc tính cho những giá trị nguyên thuỷ

Như bạn đã biết, giá trị nguyên thuỷ bao gồm: number, string, boolean. Ngược lại, bạn sẽ bị lỗi như:

  • Uncaught TypeError: Cannot create property 'true' on boolean 'false'
  • Uncaught TypeError: Cannot create property 'sailing' on number '14'
  • Uncaught TypeError: Cannot create property 'you' on string 'with'
'use strict';
false.true = false;
// => Uncaught TypeError: Cannot create property 'true' on boolean 'false'

(14).sailing = 'home';
// => Uncaught TypeError: Cannot create property 'sailing' on number '14'

'with'.you = 'far away';
// => Uncaught TypeError: Cannot create property 'you' on string 'with'

Xoá một biến thông thường ở Strict mode

Strict mode cấm bạn xoá tên biến. Ngược lại, bạn sẽ bị lỗi là:

Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.

'use strict';

var x = 10;
delete x;
// => Uncaught SyntaxError: Delete of an unqualified identifier in strict mode.

Đặt tên biến trùng với từ dự trữ

Ngoài từ khoá, JavaScript quy định danh sách những từ dự trữ - những từ sẽ được sử dụng làm từ khoá ở những phiên bản tiếp theo, như: implements, interface, let, package, private, protected, public, static, và yield.

Do đó, strict mode nghiêm cấm bạn đặt tên biến số trùng với những từ này. Nếu bạn đặt tên biến trùng với từ dự trữ thì bạn sẽ bị lỗi như sau:

Uncaught SyntaxError: Unexpected strict mode reserved word

'use strict';
var implements = 10;
// => Uncaught SyntaxError: Unexpected strict mode 

Kết luận

Trên đây là một số lỗi thường gặp phải khi bạn sử dụng JavaScript ở strict mode. Nói vậy, không có nghĩa là mình khuyên bạn tránh sử dụng strict mode. Ngược lại, chế độ này giúp bạn dễ dàng phát hiện lỗi. Và đây là sự đảm bảo cho code bạn không bị xung đột với những phiên bản JavaScript mới hơn sau này.

Bài viết này sẽ dừng lại ở đây.

Xin chào và hẹn gặp lại bạn ở bài viết tiếp theo, thân ái!

Tham khảo


★ Nếu bạn thấy bài viết này hay thì hãy theo dõi mình trên Facebook để nhận được thông báo khi có bài viết mới nhất nhé: