热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

JSProxy的优势以及使用场景

随着vue3.x的消息越来越多,proxy的讨论也。相对于Object.defineProperty,proxy有什么区别,有什么优势,以及可以应用在什么地方,该文章就简单的介绍下。

开汽车的人往往不了解汽车的构造,但是深入了解汽车的构造,可能会有如虎添翼的效果

前言

随着 vue3.x 的消息越来越多,proxy 的讨论也。相对于 Object.definePropertyproxy 有什么区别,有什么优势,以及可以应用在什么地方。该文章就简单的介绍下

Object.defineProperty

proxy 之前,先回顾下 Object.defineProperty 。大家都知道,vue2.x 以及之前的版本是使用 Object.defineProperty 实现数据的双向绑定的,至于是怎样绑定的呢?下面简单实现一下

function observer(obj) {
    if (typeof obj === 'object') {
        for (let key in obj) {
            defineReactive(obj, key, obj[key])
        }
    }
}
function defineReactive(obj, key, value) { //针对value是对象,递归检测
    observer(value) //劫持对象的key
    Object.defineProperty(obj, key, {
        get() {
            console.log('获取:' + key) return value
        },
        set(val) { //针对所设置的val是对象
            observer(val) console.log(key + "-数据改变了") value = val
        }
    })
}
let obj = {
    name: '守候',
    flag: {
        book: {
            name: 'js',
            page: 325
        },
        interest: ['火锅', '旅游'],
    }
}

observer(obj)

在浏览器的 console 执行一下,似乎能正常运行

由上图得知,虽然数组属性实际上是修改成功了,但是不能被监听到

问题3. 由于是使用递归遍历对象,使用 Object.defineProperty 劫持对象的属性,如果遍历的对象层级比较深,花的时间比较久,甚至有性能的问题

proxy

对于 proxy ,在 mdn 上的描述是: 对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等)

简单来说就是,可以在对目标对象设置一层拦截。无论对目标对象进行什么操作,都要经过这层拦截

听上去似乎,proxyObject.defineProperty 要好用,并且简单很多,实际上就是如此。下面用 proxy 对上面的代码进行改写试下

function observerProxy(obj) {
    let handler = {
        get(target, key, receiver) {
            console.log('获取:' + key) // 如果是对象,就递归添加 proxy 拦截
            if (typeof target[key] === 'object' && target[key] !== null) {
                return new Proxy(target[key], handler)
            }
            return Reflect.get(target, key, receiver)
        },
        set(target, key, value, receiver) {
            console.log(key + "-数据改变了") return Reflect.set(target, key, value, receiver)
        }
    }
    return new Proxy(obj, handler)
}
let obj = {
    name: '守候',
    flag: {
        book: {
            name: 'js',
            page: 325
        },
        interest: ['火锅', '旅游'],
    }
}
let objTest = observerProxy(obj)

也是一样的效果

表单校验

在对表单的值进行改动的时候,可以在 set 里面进行拦截,判断值是否合法

let ecValidate = {
    set(target, key, value, receiver) {
        if (key === 'age') { //如果值小于0,或者不是正整数
            if (value <0 || !Number.isInteger(value)) {
                throw new TypeError(&#39;请输入正确的年龄&#39;);
            }
        }
        return Reflect.set(target, key, value, receiver)
    }
}
let obj = new Proxy({
    age: 18
},
ecValidate) obj.age = 16obj.age = &#39;少年&#39;

增加附加属性

比如有一个需求,保证用户输入正确身份证号码之后,把出生年月,籍贯,性别都添加进用户信息里面

众所周知,身份证号码第一和第二位代表所在省(自治区,直辖市,特别行政区),第三和第四位代表所在市(地级市、自治州、盟及国家直辖市所属市辖区和县的汇总码)。第七至第十四位是出生年月日。低17位代表性别,男单女双。

const PROVINCE_NUMBER = {
    44 : &#39;广东省&#39;,
    46 : &#39;海南省&#39;
}
const CITY_NUMBER = {
    4401 : &#39;广州市&#39;,
    4601 : &#39;海口市&#39;
}
let ecCardNumber = {
    set(target, key, value, receiver) {
        if (key === &#39;cardNumber&#39;) {
            Reflect.set(target, &#39;hometown&#39;, PROVINCE_NUMBER[value.substr(0, 2)] + CITY_NUMBER[value.substr(0, 4)], receiver) Reflect.set(target, &#39;date&#39;, value.substr(6, 8), receiver) Reflect.set(target, &#39;gender&#39;, value.substr( - 2, 1) % 2 === 1 ? &#39;男&#39;: &#39;女&#39;, receiver)
        }
        return Reflect.set(target, key, value, receiver)
    }
}
let obj = new Proxy({
    cardNumber: &#39;&#39;
},
ecCardNumber)

数据格式化

比如有一个需求,需要传时间戳给到后端,但是前端拿到的是一个时间字符串,这个也可以用 proxy 进行拦截,当得到时间字符串之后,可以自动加上时间戳。

let ecArrayProxy = {
    get(target, key, receiver) {
        let _index = key <0 ? target.length + Number(key) : key
        return Reflect.get(target, _index, receiver)
    }
}
let arr = new Proxy([1, 2, 3], ecArrayProxy)

推荐教程:《JS教程》

以上就是JS Proxy 的优势以及使用场景的详细内容,更多请关注 第一PHP社区 其它相关文章!


推荐阅读
  • 深入解析Java SE、Java EE和Java Web的核心知识体系
    通过一系列图表全面解析Java SE、Java EE与Java Web的核心知识体系,帮助开发者快速掌握这些关键技术领域的要点。 ... [详细]
  • 本文详细探讨了如何根据不同的应用场景选择合适的PHP版本,包括多版本切换技巧、稳定性分析及针对WordPress等特定平台的版本建议。 ... [详细]
  • Python网络编程:深入探讨TCP粘包问题及解决方案
    本文详细探讨了TCP协议下的粘包现象及其产生的原因,并提供了通过自定义报头解决粘包问题的具体实现方案。同时,对比了TCP与UDP协议在数据传输上的不同特性。 ... [详细]
  • 实现Win10与Linux服务器的SSH无密码登录
    本文介绍了如何在Windows 10环境下使用Git工具,通过配置SSH密钥对,实现与Linux服务器的无密码登录。主要步骤包括生成本地公钥、上传至服务器以及配置服务器端的信任关系。 ... [详细]
  • PHP中Smarty模板引擎自定义函数详解
    本文详细介绍了如何在PHP的Smarty模板引擎中自定义函数,并通过具体示例演示了这些函数的使用方法和应用场景。适合PHP后端开发者学习。 ... [详细]
  • 本文探讨了在无法使用个人身份信息的情况下,利用他人(如网络上公开的个人信息)注册游戏账号的行为及其潜在的法律和道德问题。 ... [详细]
  • 本文由chszs撰写,详细介绍了Apache Mina框架的核心开发流程及自定义协议处理方法。文章涵盖从创建IoService实例到协议编解码的具体步骤,适合希望深入了解Mina框架应用的开发者。 ... [详细]
  • 本题提供了一个区间数组 intervals,其中每个区间 intervals[i] 包含两个整数 [starti, endi],并且所有 starti 值各不相同。任务是找到每个区间的右侧区间,即存在一个区间 j 满足 startj >= endi 并且 startj 是尽可能小的。返回一个数组,该数组包含每个区间右侧区间的索引;如果没有合适的右侧区间,则返回 -1。 ... [详细]
  • 本文介绍了使用Python和C语言编写程序来计算一个给定数值的平方根的方法。通过迭代算法,我们能够精确地得到所需的结果。 ... [详细]
  • C/C++ 应用程序的安装与卸载解决方案
    本文介绍了如何使用Inno Setup来创建C/C++应用程序的安装程序,包括自动检测并安装所需的运行库,确保应用能够顺利安装和卸载。 ... [详细]
  • 本文提供了一个关于AC自动机(Aho-Corasick Algorithm)的详细解析与实现方法,特别针对P3796题目进行了深入探讨。文章不仅涵盖了AC自动机的基本概念,还重点讲解了如何通过构建失败指针(fail pointer)来提高字符串匹配效率。 ... [详细]
  • 10月19日,限量免费参与IBM云计算大会
    10月19日,限量免费报名参加IBM云计算大会,探索前沿科技,推动商业转型。 ... [详细]
  • 本报告记录了嵌入式软件设计课程中的第二次实验,主要探讨了使用KEIL V5开发环境和ST固件库进行GPIO控制及按键响应编程的方法。通过实际操作,加深了对嵌入式系统硬件接口编程的理解。 ... [详细]
  • 本文分享了作者在使用LaTeX过程中的几点心得,涵盖了从文档编辑、代码高亮、图形绘制到3D模型展示等多个方面的内容。适合希望深入了解LaTeX高级功能的用户。 ... [详细]
  • LeetCode 102 - 二叉树层次遍历详解
    本文详细解析了LeetCode第102题——二叉树的层次遍历问题,提供了C++语言的实现代码,并对算法的核心思想和具体步骤进行了深入讲解。 ... [详细]
author-avatar
楠楠妈妈05乄23
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有