Việc sử dụng câu lệnh `with` với Proxy là một thực tiễn tồi?


8

Trước hết, tôi muốn làm rõ, tôi biết rằng withbị phản đối , và sử dụng nó 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 undefinedtừ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 withvà không thể giới hạn quyền truy cập vào các biến được tạo bằng letconst.

Ý tưởng

Ý tưởng là sử dụng một Proxyđối số của with...

  • hasbẫy luôn quay trở lại true, 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ài withtuyên bố
  • getBẫy hoạt động bình thường, ngoại trừ việc chúng ném ReferenceErrors 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ằng Object.create(null))
  • targetđối tượng có một thuộc @@unscopablestí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ề withtuyê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 withtuyê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ì?


Nghe có vẻ như những gì bạn thực sự muốn là chạy mã bên trong một hộp cát. Có, một hộp cát có thể sử dụng proxy trong quá trình triển khai, nhưng có lẽ bạn không nên tự viết.
Bergi

@Bergi Tôi biết rằng cơ chế hộp cát sẽ phức tạp hơn cái này, nhưng câu hỏi của tôi không thực sự là liệu hộp cát này có an toàn và tốt không, nhưng thay vào đó, nếu sử dụng cách withnày có tệ hay không.
FZ

Chà, nó vẫn ngăn bạn sử dụng chế độ nghiêm ngặt, và truy cập các thuộc tính thông qua withvà 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 withnhư một công cụ dường như để làm những gì bạn cần.
Bergi

Câu trả lời:


1

Âm thanh như chủ đề phạm vi từ vựng và động cũ tốt . Trong phạm vi từ vựng nói chung là an toàn hơn nhưng trong một số trường hợp, phạm vi động có ý nghĩa, bởi vì nó đơn giản hóa một số giải pháp rất nhiều. Tôi muốn nói ví dụ của bạn là một trong những trường hợp, trong đó nó có thể hữu ích.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.