목차
서문" >서문
Object.defineProperty" >Object.defineProperty
Object.defineProperty
proxy" >proxy
proxy 使用场景" >proxy 使用场景
负索引数组" >负索引数组
🎜negative Index array🎜
表单校验" >表单校验
增加附加属性" >增加附加属性
数据格式化" >数据格式化
웹 프론트엔드 JS 튜토리얼 JS Proxy의 장점 및 사용 시나리오

JS Proxy의 장점 및 사용 시나리오

Jun 15, 2020 am 09:22 AM
javascript js vue

JS Proxy의 장점 및 사용 시나리오

자동차를 운전하는 사람들은 자동차의 구조를 제대로 이해하지 못하는 경우가 많지만, 자동차의 구조에 대한 깊은 이해는 더욱 강력한 효과를 가져올 수도 있습니다

서문

vue3.x 점점 더 많은 뉴스가 나오고 프록시에 대한 토론도 있습니다. Object.defineProperty와 비교했을 때 차이점은 무엇인지, 프록시의 장점은 무엇이며, 어디에 적용할 수 있는지 알아보세요. 이번 글에서는 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 执行一下,似乎能正常运行

JS Proxy의 장점 및 사용 시나리오

但是实际上,Object.defineProperty 问题有以下几个

问题1.删除或者增加对象属性无法监听到

比如增加一个属性 gender ,由于在执行 observer(obj) 的时候,没有这个属性,所以这个无法监听到。删除的属性也是无法监听到

增加属性的时候, vue 需要使用 $set 进行操作,$set 的内部也是使用 Object.defineProperty

Object.defineProperty

JS Proxy의 장점 및 사용 시나리오에 대해 간략하게 소개하겠습니다. proxy에 대해 이야기하기 전에 Object .defineProperty를 살펴보겠습니다. . 우리 모두 알고 있듯이 vue2.x 및 이전 버전에서는 Object.defineProperty를 사용하여 데이터의 양방향 바인딩을 구현합니다. 간단하게 구현해 볼까요

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)
로그인 후 복사

브라우저 콘솔에서 실행해 보면 정상적으로 실행되는 것 같습니다

JS Proxy의 장점 및 사용 시나리오JS Proxy의 장점 및 사용 시나리오

그러나 실제로 Object.defineProperty에는 다음과 같은 문제가 있습니다

문제 1. 개체 속성 삭제 또는 추가를 모니터링할 수 없습니다

Object.defineProperty  劫持对象的属性,如果遍历的对象层级比较深,花的时间比较久,甚至有性能的问题

proxy

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

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

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

<br>
로그인 후 복사

也是一样的效果

JS Proxy의 장점 및 사용 시나리오

而且,能做到 Object.defineProperty 做不到的事情,比如增加一个属性 gender,能够监听到

JS Proxy의 장점 및 사용 시나리오

操作数组,也能监听到

JS Proxy의 장점 및 사용 시나리오

最后敲一下黑板,简单总结一下两者的区别

1.Object.defineProperty 拦截的是对象的属性,会改变原对象。proxy 是拦截整个对象,通过 new 生成一个新对象,不会改变原对象。

2.proxy 的拦截方式,除了上面的 get 和 set ,还有 11 种。选择的方式很多 Proxy,也可以监听一些  Object.defineProperty 监听不到的操作,比如监听数组,监听对象属性的新增,删除等。

proxy 使用场景

关于 proxy 的使用场景,受限于篇幅,这里就简单列举几个,更多的可以移步我的 github 笔记或者 mdn。

看到这里,两者的区别,和 proxy 的优势已经知道个大概了。但是在开发上,有哪些场景可以使用到 proxy 呢,下面列举个可能会遇上的情况

负索引数组

在使用 splice(-1)slice(-1) 等 API 的时候,当输入负数的时候,会定位到数组的最后一项,但是在普通数组上,并不能使用负数。 [1,2,3][-1] 这个代码并不能输出 3 。要让上面的代码输出 3 , 也可以使用 proxy예를 들어 추가 gender 속성이 하나인데, observer(obj) 실행 시 해당 속성이 없어 모니터링할 수 없기 때문입니다. 삭제된 속성은 모니터링할 수 없습니다. 속성을 추가할 때 $set를 사용해야 작동하며, $set도 내부적으로 사용됩니다. >Object.defineProperty가 동작합니다

JS Proxy의 장점 및 사용 시나리오

🎜🎜문제 2. 배열의 변경 사항을 모니터링할 수 없습니다🎜🎜🎜🎜🎜위 그림에서 볼 수 있듯이 실제로는 배열 속성이 성공적으로 수정되었지만, 모니터링이 안되네요🎜🎜질문 3. 객체를 재귀적으로 순회하므로 Object.defineProperty를 사용하여 객체의 속성을 탈취합니다. 순회하는 객체 수준이 상대적으로 깊을 경우 시간이 오래 걸리고 성능 문제가 발생할 수도 있습니다🎜🎜proxy🎜🎜🎜 proxy의 경우 mdn에 대한 설명은 다음과 같습니다. 객체는 기본 작업에 대한 사용자 정의 동작을 정의하는 데 사용됩니다(예: 속성 조회, 할당, 열거(예: 함수 호출 등) 🎜🎜간단히 말하면 대상 객체에 차단 계층을 설정할 수 있습니다. 대상 개체에 대해 어떤 작업이 수행되든 이 차단 계층을 통과해야 합니다🎜🎜proxyObject.defineProperty보다 사용하기 쉽고 훨씬 더 많은 것처럼 들립니다. 실제로는 이렇습니다. 프록시를 사용하여 위 코드를 다시 작성하여 사용해 보겠습니다🎜
let ecValidate = {
    set(target, key, value, receiver) {
        if (key === &#39;age&#39;) { //如果值小于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;
로그인 후 복사
로그인 후 복사
🎜같은 효과🎜🎜JS Proxy의 장점 및 사용 시나리오🎜🎜또한 gender 속성을 ​​추가하고 🎜🎜Object.defineProperty가 할 수 없는 작업을 수행할 수 있습니다. ://img.php.cn/upload/article/000/000/046/8f6814814e0335ec53da5d118522f108-4.png"/>🎜🎜연산 배열도 모니터링 가능🎜🎜JS Proxy의 장점 및 사용 시나리오🎜🎜마지막으로 칠판을 두드리며 간략한 요약 둘의 차이점🎜🎜1.Object.defineProperty은 개체의 속성을 가로채서 원래 개체를 변경합니다. proxy는 전체 객체를 가로채서 원래 객체를 변경하지 않고 new를 통해 새 객체를 생성합니다. 🎜🎜2. 위의 get 및 set 외에도 프록시에 대한 11가지 차단 방법이 있습니다. 배열 모니터링, 객체 속성 추가 및 삭제 모니터링 등 Object.defineProperty가 모니터링할 수 없는 일부 작업을 모니터링할 수도 있습니다. 🎜

🎜프록시 사용 시나리오🎜🎜🎜 프록시의 사용 시나리오와 관련하여 공간 제한으로 인해 다음은 몇 가지입니다. 자세한 내용은 내 github 노트 또는 mdn을 방문하세요. 🎜🎜이것을 보시면 이미 둘의 차이점과 프록시의 장점에 대해 대략적으로 아실 것입니다. 하지만 개발 중에 프록시를 사용할 수 있는 시나리오는 무엇입니까? 다음은 발생할 수 있는 몇 가지 상황입니다🎜

🎜negative Index array🎜

🎜splice(-1), slice(-1) 등의 API를 사용할 때 음수를 입력하면 배열이 위치 지정됩니다. 마지막 항목이지만 일반 배열에서는 음수를 사용할 수 없습니다. [1,2,3][-1] 이 코드는 3 을 출력하지 않습니다. 위의 코드 출력 3을 만들려면 proxy를 사용하여 구현할 수도 있습니다. 🎜
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)
로그인 후 복사
로그인 후 복사
🎜🎜🎜

表单校验

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

let ecValidate = {
    set(target, key, value, receiver) {
        if (key === &#39;age&#39;) { //如果值小于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;
로그인 후 복사
로그인 후 복사

JS Proxy의 장점 및 사용 시나리오

增加附加属性

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

众所周知,身份证号码第一和第二位代表所在省(自治区,直辖市,特别行政区),第三和第四位代表所在市(地级市、自治州、盟及国家直辖市所属市辖区和县的汇总码)。第七至第十四位是出生年月日。低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)
로그인 후 복사
로그인 후 복사

JS Proxy의 장점 및 사용 시나리오

数据格式化

比如有一个需求,需要传时间戳给到后端,但是前端拿到的是一个时间字符串,这个也可以用 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 Proxy의 장점 및 사용 시나리오<br>

推荐教程:《JS教程》    <br>

위 내용은 JS Proxy의 장점 및 사용 시나리오의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Vue 용 버튼에 기능을 추가하는 방법 Vue 용 버튼에 기능을 추가하는 방법 Apr 08, 2025 am 08:51 AM

HTML 템플릿의 버튼을 메소드에 바인딩하여 VUE 버튼에 함수를 추가 할 수 있습니다. 메소드를 정의하고 VUE 인스턴스에서 기능 로직을 작성하십시오.

Vue에서 부트 스트랩을 사용하는 방법 Vue에서 부트 스트랩을 사용하는 방법 Apr 07, 2025 pm 11:33 PM

vue.js에서 bootstrap 사용은 5 단계로 나뉩니다 : Bootstrap 설치. main.js.의 부트 스트랩 가져 오기 부트 스트랩 구성 요소를 템플릿에서 직접 사용하십시오. 선택 사항 : 사용자 정의 스타일. 선택 사항 : 플러그인을 사용하십시오.

Vue에서 시계를 사용하는 방법 Vue에서 시계를 사용하는 방법 Apr 07, 2025 pm 11:36 PM

vue.js의 시계 옵션을 사용하면 개발자가 특정 데이터의 변경 사항을들을 수 있습니다. 데이터가 변경되면 콜백 기능을 트리거하여 업데이트보기 또는 기타 작업을 수행합니다. 구성 옵션에는 즉시 콜백을 실행할지 여부와 DEEP를 지정하는 즉시 포함되며, 이는 객체 또는 어레이에 대한 변경 사항을 재귀 적으로 듣는 지 여부를 지정합니다.

vue.js로 JS 파일을 참조하는 방법 vue.js로 JS 파일을 참조하는 방법 Apr 07, 2025 pm 11:27 PM

vue.js에서 JS 파일을 참조하는 세 가지 방법이 있습니다. & lt; script & gt; 꼬리표;; mounted () 라이프 사이클 후크를 사용한 동적 가져 오기; Vuex State Management Library를 통해 수입.

Vue 다중 페이지 개발은 무엇을 의미합니까? Vue 다중 페이지 개발은 무엇을 의미합니까? Apr 07, 2025 pm 11:57 PM

VUE 멀티 페이지 개발은 vue.js 프레임 워크를 사용하여 응용 프로그램을 구축하는 방법입니다. 여기서 응용 프로그램은 별도의 페이지로 나뉩니다. 코드 유지 보수 : 응용 프로그램을 여러 페이지로 분할하면 코드를보다 쉽게 ​​관리하고 유지 관리 할 수 ​​있습니다. 모듈 식 : 각 페이지는 쉬운 재사용 및 교체를 위해 별도의 모듈로 사용할 수 있습니다. 간단한 라우팅 : 페이지 간의 탐색은 간단한 라우팅 구성을 통해 관리 할 수 ​​있습니다. SEO 최적화 : 각 페이지에는 자체 URL이있어 SEO가 도움이됩니다.

Vue가 이전 페이지로 돌아 오는 방법 Vue가 이전 페이지로 돌아 오는 방법 Apr 07, 2025 pm 11:30 PM

vue.js는 이전 페이지로 돌아갈 수있는 네 가지 방법이 있습니다. $ router.go (-1) $ router.back () 사용 & lt; router-link to = & quot;/quot; Component Window.history.back () 및 메소드 선택은 장면에 따라 다릅니다.

VUE 버전을 쿼리하는 방법 VUE 버전을 쿼리하는 방법 Apr 07, 2025 pm 11:24 PM

Vue DevTools를 사용하여 브라우저 콘솔에서 vue 탭을 보면 VUE 버전을 쿼리 할 수 ​​있습니다. npm을 사용하여 "npm list -g vue"명령을 실행하십시오. package.json 파일의 "종속성"객체에서 vue 항목을 찾으십시오. Vue Cli 프로젝트의 경우 "vue -version"명령을 실행하십시오. & lt; script & gt에서 버전 정보를 확인하십시오. vue 파일을 나타내는 html 파일의 태그.

VUE 기능의 매개 변수를 전달하는 방법 VUE 기능의 매개 변수를 전달하는 방법 Apr 08, 2025 am 07:36 AM

매개 변수를 vue.js 함수로 전달하는 두 가지 주요 방법이 있습니다. 슬롯을 사용하여 데이터를 전달하거나 BAND를 사용하여 함수를 바인딩하고 매개 변수를 제공합니다. 슬롯을 사용하여 매개 변수를 전달합니다 : 구성 요소 템플릿에서 데이터를 전달하고 컴포넌트 내에서 액세스하고 기능의 매개 변수로 사용됩니다. 바인드 바인딩을 사용하여 매개 변수를 전달합니다 : vue.js 인스턴스에서 바인드 함수를 제공하고 기능 매개 변수를 제공합니다.

See all articles