プロキシ オブジェクトについて理解および学習する

hzc
リリース: 2020-06-29 10:39:44
転載
3011 人が閲覧しました

1. Proxy オブジェクトとは正確には何ですか?

Proxy オブジェクトとは正確には何ですか?プロキシとは代理の意味で、プロキシ オブジェクトの機能は、プロキシを通じてプロキシ オブジェクトを作成し、そのプロキシ オブジェクトを操作して、指定したオブジェクトの一部の動作をカスタマイズできるようにすることです。

Proxy(target,handler); Proxy コンストラクターは 2 つのオブジェクトを受け取ります。最初のパラメーターは処理されるオブジェクトで、2 番目のパラメーターはカスタマイズされるメソッドのコレクション (つまり、オブジェクト) です。 。

非常に抽象的ですか?実際、これは js の Object.defineProperty (つまり、vue2.x の最下層を実装するために使用されるアクセサー プロパティ) に非常に似ています。

Object.defineProperty は、特定のプロパティの読み取りおよび書き込み動作を制御できるアクセサー プロパティを定義します。これはプロキシでも実行でき、プロキシはより柔軟で強力です。アクセサー プロパティを使用して多くのことができます。 . 達成できないこと。

たとえば、属性削除イベント (delete obj.prop;)、イベント ('id' in obj;)、apply 呼び出しなどをリッスンします。

まず、プロキシ オブジェクトの内容を見てみましょう。

    var targetObj = {
        id : 1,
        name : 'pxh',
        age : 20,
        school : '小学'
    }
    
    var handler = {};
    
    // 此处,我们先不对targetObj的行为进行干预,所以传个空对象进去即可。
    var proxy = new Proxy(targetObj,handler);
    
    console.log(proxy);
ログイン後にコピー

次に示すように、印刷されたプロキシが何であるかを見てください。

プロキシ オブジェクトについて理解および学習する

ご覧のとおり、プロキシ オブジェクトには Handler 属性、Target 属性、IsRevoked が含まれており、それらの値はそれぞれ、渡したハンドラー、targetObj、false です。

This isRevoked は、取り消し可能かどうかを示します。取り消し可能なプロキシ オブジェクトを生成するには、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 オブジェクトのプロパティ削除動作に介入します
  • #handler.get 介入しますオブジェクトの属性読み取り動作に介入
  • #handler.getOwnProperty オブジェクトの属性の特性値に介入

  • ##handler.has オブジェクトの in 動作に介入 ( obj の prop )

  • handler.isExtensible

  • handler.ownKeys

  • handler.set動作

  • ....
  • 最初に取得動作 (属性読み取り動作) に介入します
    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、name、age 属性の変更は許可されません

        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. 概要

    同様に、プロキシも多くのオブジェクトの動作に介入できるため、ここでは 1 つずつ紹介しません。ご興味がございましたら、MDN ドキュメントをクリックしてください。

    推奨チュートリアル: 「

    WeChat ミニ プログラム

    以上がプロキシ オブジェクトについて理解および学習するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    関連ラベル:
    ソース:jianshu.com
    このウェブサイトの声明
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
    人気のチュートリアル
    詳細>
    最新のダウンロード
    詳細>
    ウェブエフェクト
    公式サイト
    サイト素材
    フロントエンドテンプレート
    私たちについて 免責事項 Sitemap
    PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!