ホームページ  >  記事  >  ウェブフロントエンド  >  ES6 のプロキシとは何ですか?プロキシの詳細分析

ES6 のプロキシとは何ですか?プロキシの詳細分析

不言
不言オリジナル
2018-09-27 16:21:393513ブラウズ

この記事の内容は、ES6 のプロキシとは何ですか? Proxy の詳細な分析は、参考になると思います。

プロキシとは中国語で代理という意味です。この単語は他のプログラミング言語でも同様の意味を持ちます。

それは何ですか

プロキシはコンストラクターです。 js のコンストラクターの典型的な特徴は、最初の文字が大文字であることです。新しい Proxy (元のオブジェクト、{proxy list}) 形式でオブジェクトを作成します。作成されたオブジェクトは、プロキシ オブジェクトと呼ばれます。
つまり:

プロキシ オブジェクト = 新しいプロキシ (元のオブジェクト, {プロキシ リスト})

このような追加のプロキシ オブジェクトが生成される理由は、元のオブジェクトを保持できるためです。新しい関数をプロキシ オブジェクトに追加するか、特定の関数を変更します。元のオブジェクトは、適切な時点でロールバックできます。デザインパターンにおけるエージェントパターンと比較して理解することができます。

使用形式

var obj;
var proxyObj = new Proxy(obj, {
    对obj的操作1: 函数1,
    对obj的操作2: 函数2,
    ...
    
})

入門例

Proxyの基本デモ

var obj = {name:'fan',age:34}
console.info(obj.name)

var proxyObj = new Proxy(obj,{
    get:function(target,key,receiver){console.info(target,key,receiver); return 'no'}
})

console.info(proxyObj.name) 
console.info(proxyObj.abc)

説明は次のとおりです:

  • proxy オブジェクトは、obj オブジェクトに基づいて作成された新しいオブジェクトです。

  • proxyObj.name は、プロキシ オブジェクトの name 属性を取得します。 .オペレーターは自動的に get() メソッド を呼び出します。これは非常に重要です。 js では、オブジェクトは順序付けされていないプロパティのコレクションです。オブジェクトには属性のみがあり、他には何もありません。たとえば、配列オブジェクト arr の sort メソッド: arr.sort() の呼び出しについてはよく話されます。 object (より厳密には) の場合、sort はオブジェクトの属性です (arr.__proto__)。 length 属性と比較すると、sort 属性の属性値は関数なので、この関数を実行するにはその後に () を追加します。 length 属性は数値なので、() を追加せずにそのまま使用できます。もう一度強調しておきますが、 オブジェクトの操作では get が自動的に呼び出されます。もちろん、普段使っているときにはこのことに気づきません。

  • 新しい Proxy の 2 番目のパラメーターでは、get メソッドが明確に設定されています。proxyObj の属性にアクセスすると、ターゲット、キー、レシーバーの値が出力され、何も出力されません。一律に返却されます。したがって、proxyObj.name と proxyObj.abc はどちらも no になります。

これを書いて、元のオブジェクトとプロキシ オブジェクトの間にはどのような関係があると思いますか?なぜ

エージェント と呼ばれるのですか?

エージェントの役割を理解する

エージェント オブジェクトは、スターのエージェントとして理解できます。

外界 <----> 原对象;
外界 <----> 代理对象 <------> 原对象;
要件を改善するための例として上記のコードを取り上げます。誰かが obj の名前を尋ねた場合は、その人に直接伝え、obj の年齢を尋ねた場合は 5 歳下の年齢を返します。

var obj = {name:'fan',age:34}
console.info(obj.age)           // 34
var proxyObj = new Proxy(obj,{
    get:function(target,key,receiver){
        console.info(target === obj);           //true
        console.info(receiver === proxyObj);    //true
        if('age' === key){
            return target[key] - 5;
        }
        else{
            return target[key]
        }
    }
})

console.info(proxyObj.age)  // 34- 5 = 29
説明は次のとおりです:

  • get 関数の 3 つのパラメーター: ターゲット、キー、レシーバー。 target は元のオブジェクト j、keys は現在の属性名、receiver はプロキシ オブジェクトです。 get メソッドでは任意のカスタム処理を実行できます。

プロキシ オブジェクトと元のオブジェクトの関係

var arr = [2,1]
var proxyArr = new Proxy(arr,{} )
proxyArr.push(3);
console.info(arr) // [2,1,3]
console.info(arr === proxyArr) // false
arr.sort();
console.info(proxyArr[0]) // 1

上記のコードでは、このプロキシ オブジェクトは特別な操作を実行しません。有名人のマネージャーは、外界からの情報を有名人自身に伝えるという受動的な仕事をしていると理解されています。したがって、proxyArr で実行される操作は arr に直接影響します。

同様に、arr に対する操作も proxyArr に影響します。

ただし、注意してください: proxyArr と arr は 2 つの異なるオブジェクトです: arr !== proxyArr。

次のように考えられるかもしれません。なぜ proxyArr はプッシュ メソッドを直接使用できるのでしょうか?理由は次のとおりです:

proxyArr.__proto__ === arr.__proto__ === Array.prototype
前の式が真である理由は、新しいプロキシの遺伝子によって決まります。つまり、元のオブジェクトがプロキシされます。

プロキシリスト

新規プロキシの第二引数に設定できるプロキシ属性は以下の通りです。

var proxyObj = new Proxy(obj, {

    get: function(tagert,key,receiver){},
    set: function(tagert,key,receiver){},
    has: function(tagert,key){},
    deleteProperty: function(tagert,key){},
    ownKeys: function(tagert){},
    getOwnPropertyDescriptor: function(tagert,key){},
    defineProperty: function(tagert,key,desc){},
    preventExtensions: function(tagert){},
    getPrototypeOf: function(tagert){},
    isExtensible: function(tagert){},
    setPrototypeof: function(tagert,proto){},
    apply: function(tagert,obj,args){},
    construct: function(tagert,args){},
    
})
get() プロキシの適用

配列の添え字に負の値を許可する

#js では、有効な配列テーブルは 0 から始まります。

var arr = [1,2,3];
console.info(arr[0])  // 1
console.info(arr[-1]) // undefined
console.info(arr[100]) // undefined

次のテーブルが範囲外である場合、または負の値がある場合、得られる結果はエラーではなく未定義であることに注意してください。

以下の表に示すように、配列が負の値を取ることができることを期待します。ルールは次のとおりです。

    -n は、からの n 番目の要素を表します。最後。例: -1 は最後の要素から最初の要素を意味します。
  • プロキシを使用して、次のように問題を解決します。
var arr = [1,2,3];

var proxyArr = new Proxy(arr,{
    get: (target,prop)=>{
        let index = Number(prop);
        if(index < 0){
            prop = target.length + index;
        }
        return target[prop];
        
    }
})
console.info(arr[-1]);      // undefined
console.info(proxyArr[-1]); // 3

注:

    Number() は受信値を変換できます。数値型に変換します。数値以外の値 --> NaN;
  • proxyArr.push(3)の場合、この時のpropは'push'なのでif分岐に入りません。 。
  • proxyArr[-1] の場合、この時点の prop は '-1' なので、if 分岐に入ります: prop を -1 から 2 に変更します。代理店の効果を達成します。
  • この時点で、proxyArr を配列として使用でき、sort や Push などのメソッドを呼び出すことができます。 Array.isArray(proxyArr) === true
  • もちろん、これをさらにファクトリ関数にカプセル化することもできます。
function myArr(...args){
    var arr = new Array(...args);

    var proxyArr = new Proxy(arr,{
        get: (target,key)=>{
            let index = Number(key);
            if(index < 0){
                key = target.length + index;
            }
            return target[key];

        }
    })
    return proxyArr;
}
var obj = myArr([1,2,3]);
console.info(obj[0],obj[-1])

チェーン操作

var double = n => n*2;
var pow2 = n => n*n;
var half = n => n/ 2;
var add1 = n => n+1;

function pipe (num){
    let funs = []
    let obj = new Proxy({},{
        get:function(target,prop){
            if(prop === 'end'){
                return funs.reduce((val,currentfn)=>currentfn(val),num);
            }else{
                funs.push(window[prop])
            }
            return obj;
        }
    })

    return obj;
};

console.info( pipe(4).double.pow2.end);
console.info( pipe(4).pow.double.pow2.add1.end);

以上がES6 のプロキシとは何ですか?プロキシの詳細分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。