【ES6系列】Proxy 数据保护实例

本文介绍了一种利用Proxy对象在不修改原始数据的情况下,实现数据升序、降序及重置的方法。通过Vue.js示例展示了如何在前端应用中动态更新列表排序,并保持数据的原始状态。

业务场景:对数据进行升序、降序、重置操作而不影响原始数据,除了用闭包的方式实现之外,还可以用proxy来实现。 

<template>
  <div class="price">
    <ul>
      <li v-for="item in price"
          :key="item">{{item}}</li>
    </ul>
    <button type="button"
            @click="up">升序</button>
    <button type="button"
            @click="down">降序</button>
    <button type="button"
            @click="reset">重置</button>
  </div>
</template>
<script>
import axios from 'axios'
export default {
  data () {
    return {
      price: []
    }
  },
  methods: {
    up () {
      this.price = this.proxy.up
    },
    down () {
      this.price = this.proxy.down
    },
    reset () {
      this.price = this.proxy.default
    }
  },
  async mounted () {
    let { data: { price } } = await axios.get('/proxy')
    Object.freeze(price)
    this.proxy = new Proxy({}, {
      get (target, key) {
        if (key === 'up') {
          return [].concat(price).sort((a, b) => a - b)
        } else if (key === 'down') {
          return [].concat(price).sort((a, b) => b - a)
        } else {
          return price
        }
      },
      set () {
        return false
      }
    })
    this.price = this.proxy.default
  }
}
</script>
<style scoped>
ul,
li {
  list-style: none;
}
</style>

 

### ES6Proxy 对象的核心特性与使用方法 #### 1. **Proxy 的基本概念** `Proxy` 是 ECMAScript 6ES6)引入的一种新功能,用于拦截并重新定义对象的基本操作行为。它允许开发者在访问或修改目标对象时插入自定义逻辑[^1]。 --- #### 2. **核心组成部分** `Proxy` 主要由两部分组成: - **目标对象 (`target`):** 被代理的对象。 - **处理器 (`handler`):** 定义了一系列陷阱函数(trap functions),用来捕获对目标对象的操作。 以下是 `Proxy` 构造器的标准语法: ```javascript const proxy = new Proxy(target, handler); ``` 其中,`target` 可以是一个普通的对象、数组甚至函数;而 `handler` 则包含了各种可选的方法来拦截不同的操作。 --- #### 3. **常见的陷阱函数及其用途** ##### (1)数据验证——`set` 方法 当尝试设置某个属性的值时,可以通过 `set` 来执行额外的数据校验逻辑。例如: ```javascript let validator = { set: function (obj, prop, value) { if (prop === 'age') { if (!Number.isInteger(value)) { throw new Error('The age must be an integer'); } if (value > 200 || value < 0) { throw new Error('The age seems invalid'); } } obj[prop] = value; return true; } }; let person = new Proxy({}, validator); person.age = 18; // 正常赋值 console.log(person.age); // 输出 18 try { person.age = 'young'; // 抛出错误 } catch (e) { console.error(e.message); // The age must be an integer } ``` 上述代码展示了如何通过 `set` 实现简单的年龄字段校验。 --- ##### (2)读取控制——`get` 方法 可以利用 `get` 拦截对属性的读取请求,并返回经过加工后的结果。比如隐藏敏感信息或者提供默认值: ```javascript let user = { firstName: 'John', lastName: 'Doe' }; let handlerGet = { get: function (target, key) { if (!(key in target)) { return `${key} is not defined`; } return target[key]; } }; let proxiedUser = new Proxy(user, handlerGet); console.log(proxiedUser.firstName); // John console.log(proxiedUser.email); // email is not defined ``` 此示例说明了如何优雅地处理未定义键的情况[^4]。 --- ##### (3)实例化支持——`construct` 和 `apply` 如果目标本身是个构造函数,则可通过 `construct` 或者对于普通函数调用则借助于 `apply` 进行扩展管理[^3]。下面展示了一个例子,演示如何记录每次类实例化的次数: ```javascript function MyClass() {} MyClass.prototype.incrementCount = function () {}; let countHandler = { construct: function (target, args, newTarget) { const instance = Reflect.construct(...arguments); Object.defineProperty(instance, '_count', { writable: true }); instance._count++; return instance; }, }; let CountableClass = new Proxy(MyClass, countHandler); let a = new CountableClass(); a._count++; // 修改计数器变量 console.log(a._count); // 结果为 1 ``` 这里我们看到即使是在复杂场景下也能灵活运用 Proxies 提供的功能。 --- #### 4. **实际应用案例分析** 为了更直观理解其强大之处,在日常开发过程中经常遇到的需求之一就是实时监控某些特定状态的变化情况。这正是前面提到过的关于工程师信息更新的通知机制: ```javascript var engineer = { name: 'Alice', skills: ['JavaScript'] }; var interceptor = { set: function (receiver, property, value) { console.log(`${property} was updated from ${receiver[property]} to ${value}`); receiver[property] = value; } }; new Proxy(engineer, interceptor).skills.push('Python'); // Output: // skills was updated from ["JavaScript"] to ["JavaScript", "Python"] ``` 这段脚本清楚表明每当技能列表发生变化都会打印相应的日志消息出来。 --- ### 总结 综上所述,`Proxy` 不仅赋予了 JavaScript 更加丰富的元编程能力,还极大地增强了应用程序灵活性和可控度。无论是基础的数据验证还是高级别的框架设计都可以找到它的身影[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值