Không nên sử dụng with trong JavaScript
Ngày nay từ khoá with không được phép sử dụng trong Strict Mode
with là một từ khóa trong JavaScript cho phép bạn tạm thời đưa một đối tượng vào đầu scope chain, nhờ đó có thể truy cập các thuộc tính của đối tượng mà không cần lặp lại tên đối tượng.
Tuy nhiên, with không được phép trong Strict Mode và chúng ta cũng không nên sử dụng.
Cú pháp
with (object) {
// truy cập trực tiếp các thuộc tính của object
}
Ví dụ:
const person = {
name: 'Andy',
age: 25,
};
with (person) {
console.log(name); // "Andy"
console.log(age); // 25
}
Tương đương với:
console.log(person.name);
console.log(person.age);
Ví dụ dễ gây nhầm lẫn
const person = {
name: 'Andy',
};
const name = 'Nacy';
with (person) {
console.log(name);
}
Bạn nghĩ kết quả là gì?
Andy
Bởi vì with sẽ ưu tiên tìm name trong person trước.
Nếu thuộc tính không tồn tại:
const person = {
age: 25,
};
const name = 'Nacy';
with (person) {
console.log(name);
}
Kết quả:
Nacy
JavaScript sẽ tiếp tục tìm trong scope bên ngoài.
Vấn đề của with
1. Khó biết biến đến từ đâu
const person = {
age: 25,
};
let name = 'Andy';
with (person) {
console.log(name);
}
Khi đọc đoạn code này, bạn không biết:
namelà biến toàn cục?person.name?- Hay một biến cục bộ?
Phải đọc toàn bộ chương trình mới xác định được.
2. Hiệu năng kém
Thông thường:
person.name;
Engine biết ngay phải truy cập thuộc tính của person.
Nhưng với:
with (person) {
console.log(name);
}
Engine phải tra cứu:
person.name ?
↓
scope hiện tại ?
↓
scope cha ?
↓
global ?
Việc tra cứu động này khiến JavaScript khó tối ưu.
3. Dễ sinh lỗi
Ví dụ:
const obj = {};
let value = 100;
with (obj) {
console.log(value);
}
Sau này có người thêm:
obj.value = 200;
Thì cùng một đoạn code lại in:
200
Thay vì:
100
Code thay đổi hành vi chỉ vì đối tượng được bổ sung thuộc tính.
4. Không dùng được trong Strict Mode
'use strict';
with ({ x: 1 }) {
console.log(x);
}
Kết quả:
SyntaxError: Strict mode code may not include a with statement
Tại sao with từng tồn tại?
Thời JavaScript còn sơ khai, with giúp viết ngắn hơn.
Ví dụ:
const Math = window.Math;
with (Math) {
console.log(sin(1));
console.log(cos(1));
console.log(pow(2, 3));
}
Thay vì:
console.log(Math.sin(1));
console.log(Math.cos(1));
console.log(Math.pow(2, 3));
Ngày nay, ta có thể dùng destructuring:
const { sin, cos, pow } = Math;
console.log(sin(1));
console.log(cos(1));
console.log(pow(2, 3));
Nên thay thế with bằng gì?
Cách 1: Gọi trực tiếp
console.log(person.name);
console.log(person.age);
Cách 2: Destructuring
const { name, age } = person;
console.log(name);
console.log(age);
Cách 3: Đặt biến tham chiếu
const p = person;
console.log(p.name);
console.log(p.age);
Kết luận
withthêm một đối tượng vào đầu scope chain, cho phép truy cập thuộc tính mà không cần ghi tên đối tượng.- Nó làm mã nguồn khó đọc, khó tối ưu, và dễ phát sinh lỗi khi đối tượng thay đổi.
withkhông được phép trong Strict Mode và bị xem là tính năng lỗi thời.- Trong JavaScript hiện đại, hãy ưu tiên truy cập trực tiếp thuộc tính hoặc sử dụng destructuring, vừa rõ ràng vừa thân thiện với trình tối ưu của JavaScript engine.