Proxy 객체에 대한 이해와 학습

hzc
풀어 주다: 2020-06-29 10:39:44
앞으로
3011명이 탐색했습니다.

1. 프록시 객체란 정확히 무엇인가요?

프록시 객체란 정확히 무엇인가요? 프록시는 프록시를 의미합니다. 프록시 개체의 기능은 프록시를 통해 프록시 개체를 만든 다음 프록시 개체를 작동하여 지정된 개체의 일부 동작을 사용자 정의할 수 있도록 하는 것입니다.

Proxy(target,handler); 프록시 생성자는 2개의 객체를 받습니다. 첫 번째 매개변수는 처리할 객체이고, 두 번째 매개변수는 사용자 정의할 메서드 모음(즉, 객체)입니다.

매우 추상적인가요? 실제로 js의 Object.defineProperty(즉, vue2.x의 하위 레이어를 구현하는 데 사용되는 accessor 속성)와 매우 유사합니다.

Object.defineProperty는 특정 속성의 읽기 및 쓰기 동작을 제어할 수 있는 접근자 속성을 정의하며, 프록시에서는 접근자 속성이 수행할 수 없는 많은 작업을 수행할 수 있습니다.

예를 들어 속성 ​​삭제 이벤트(obj.prop; 삭제), 이벤트(obj;의 'id'), 호출 적용 등을 수신합니다.

먼저 프록시 객체에 무엇이 포함되어 있는지 살펴보겠습니다.

    var targetObj = {
        id : 1,
        name : 'pxh',
        age : 20,
        school : '小学'
    }
    
    var handler = {};
    
    // 此处,我们先不对targetObj的行为进行干预,所以传个空对象进去即可。
    var proxy = new Proxy(targetObj,handler);
    
    console.log(proxy);
로그인 후 복사

아래 그림과 같이 인쇄된 프록시가 무엇인지 살펴보세요.

Proxy 객체에 대한 이해와 학습

프록시 객체에 Handler 속성, Target 속성 및 IsRevoked가 포함되어 있음을 확인할 수 있습니다. 해당 값은 각각 우리가 전달한 핸들러인 targetObj 및 false입니다.

Revoked는 취소 가능한지 여부를 나타냅니다. Proxy.revocable() 메서드를 사용하여 취소 가능한 프록시 객체를 생성하세요. 자세한 내용은 MDN으로 이동하여 설명서를 참조하세요.

2. 프록시 객체를 통해 원본 객체 조작

위에서 프록시 객체를 생성했는데, 이제 프록시 객체를 조작하여 원본 객체를 조작해 보겠습니다. (실제로 프록시 개체는 내부적으로 매핑됩니다.)

    var targetObj = {
        id : 1,
        name : 'pxh',
        age : 20,
        school : '小学'
    }
    
    var handler = {};
    
    // 此处,我们先不对targetObj的行为进行干预,所以传个空对象进去即可。
    var proxy = new Proxy(targetObj,handler);
    
    
    /**
     * 1、读取及修改属性,可以看到原来的对象的属性也被修改了
     */
    console.log(proxy.age);  // 20
    console.log(targetObj.age); // 20
    proxy.age = 22;
    console.log(proxy.age);  // 22
    console.log(targetObj.age); // 22
    
    /**
     * 2、删除proxy对象的属性,影响原来的对象的属性
     */
    console.log(proxy.school);  // 小学
    console.log(targetObj.school); // 小学
    delete proxy.age;
    console.log(proxy.school);  // undefined
    console.log(targetObj.school); // undefined
로그인 후 복사

3. 메서드 설정 및 메서드 가져오기

자, 이제 원본 개체의 동작을 간섭하기 시작할 수 있습니다. 구체적으로 동작에 개입하려는 목적을 달성합니다. 다음 메소드를 구현하여 객체를 생성합니다.

  • handler.apply

  • handler.construct 생성자의 새로운 동작에 개입

  • handler.defineProperty 객체의 데이터 속성 또는 접근자 속성 정의에 개입

  • handler.deleteProperty 개입 객체의 속성 삭제 동작 G 개입 객체의 속성 읽기 동작

  • handler.Getownproperty 개입 객체

  • handler.has 개입 객체(obj의 prop)

  • 속성의 속성 특성 값 handler .isExtensible

  • handler.ownKeys

  • handler.set 객체의 속성 설정 동작에 개입

  • ...

  • 먼저 get 동작(속성 읽기 동작)에 개입
  •     var targetObj = {
            id : 1,
            name : 'pxh',
            age : 20,
            school : '小学'
        }
        
        
        var handler = {
            // 定义get方法,get方法可以接收2个参数,分别是原来的对象及属性
            get : function(target,prop){
                console.log(`${prop}属性正在被查看`);
                console.log(targetObj == target); // true
                return target[prop];
            }
        };
        
        var proxy = new Proxy(targetObj,handler);
        
        console.log(proxy.id);
        
        /**
         * 可以看到,打印顺序为:
         *  id属性正在被查看
         *  true
         *  1
         */
    로그인 후 복사
  • 다음 , 일부를 넣으면 속성이 "비공개"가 됩니다. 예를 들어 id 속성을 읽을 수 없습니다

set 메서드를 정의하고 id, 이름, 나이 속성을 수정할 수 없습니다

    var targetObj = {
        id : 1,
        name : 'pxh',
        age : 20,
        school : '小学'
    }
    
    
    var handler = {
        // 定义get方法,get方法可以接收2个参数,分别是原来的对象及属性
        get : function(target,prop){
            if(prop == 'id'){
                return undefined;
            }
            return target[prop];
        },
        // 定义set方法,set方法比get多1个参数,那就是该属性修改时的值
        set : function(target,prop,value){
            if(prop == 'id' || prop == 'name' || prop == 'age'){
                console.log(`不允许修改${prop}属性`)
            }else{
                target[prop] = value;
            }
        }
    };
    
    var proxy = new Proxy(targetObj,handler);
    
    /**
     * 修改属性,分别打印
     * 不允许修改id属性
     * 不允许修改name属性
     * 不允许修改age属性
     */
    proxy.id = 2; 
    proxy.name = 'pxh222';
    proxy.age = 23;
    
    proxy.school = '中学'; // 这个无打印
    
    /**
     * 读取属性,可以看到分别打印
     * undefined
     * pxh
     * 20
     * 中学  // 这个没有拦截,因此可以修改
     */
    console.log(proxy.id);
    console.log(proxy.name);
    console.log(proxy.age);
    console.log(proxy.school);
로그인 후 복사

4. 삭제 동작에서 (obj.prop 문 삭제에 유효)

동일하게 객체 속성 삭제 동작에 개입하여 id, name, age 속성 삭제를 허용하지 않습니다.

    var targetObj = {
        id : 1,
        name : 'pxh',
        age : 20,
        school : '小学'
    }
    
    var handler = {
        // 在handler中定义get方法,get方法可以接收2个参数,分别是原来的对象及属性
        get : function(target,prop){
            if(prop == 'id'){
                return undefined;
            }
            return target[prop];
        },
        // set方法比get多1个参数,那就是该属性修改时的值
        set : function(target,prop,value){
            if(prop == 'id' || prop == 'name' || prop == 'age'){
                console.log(`不允许修改${prop}属性`)
            }else{
                target[prop] = value;
            }
        },
        /**
         * 这个方法要求返回个boolean值,表示是否删除成功
         * 如果返回的值不是boolean值,则会进行类型转换成boolean值再返回
         */
        deleteProperty : function(target,prop){
            if(prop == 'id' || prop == 'name' || prop == 'age'){
                console.log(`不允许删除${prop}属性`);
                return false;
            }else{
                delete target[prop];
                return true;
            }
        }
    };
    
    var proxy = new Proxy(targetObj,handler);
    /**
     * 尝试删除id属性,可以看到打印顺序为:
     * 不允许删除id属性
     * false
     */
    console.log(delete proxy.id);
    
    /**
     * 删除school属性,可以看到打印
     * true
     * undefined
     */
    console.log(delete proxy.school);
    console.log(proxy.school);
로그인 후 복사

5. obj 동작의 prop에 개입합니다(객체에 특정 속성이 있는지 확인)

위에서는 객체의 id 값을 얻을 수 없으며, 이제 이를 숨기거나 수정할 수 없습니다. .

    var targetObj = {
        id : 1,
        name : 'pxh',
        age : 20,
        school : '小学'
    }
    
    var handler = {
        // 在handler中定义get方法,get方法可以接收2个参数,分别是原来的对象及属性
        get : function(target,prop){
            if(prop == 'id'){
                return undefined;
            }
            return target[prop];
        },
        // set方法比get多1个参数,那就是该属性修改时的值
        set : function(target,prop,value){
            if(prop == 'id' || prop == 'name' || prop == 'age'){
                console.log(`不允许修改${prop}属性`)
            }else{
                target[prop] = value;
            }
        },
        /**
         * 这个方法要求返回个boolean值,表示是否删除成功
         * 如果返回的值不是boolean值,则会进行类型转换成boolean值再返回
         */
        deleteProperty : function(target,prop){
            if(prop == 'id' || prop == 'name' || prop == 'age'){
                console.log(`不允许删除${prop}属性`);
                return false;
            }else{
                delete target[prop];
                return true;
            }
        },
        /**
         * 通过has 方法来控制,返回值也是个boolean,表示对象是否拥有某个属性
         * 如果返回的值不是boolean值,则会进行类型转换成boolean值再返回
         */
        has : function(target,prop){
            if(prop == 'id'){
                return false
            }else{
                return prop in target;
            }
        }
    };
    
    var proxy = new Proxy(targetObj,handler);
    console.log('id' in proxy); // false
    console.log('name' in proxy); // true
로그인 후 복사

6. 요약

마찬가지로 프록시도 여러 가지 방법으로 개체의 동작을 방해할 수 있으므로 여기서는 하나씩 소개하지 않겠습니다. 관심이 있으시면 MDN 문서

추천 튜토리얼: "

WeChat Mini Program

"

을 클릭하세요.

위 내용은 Proxy 객체에 대한 이해와 학습의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:jianshu.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!