1. 反射とは何ですか?リフレクションの概念は、 オブジェクト指向プログラミングでは、通常、最初にクラスとメソッドが定義され、次に次の例のように、メソッドを明示的に呼び出すためのオブジェクトが作成されます。 パブリッククラスUser{ プライベート文字列名; プライベート日付誕生日; //.... パブリック int 誕生日による年齢計算(){ // ..... } } // ユーザーを呼び出す u = new User("jack", new Date()); 誕生日による年齢を計算します。 上記の呼び出し方法はよく知られています。ただし、抽象フレームワーク (フレームワークはビジネス定義クラスと相互運用する必要があります) を作成する場合、ビジネス クラスのメンバーとメソッドがわからないため、リフレクションを使用してメンバー変数を動的に取得したり、メソッドを呼び出したりします。 次の例では、リフレクションを使用して json を Java オブジェクトに変換します。 パブリック静的クラス User { プライベート文字列名; パブリック文字列getName() { 名前を返します。 } パブリック void setName(文字列名) { this.name = 名前; } } // リフレクションを使用してオブジェクト セッター メソッドを呼び出します。 パブリック静的 <T> T fill(Class<T> userClass, Map<String, Object> json) 例外をスローします { フィールド[] fields = userClass.getDeclaredFields(); T ユーザー = userClass.newInstance(); for (フィールド フィールド: フィールド) { // 最初の文字を大文字にします String name = field.getName(); char[] arr = name.toCharArray(); arr[0] = Character.toUpperCase(arr[0]); System.out.println(新しいString(arr)); メソッド method = userClass.getDeclaredMethod("set" + new String(arr), field.getType()); オブジェクトの戻り値 = method.invoke(user, json.get(name)); } ユーザーを返します。 } 2. JavaScriptで反映する
2.1 Reflect.get(ターゲット、名前、受信者) 定数オブジェクト = { 名前: 'ジャック', 年齢: 12歳 ユーザー情報を取得する() { this.name + 'age is ' + this.age を返します。 } } Reflect.get(obj, 'name') // ジャック Reflect.get(obj, '年齢') // 12 Reflect.get(obj, 'userInfo') // ジャックの年齢は12歳です // レシーバー パラメーターが渡された場合、userInfo() 関数が呼び出されると、レシーバー オブジェクトが参照されます。 定数レシーバーオブジェクト = { 名前: 'シャオミン'、 年齢: 22 }; Reflect.get(obj, 'userInfo', receivedObj) // Xiaoming の年齢は 22 歳です 2.2 Reflect.set(ターゲット、名前、値、レシーバー)定数オブジェクト = { 名前: 'ジャック', 年齢: 12歳 updateAge(値)を設定する{ this.age = value を返します。 }, } Reflect.set(obj, '年齢', 22); オブジェクト年齢 // 22 // レシーバー パラメーターが渡された場合、updateAge() 関数が呼び出されると、レシーバー オブジェクトが参照されます。 定数レシーバーオブジェクト = { 年齢: 0 }; Reflect.set(obj, 'updateAge', 10, レシーバーObj) // オブジェクト年齢 // 22 レシーバーオブジェクト.年齢 // 10 2.3 Reflect.has(obj, name) 定数オブジェクト = { 名前: 'ジャック', } 名前内のオブジェクト // true Reflect.has(obj, 'name') // 真 2.4 Reflect.deleteProperty(obj, name) 定数オブジェクト = { 名前: 'ジャック', } オブジェクト名を削除 Reflect.deleteProperty(obj, 'name') 2.5 Reflect.construct(ターゲット、引数) 関数 User(名前){ this.name = 名前; } const user = 新しい User('jack'); Reflect.construct(ユーザー、['jack']); Reflect.getPrototypeOf(obj) Reflect.getPrototypeOf メソッドは、オブジェクトの __proto__ プロパティを読み取るために使用されます。 2.6 Reflect.setPrototypeOf(obj, newProto) 定数オブジェクト = { 名前: 'ジャック', } Reflect.setPrototypeOf(obj, Array.prototype); オブジェクトの長さ // 0 2.7 Reflect.apply(func, thisArg, args) 定数数値 = [1,2,3,4,5]; Math.max.apply(Math, nums) の最小値と最大値を適用します。 // Reflect.apply 経由で呼び出されます const min = Reflect.apply(Math.min, Math, nums); 2.8 Reflect.defineProperty(ターゲット、プロパティキー、属性) 定数obj = {}; Object.defineProperty(obj, 'プロパティ', { 値: 0, 書き込み可能: false }); Reflect.defineProperty(obj, 'プロパティ', { 値: 0, 書き込み可能: false }); 2.9 Reflect.getOwnPropertyDescriptor(ターゲット、プロパティキー)
2.10 Reflect.isExtensible (ターゲット)
2.11 Reflect.preventExtensions(ターゲット)
2.13 Reflect.ownKeys (ターゲット) 定数オブジェクト = { 名前: 'ジャック', 年齢: 12歳 ユーザー情報を取得する() { this.name + 'age is ' + this.age を返します。 } } オブジェクト.getOwnPropertyNames(obj) Reflect.ownKeys(obj) // ['name', 'age', 'userInfo'] 3. JavaScript のプロキシプロキシはプログラミングに非常に役立ちます。プロキシを使用すると、ターゲット オブジェクトの前に「インターセプション」レイヤーを追加して、共通のロジックを実装できます。 プロキシコンストラクター
const ユーザー = {名前: 'hello'} const proxy = 新しいProxy(user, { get: function(target, property) { // プロパティの読み取り時にトリガーされます return 'hi'; } }); proxy.name // 'こんにちは' 3.1 プロキシでサポートされる傍受操作
3.2 取得()これは、特定の属性の読み取り操作をインターセプトするために使用されます。ターゲット オブジェクト、属性名、 定数ユーザー = { 名前: 'ジャック' } // 属性が存在する場合にのみ値を返し、存在しない場合は例外をスローします。 const proxy = 新しいProxy(user, { 取得: 関数(ターゲット、プロパティ) { if (!(ターゲット内のプロパティ)) { 新しい ReferenceError をスローします (`${property} は存在しません。`); } ターゲット[プロパティ]を返します。 } }); proxy.name // ジャック proxy.age // ReferenceError: age が存在しません。 いくつかの共通プロキシ オブジェクトを定義し、子オブジェクトにそれらを継承させることができます。 // 属性が存在する場合にのみ値を返し、存在しない場合は例外をスローします。 const proxy = 新しいプロキシ({}, { 取得: 関数(ターゲット、プロパティ) { if (!(ターゲット内のプロパティ)) { 新しい ReferenceError をスローします (`${property} は存在しません。`); } ターゲット[プロパティ]を返します。 } }); obj = Object.create(プロキシ); obj.name = 'こんにちは' obj.name // こんにちは obj.age // ReferenceError: age が存在しません。 3.3 設定()これは、特定の属性の割り当て操作をインターセプトするために使用されます。ターゲット オブジェクト、属性名、属性値、および // 文字タイプ属性の長さチェック let sizeValidator = { 設定: 関数(ターゲット、プロパティ、値、レシーバー) { if (typeof value == 'string' && value.length > 5) { throw new RangeError('5文字を超えることはできません。'); } ターゲット[プロパティ] = 値; true を返します。 } }; const バリデーター = 新しいプロキシー({}、sizeValidator); obj = Object.create(validator); を作成します。 obj.name = '123456' // RangeError: 5 文字を超えることはできません。 obj.age = 12 // 12 3.4 は() ターゲット オブジェクトとクエリする属性名の 2 つのパラメータを受け入れます。 定数ハンドラ = { (ターゲット、キー) { キー[0] === '_'の場合{ false を返します。 } ターゲットのキーを返します。 } }; var target = { _prop: 'foo', prop: 'foo' }; var proxy = 新しい Proxy(ターゲット、ハンドラー); プロキシ内の '_prop' // false 3.5 プロパティの定義()
3.6 プロパティの削除()
3.7 getOwnPropertyDescriptor()
3.8 getPrototypeOf()主にオブジェクトのプロトタイプを傍受して取得するために使用されます。傍受操作は次のとおりです。
定数obj = {}; const プロトコル = {}; 定数ハンドラ = { getPrototypeOf(ターゲット) { console.log(target === obj); // 真 console.log(this === ハンドラー); // true proto を返します。 } }; const p = 新しいプロキシ(obj、ハンドラ); console.log(Object.getPrototypeOf(p) === proto); // 真 3.9 プロトタイプの設定()主に const ハンドラReturnsFalse = { setPrototypeOf(ターゲット、新しいProto) { false を返します。 } }; const newProto = {}、ターゲット = {}; const p1 = 新しいプロキシ(ターゲット、ハンドラーはFalseを返します); Object.setPrototypeOf(p1, newProto); // TypeError をスローします Reflect.setPrototypeOf(p1, newProto); // false を返す 3.10 拡張可能()メソッドは Object.isExtensible() 操作をインターセプトします。 const p = 新しいプロキシ({}, { isExtensible: 関数(ターゲット) { console.log('呼び出されました'); return true; //true の値を表すために return 1; などを使用することもできます} }); console.log(Object.isExtensible(p)); // "呼び出されました" // 真実 3.11 所有キー()オブジェクト自身の属性の読み取り操作をインターセプトするために使用されます。具体的には、以下の操作が傍受されます。
const p = 新しいプロキシ({}, { 所有キー: 関数(ターゲット) { console.log('呼び出されました'); ['a', 'b', 'c'] を返します。 } }); console.log(Object.getOwnPropertyNames(p)); // "呼び出されました" 3.12 拡張機能の防止() このメソッドには制限があります。proxy.preventExtensions const p = 新しいプロキシ({}, { 拡張機能を防止: 関数(ターゲット) { console.log('呼び出されました'); オブジェクト.preventExtensions(ターゲット); true を返します。 } }); console.log(Object.preventExtensions(p)); // "呼び出されました" // 間違い 3.13 適用()apply メソッドは次の操作をインターセプトします。
ターゲット オブジェクト、ターゲット オブジェクトのコンテキスト オブジェクト (this)、およびターゲット オブジェクトのパラメーター配列の 3 つのパラメーターを受け入れます。 定数ハンドラ = { 適用 (ターゲット、ctx、引数) { Reflect.apply(...引数) を返します。 } }; 例: 定数ターゲット = 関数 () { }; 定数ハンドラ = { 適用: 関数 (ターゲット、thisArg、argumentsList) { console.log('呼び出されました: ' + argumentsList.join(', ')); 引数リスト[0] + 引数リスト[1] + 引数リスト[2]を返します。 } }; const p = 新しいプロキシ(ターゲット、ハンドラー); p(1,2,3) // "呼び出された: 1, 2, 3" 6 3.14 コンストラクト() 定数ハンドラ = { 構築 (ターゲット、引数、新しいターゲット) { 新しいターゲット(...args)を返します。 } }; このメソッドは 3 つのパラメータを受け入れます。
注意:メソッドはオブジェクトを返す必要があり、ターゲット オブジェクトは関数である必要があります。そうでない場合はエラーが報告されます。 const p = 新しいプロキシ(関数() {}, { 構成: function(target, argumentsList) { 0を返します。 } }); new p() // 戻り値がオブジェクトではないため、エラーが報告されます const p = new Proxy({}, { 構成: function(target, argumentsList) { 戻る {}; } }); new p() // 対象オブジェクトは関数ではないのでエラー 4. オブザーバーパターンオブザーバーは非常に一般的なパターンであり、オブジェクトの状態が変化すると、それに依存するすべてのオブジェクトに通知され、自動的に更新されるものとして定義されます。 監視対象オブジェクトの状態が変化したときに監視関数が自動的に実行される例を オブザーバー関数は、観測対象をラップし、観測機能を追加します。
const queuedObservers = 新しい Set(); const observe = fn => queuedObservers.add(fn); const observable = obj => new Proxy(obj, {set}); // プロパティが変更されたときに自動的に監視関数を実行します。 関数set(ターゲット、キー、値、レシーバー) { const result = Reflect.set(ターゲット、キー、値、レシーバー); キューに入れられたオブザーバー。各オブザーバーをそれぞれ処理します。 結果を返します。 } 例: const ユーザー = 観測可能({ 名前: 'ジャック', 年齢: 20 }); 関数userInfo() { console.log(`${user.name}, ${user.age}`) } 観察(ユーザー情報); user.name = 'Xiaoming'; // Xiaoming、20歳 これで、フロントエンド 以下もご興味があるかもしれません:
|
弊社のネットワーク管理センターは管理センター兼サーバーとして機能します!各管理対象デバイスは、TCP...
構造(位置)擬似クラスセレクタ(CSS3) :first-child : 指定されたセレクタは、親要...
tcpdump は、ネットワークの問題のトラブルシューティングに効果的に役立つ、柔軟で強力なパケット...
展開環境: ここでは docker コンテナ、Linux システム、VmWare 仮想マシンが使用さ...
この記事の例では、衝突検出を実装するためのjsの具体的なコードを参考までに共有しています。具体的な内...
目次1. コンポーネントの登録2. コンポーネントの使用3. 父から息子へ4. 息子から父へ5. ス...
今日は、タブ バーをクリックして切り替えるという目的を実現するために、js と jQuery を使用...
最近、新しいプロジェクトでは springcloud と docker が使用されています。この 2...
以下の例では、名前が入っている td の幅が 60px のとき、2 行目の文字数が少ない場合は正常に...
エンコーディングの理由により、Linux サーバーに中国語のファイルやディレクトリをアップロードまた...
Docker コンテナのタイムゾーンがホストマシンと一致しているかどうかを確認するにはどうすればよい...
私たちの生活、仕事、勉強において、ソーシャル ネットワークは徐々に将来のインターネット発展のトレンド...
アプリケーション ソフトウェアには通常、次のようなビジネス要件があります。新しいバージョンの APP...
1. InnoDBのロック機構InnoDB ストレージ エンジンは、行レベルのロックとトランザクショ...
テーブルを美しくするために、セルごとに異なる境界線の色を設定できます。基本的な構文<TD 境界...