Trước hết, tôi muốn làm rõ, tôi biết rằng with
bị phản đối , và sử dụng nó là chung một thực tế xấu .
Tuy nhiên, câu hỏi của tôi là về một trường hợp đặc biệt: sử dụng một Proxy
đối tượng đặc biệt làm tham số của with
.
Lý lịch
Tôi đang làm việc trên một dự án, nơi tôi phải giới hạn quyền truy cập của một đoạn mã vào phạm vi toàn cầu.
Một cách tiếp cận có thể là sử dụng một vòng lặp với eval
, tạo ra các biến không đổi với giá trị của undefined
từng thuộc tính của đối tượng toàn cầu, nhưng điều đó dường như còn tồi tệ hơn việc sử dụng with
và không thể giới hạn quyền truy cập vào các biến được tạo bằng let
và const
.
Ý tưởng
Ý tưởng là sử dụng một Proxy
đối số của with
...
has
bẫy luôn quay trở lạitrue
, do đó nó không cho phép bất kỳ tra cứu hoặc bài tập nào vượt ra ngoàiwith
tuyên bốget
Bẫy hoạt động bình thường, ngoại trừ việc chúng némReferenceError
s khi cố gắng truy cập vào một biến không tồn tại (tức là thuộc tính)set
bẫy hoạt động bình thường (hoặc có thể chứa một số logic tùy chỉnh)target
đối tượng không có[[Prototype]]
(tức là nó được tạo bằngObject.create(null)
)target
đối tượng có một thuộc@@unscopables
tính, với giá trị của một đối tượng trống, để cho phép phạm vi của mọi thuộc tính
Vì vậy, một cái gì đó giống như mã này:
const scope = Object.create(null)
Object.assign(scope, {
undefined,
console,
String,
Number,
Boolean,
Array,
Object,
/* etc. */
[Symbol.unscopables]: Object.create(null)
})
const scopeProxy = new Proxy(scope, {
get: (obj, prop) => {
if (prop in obj)
return obj[prop]
else
throw new ReferenceError(`${prop} is not defined`)
},
set: Reflect.set,
has: () => true
})
with(scopeProxy) {
//Sandboxed code
foo = Number('42')
console.log(foo) //42
try{
console.log(scopeProxy) //Inaccessible
}catch(e){
console.error(e) //ReferenceError: scopeProxy is not defined
}
}
Tránh các cơn co thắt
Có một số điều khoản được liệt kê trên trang của MDN về with
tuyên bố , nhưng cách sử dụng này được loại bỏ.
1. Hiệu suất
Vấn đề:
Tra cứu các định danh không phải là thành viên của
with
đối tượng tham số của câu lệnh là ít hiệu suất hơn.Tránh:
Không có tra cứu có thể vượt ra ngoài đối tượng tham số.
2. Sự mơ hồ
Vấn đề:
Thật khó để quyết định, định danh nào được tra cứu từ những người có cùng tên.
Tránh:
Tất cả các tra cứu và bài tập lấy hoặc sửa đổi thuộc tính của đối tượng tham số.
3. Tương thích chuyển tiếp
Vấn đề:
Các thuộc tính của các đối tượng tham số hoặc nguyên mẫu của chúng có thể thay đổi trong tương lai.
Tránh:
Đối tượng tham số ban đầu trống và không có nguyên mẫu, do đó không có thuộc tính nào có thể thay đổi.
Câu hỏi
Đoạn mã trên hoạt động hoàn hảo và các điều khoản được liệt kê trên MDN không áp dụng cho điều này.
Vì vậy, câu hỏi của tôi là:
Nó vẫn là một thực hành xấu để sử dụng with
tuyên bố, và nếu vậy, những nhược điểm của việc sử dụng nó trong trường hợp này là gì?
with
này có tệ hay không.
with
và một proxy vẫn còn khá chậm. Tôi sẽ cố gắng tìm kiếm một giải pháp khác cho vấn đề tiềm ẩn, nhưng khác hơn là bạn chỉ đang sử dụng with
như một công cụ dường như để làm những gì bạn cần.