ES6プロキシの分析

1プロキシについて

プロキシ、プロキシは、ES6によって導入された機能です。プロキシを介して、オブジェクトの特定の操作をインターセプトし、カスタマイズされたコードを追加して、これらの操作をより豊富で柔軟にすることができます

文法:

let proxy = new Proxy(target,handle)

Proxyは、プロキシインスタンスを作成するクラスを表し、targetはプロキシされるオブジェクト、handleはインターセプターオブジェクトであり、インターセプターメソッドが含まれます。

2プロキシで一般的に使用されるAPI

  • インターセプト属性の書き込みを設定します
  • インターセプト属性の読み取りを取得
  • deleteProertyインターセプトプロパティの削除
  • オペレーターにインターセプトがあります
  • 取り消し可能なプロキシのキャンセル
    ..。

2.1プロキシAPIの例:set

プロキシには多くのメソッドがあります。例として最も代表的なsetメソッドを次に示します。

プロキシハンドルでは、setは、ターゲットオブジェクトの属性割り当て操作をインターセプトするために使用されます。set
には、プロキシオブジェクトターゲット、属性名キー、属性値値、およびsetメソッドの呼び出し元レシーバーの4つのパラメーターがあります(これは一般的にObjの呼び出しを指しているのと同様に、この受信者は一般にプロキシですが、例外があります。これについては後で説明します。

プロキシの後、オブジェクト属性がプロキシを介して割り当てられると、プロキシ内のセット(存在する場合)が実行されます。それ以外の場合、いいえ、つまり、オブジェクトに直接値を割り当てても、プロキシセットメソッドはトリガーされません。

let person = {
    
    name:'island'}
let proxy = new Proxy(person,{
    
    
    set(target,key,value,receiver){
    
    
        console.log('set run')
        return Reflect.set(target,key,value,receiver)
    }
})
proxy.name = 'proxy set'  // set run
person.name = 'person set' // nothing happen

ターゲットはプロキシオブジェクトである必要があります。受信者は通常、プロキシオブジェクトプロキシですが、実際にはsetメソッドの呼び出し元です。

let person = {
    
    name:'island'}
let proxy = new Proxy(person,{
    
    
    set(target,key,value,receiver){
    
    
        console.log(target === person) // true
        console.log(receiver === proxy ) // true 
    }
})
proxy.name = 'person set'

プロキシが人のプロトタイプに書き込まれている場合、この時点で人の属性が設定されると、jsは人自身からプロトタイプチェーンまでのセットを見つけて実行します。このとき、セットの呼び出し元はペオキシではなく人であり、対応する受信者も変化します。人になるので、受信者はsetメソッドの呼び出し元であり、必ずしもプロキシではありません。

let person = {
    
    };
let proxy = new Proxy({
    
    }, {
    
    
    set(target, prop, value, receiver) {
    
    
        console.log(receiver === person) // true
        console.log(receiver === proxy) // false
    }
});
Object.setPrototypeOf(person, proxy);
person.name = 'island'

注意:

  • setメソッドは、ターゲットのwritable属性(writableがtrue)でのみ機能し、writableがfalseの場合はsetが無効になります。
  • setメソッドでレシーバーに属性を割り当てることはお勧めしません。これにより、setの実行が繰り返しトリガーされ、関数実行スタックオーバーフロー例外がスローされるためです。同じ理由で、getメソッドのレシーバーで属性読み取り操作を実行することはお勧めしません。
let person = {
    
    name:'isand'};
let proxy = new Proxy(person, {
    
    
    set: function (target, prop, value, receiver) {
    
    
        receiver[prop] = value //  Maximum call stack size exceeded

    },
    get(target,key,receiver){
    
    
        receiver[key] //  Maximum call stack size exceeded
    }
});
proxy.name = 'yoke'

3プロキシの適用

独自の豊富で柔軟な特性を備えたプロキシは、多くの開発シナリオで使用でき
、エンジニアリングで使用できます。フロントエンドは、UIとバックグラウンドデータ間のブリッジです。よくあるシナリオは、インターフェイスデータのタイムスタンプをフォーマットして、ユーザー。、またはフォームの入力に対して妥当な検証を実行します。これらはプロキシプロキシを介して実行できます。

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

プロキシを介してプロキシオブジェクトターゲットの属性を変更する場合でも、操作オブジェクトターゲットの属性を直接変更する場合でも、プロキシオブジェクトとターゲットでフィードバックを取得できます。プロキシとターゲットの関係については、いつも戸惑っています。浅いコピーだと思う人もいますが、そうではないと思います。浅いコピーの場合、非参照型のプロパティを変更しても相手の記憶に影響はありません。しかし、事実は明らかにそれに反しています。proxy.stringまたはtarget.stringのどちらを変更しても、相手への影響を確認できるため、両者の関係は浅いコピーではありません。
とりあえず、プロキシとターゲットの関係は同じメモリにアクセスできると思いますが、プロキシ===ターゲット値が偽であるため、割り当て参照ではありません。この質問は当分の間です。将来V8の実装を読むのを待たなければならないかもしれません。さもないと、コミュニティの誰かがV8関連の実装を読んで、それを外の世界と共有することができます。

5ProxyとObject.definePropertyの違い

Object.definePropertyには、プロキシと共通の部分を持つgetメソッドとsetメソッドもあります。Object.definePropertyは、Vue2.0でデータハイジャックと双方向データバインディングに使用されます。ただし、Vue3.0では、この機能をProxyで書き直しました。これにより、ProxyとObject.definePropertyの違いについて全員の議論を呼び起こす必要があります。

意味的に言えば、definePropertyは、プロパティが変更可能かどうか、書き込み可能かどうか、構成可能かどうかなど、プロパティが操作されるときのアクセス許可に焦点を当てています。また、プロキシは、オブジェクトプロパティがトラバースされる前に何を実行する必要があるか、削除する前に何を実行する必要があるかなど、プロパティが操作されるときの動作についてより懸念しています。deleteProerty

詳細に関しては、プロキシはプロパティをより詳細に監視します。属性値を配列として定義します。プロキシの場合、配列の内部要素の変更も聞こえ、セットトラップがトリガーされます。definePropertyのセットは、アドレスを指す属性が変更された場合にのみ実行され、配列の内部要素の変更は検出されません。Vue2.0がプッシュを書き換える必要があるのは、definePropertyのこの機能のためです。アレイプロトタイプ。、スプライスおよびその他の方法

let arrProxy = new Proxy([], {
    
    
    set(target, key, value, receiver) {
    
    
        console.log('run Proxy set')
    }
})

let target = {
    
    }
Object.defineProperty(target,'arr',{
    
    
    set:function(){
    
    
        console.log('run defineProperty set ')
    }
})

arrProxy.push(1) // run Proxy set
target.arr.push(1) // nth happpen

おすすめ

転載: blog.csdn.net/qq_41109610/article/details/114558818
おすすめ