概念

  • 使用者无权访问目标对象
  • 中间加代理,通过代理做授权和控制

代码

/**
 * 真正的类
 */
class RealImg {
  constructor(fileName) {
    this.fileName = fileName
  }
 
  display() {
    console.log(`display....${this.fileName}`)
  }
 
  loadFromDisk() {
    console.log(`loading....${this.fileName}`)
  }
}
 
/**
 * 代理类
 */
class ProxyImg {
  constructor(fileName) {
    this.realImg = new RealImg(fileName)
  }
 
  display() {
    this.realImg.display()
  }
}
 
const img = new ProxyImg("一张图片")
img.display() // display....一张图片

使用场景

网页事件代理

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <p>FUCK JS !</p>
    <div id="box">
      <span href="">A1</span>
      <span href="">A2</span>
      <span href="">A3</span>
      <span href="">A4</span>
      <span href="">A5</span>
    </div>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script>
      var $div = document.getElementById("box")
      $div.addEventListener("click", function (e) {
        const target = e.target
        if (target.nodeName === "SPAN") {
          console.log(target.innerHTML)
        }
      })
    </script>
  </body>
</html>

JQuery 代理

// 错误写法
$("#box").click(function () {
  setTimeout(function () {
    console.log("this:", this) // this === window
    $(this).css("background-color", "yellow")
  }, 300)
})
 
// 普通写法
$("#box").click(function () {
  var _this = this
  setTimeout(function () {
    $(_this).css("background-color", "yellow")
  }, 300)
})
 
// jquery代理
$("#box").click(function () {
  var fn = function () {
    $(this).css("background-color", "yellow")
  }
  fn = $.proxy(fn, this)
 
  setTimeout(fn, 1000)
})

ES6 Proxy

const star = {
  name: "柳岩",
  age: 26,
  phone: 13123936928,
}
 
const agent = new Proxy(star, {
  get: function (target, key) {
    if (key === "phone") {
      return "agent 1515818292"
    }
 
    if (key === "price") {
      return 12000
    }
 
    return target[key]
  },
 
  set: function (target, key, val) {
    if (key === "customPrice") {
      if (val < 10000) {
        throw new Error("价格太低了")
      } else {
        target[key] = val
        return true
      }
    }
  },
})
 
console.log(agent.name)
console.log(agent.age)
console.log(agent.phone)
console.log(agent.price)
 
agent.customPrice = 80000
console.log("agent customPrice:", agent.customPrice)

设计原则验证

  • 代理类和目标类分离,隔离开目标类和使用者
  • 符合开放封闭原则