ES6 でのdefineProperty と proxy の詳細な紹介 (コード例)
この記事では、ES6 の defineProperty と proxy について詳しく説明します (コード例)。必要な方は参考にしていただければ幸いです。
「データ バインディング」という言葉は多かれ少なかれ聞いたことがあるでしょう。「データ バインディング」の鍵はデータの変更を監視することですが、このようなオブジェクトの場合は次のようになります。 }、obj が変更されたことはどうやってわかるのでしょうか?
構文
Object.defineProperty(obj, prop, descriptor)
パラメータ
obj: 要在其上定义属性的对象。 prop: 要定义或修改的属性的名称。 descriptor: 将被定义或修改的属性的描述符。例:
var obj = {}; Object.defineProperty(obj, "num", { value : 1, writable : true, enumerable : true, configurable : true }); // 对象 obj 拥有属性 num,值为 1ただし、直接追加することもできます。プロパティと値ですが、この方法でさらに多くの構成を行うことができます。 関数の 3 番目のパラメーター記述子によって表される属性記述子には、
データ記述子とアクセス記述子の 2 つの形式があります。
どちらにも次の 2 つのキー値があります :
configurable
属性の構成可能値が true の場合に限り、プロパティ記述子は変更または削除できます。デフォルトは false です。enumerable
プロパティの列挙可能性が true の場合に限り、プロパティはオブジェクトの列挙プロパティに表示されます。デフォルトは false です。データ記述子には、次のオプションのキー値もあります:
value
これに対応する値属性 。任意の有効な JavaScript 値 (数値、オブジェクト、関数など) を指定できます。デフォルトは未定義です。writable
プロパティの writable が true である場合に限り、プロパティは代入演算子によって変更できます。デフォルトは false です。アクセス記述子には、次のオプションのキー値もあります:
get
属性に指定される 1 つgetter メソッドは、getter が存在しない場合は未定義です。このメソッドの戻り値が属性値として使用されます。デフォルトは未定義です。set
属性記述子は、データ記述子またはアクセス記述子の 2 つの形式のいずれかである必要があり、同時に両方を指定することはできません。 これは、次のことができることを意味します:
Object.defineProperty({}, "num", { value: 1, writable: true, enumerable: true, configurable: true });次のこともできます:
var value = 1; Object.defineProperty({}, "num", { get : function(){ return value; }, set : function(newValue){ value = newValue; }, enumerable : true, configurable : true });ただし、次のことはできません:
// 报错 Object.defineProperty({}, "num", { value: 1, get: function() { return 1; } });さらに、すべての属性記述子はオプションですが、記述子はフィールドは必須です。設定を何も実行しない場合は、次のようにすることができます:
var obj = Object.defineProperty({}, "num", {}); console.log(obj.num); // undefinedSetters と GettersdefineProperty について説明する理由は、アクセス記述子を使用したいためです。 get と set、これら 2 つのメソッドはゲッターおよびセッターとも呼ばれます。ゲッターとセッターによって定義されたプロパティは「アクセサー プロパティ」と呼ばれます。 プログラムがアクセサー プロパティの値をクエリするとき、JavaScript はゲッター メソッドを呼び出します。このメソッドの戻り値は、属性アクセス式の値です。プログラムがアクセサー プロパティの値を設定すると、JavaScript は setter メソッドを呼び出し、代入式の右側の値をパラメーターとして setter に渡します。ある意味、このメソッドはプロパティ値を「設定」する役割を果たします。 setterメソッドの戻り値は無視して構いません。 例:
var obj = {}, value = null; Object.defineProperty(obj, "num", { get: function(){ console.log('执行了 get 操作') return value; }, set: function(newValue) { console.log('执行了 set 操作') value = newValue; } }) obj.value = 1 // 执行了 set 操作 console.log(obj.value); // 执行了 get 操作 // 1これはデータの変更を監視したい方法ではないでしょうか?もう一度カプセル化しましょう:
function Archiver() { var value = null; // archive n. 档案 var archive = []; Object.defineProperty(this, 'num', { get: function() { console.log('执行了 get 操作') return value; }, set: function(value) { console.log('执行了 set 操作') value = value; archive.push({ val: value }); } }); this.getArchive = function() { return archive; }; } var arc = new Archiver(); arc.num; // 执行了 get 操作 arc.num = 11; // 执行了 set 操作 arc.num = 13; // 执行了 set 操作 console.log(arc.getArchive()); // [{ val: 11 }, { val: 13 }]watch APIデータの変更を監視できるので、データが変更されるとレンダリング作業が自動的に実行されることが想像できます。例: HTML には、span タグと button タグがあります。
<span>1</span> <button>点击加 1</button>ボタンがクリックされると、span タグの値が 1 増加します。 従来のアプローチは次のとおりです:
document.getElementById('button').addEventListener("click", function(){ var container = document.getElementById("container"); container.innerHTML = Number(container.innerHTML) + 1; });defineProperty を使用する場合:
var obj = { value: 1 } // 储存 obj.value 的值 var value = 1; Object.defineProperty(obj, "value", { get: function() { return value; }, set: function(newValue) { value = newValue; document.getElementById('container').innerHTML = newValue; } }); document.getElementById('button').addEventListener("click", function() { obj.value += 1; });コードは増加するように見えますが、span タグの値を直接変更する必要がある場合は、 obj.value の値を変更するだけです。 ただし、現在の書き方では、obj.value の値を格納する別の変数を宣言する必要があります。これは、セット内で
obj.value = newValue を直接実行する場合があるためです。 、無限ループに陥ってしまいます。さらに、多くの属性値の変更を監視する必要がある場合があります。それらを 1 つずつ記述するのは面倒なので、単純に監視関数を記述します。使用の効果は次のとおりです:
var obj = { value: 1 } watch(obj, "num", function(newvalue){ document.getElementById('container').innerHTML = newvalue; }) document.getElementById('button').addEventListener("click", function(){ obj.value += 1 });この監視関数を作成しましょう:
(function(){ var root = this; function watch(obj, name, func){ var value = obj[name]; Object.defineProperty(obj, name, { get: function() { return value; }, set: function(newValue) { value = newValue; func(value) } }); if (value) obj[name] = value } this.watch = watch; })()これで、オブジェクトの属性値の変化を監視し、属性値の変化に基づいてコールバック関数を追加できるようになりました。素晴らしい ~proxydefineProperty を使用すると、プロパティの読み取り (get) と設定 (set) の動作のみを再定義できます。ES6 では、Proxy が提供され、さらに多くの動作を再定義できます。たとえば、削除、関数呼び出しなどの動作です。
Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。我们来看看它的语法:
var proxy = new Proxy(target, handler);
proxy 对象的所有用法,都是上面这种形式,不同的只是handler参数的写法。其中,new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。
var proxy = new Proxy({}, { get: function(obj, prop) { console.log('设置 get 操作') return obj[prop]; }, set: function(obj, prop, value) { console.log('设置 set 操作') obj[prop] = value; } }); proxy.time = 35; // 设置 set 操作 console.log(proxy.time); // 设置 get 操作 // 35
除了 get 和 set 之外,proxy 可以拦截多达 13 种操作,比如 has(target, propKey),可以拦截 propKey in proxy 的操作,返回一个布尔值。
// 使用 has 方法隐藏某些属性,不被 in 运算符发现 var handler = { has (target, key) { if (key[0] === '_') { return false; } return key in target; } }; var target = { _prop: 'foo', prop: 'foo' }; var proxy = new Proxy(target, handler); console.log('_prop' in proxy); // false
又比如说 apply 方法拦截函数的调用、call 和 apply 操作。
apply 方法可以接受三个参数,分别是目标对象、目标对象的上下文对象(this)和目标对象的参数数组,不过这里我们简单演示一下:
var target = function () { return 'I am the target'; }; var handler = { apply: function () { return 'I am the proxy'; } }; var p = new Proxy(target, handler); p(); // "I am the proxy"
又比如说 ownKeys 方法可以拦截对象自身属性的读取操作。具体来说,拦截以下操作:
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
下面的例子是拦截第一个字符为下划线的属性名,不让它被 for of 遍历到。
let target = { _bar: 'foo', _prop: 'bar', prop: 'baz' }; let handler = { ownKeys (target) { return Reflect.ownKeys(target).filter(key => key[0] !== '_'); } }; let proxy = new Proxy(target, handler); for (let key of Object.keys(proxy)) { console.log(target[key]); } // "baz"
更多的拦截行为可以查看阮一峰老师的 《ECMAScript 6 入门》
值得注意的是,proxy 的最大问题在于浏览器支持度不够,而且很多效果无法使用 poilyfill 来弥补。
watch API 优化
我们使用 proxy 再来写一下 watch 函数。使用效果如下:
(function() { var root = this; function watch(target, func) { var proxy = new Proxy(target, { get: function(target, prop) { return target[prop]; }, set: function(target, prop, value) { target[prop] = value; func(prop, value); } }); if(target[name]) proxy[name] = value; return proxy; } this.watch = watch; })() var obj = { value: 1 } var newObj = watch(obj, function(key, newvalue) { if (key == 'value') document.getElementById('container').innerHTML = newvalue; }) document.getElementById('button').addEventListener("click", function() { newObj.value += 1 });
我们也可以发现,使用 defineProperty 和 proxy 的区别,当使用 defineProperty,我们修改原来的 obj 对象就可以触发拦截,而使用 proxy,就必须修改代理对象,即 Proxy 的实例才可以触发拦截。
以上がES6 でのdefineProperty と proxy の詳細な紹介 (コード例)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

はい、JavaScriptのエンジンコアはCで記述されています。1)C言語は、JavaScriptエンジンの開発に適した効率的なパフォーマンスと基礎となる制御を提供します。 2)V8エンジンを例にとると、そのコアはCで記述され、Cの効率とオブジェクト指向の特性を組み合わせて書かれています。3)JavaScriptエンジンの作業原理には、解析、コンパイル、実行が含まれ、C言語はこれらのプロセスで重要な役割を果たします。

JavaScriptは、Webページのインタラクティブ性とダイナミズムを向上させるため、現代のWebサイトの中心にあります。 1)ページを更新せずにコンテンツを変更できます。2)Domapiを介してWebページを操作する、3)アニメーションやドラッグアンドドロップなどの複雑なインタラクティブ効果、4)ユーザーエクスペリエンスを改善するためのパフォーマンスとベストプラクティスを最適化します。

CおよびJavaScriptは、WebAssemblyを介して相互運用性を実現します。 1)CコードはWebAssemblyモジュールにコンパイルされ、JavaScript環境に導入され、コンピューティングパワーが強化されます。 2)ゲーム開発では、Cは物理エンジンとグラフィックスレンダリングを処理し、JavaScriptはゲームロジックとユーザーインターフェイスを担当します。

JavaScriptは、Webサイト、モバイルアプリケーション、デスクトップアプリケーション、サーバー側のプログラミングで広く使用されています。 1)Webサイト開発では、JavaScriptはHTMLおよびCSSと一緒にDOMを運用して、JQueryやReactなどのフレームワークをサポートします。 2)ReactNativeおよびIonicを通じて、JavaScriptはクロスプラットフォームモバイルアプリケーションを開発するために使用されます。 3)電子フレームワークにより、JavaScriptはデスクトップアプリケーションを構築できます。 4)node.jsを使用すると、JavaScriptがサーバー側で実行され、高い並行リクエストをサポートします。

Pythonはデータサイエンスと自動化により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、データ処理とモデリングのためにNumpyやPandasなどのライブラリを使用して、データサイエンスと機械学習でうまく機能します。 2。Pythonは、自動化とスクリプトにおいて簡潔で効率的です。 3. JavaScriptはフロントエンド開発に不可欠であり、動的なWebページと単一ページアプリケーションの構築に使用されます。 4. JavaScriptは、node.jsを通じてバックエンド開発において役割を果たし、フルスタック開発をサポートします。

CとCは、主に通訳者とJITコンパイラを実装するために使用されるJavaScriptエンジンで重要な役割を果たします。 1)cは、JavaScriptソースコードを解析し、抽象的な構文ツリーを生成するために使用されます。 2)Cは、Bytecodeの生成と実行を担当します。 3)Cは、JITコンパイラを実装し、実行時にホットスポットコードを最適化およびコンパイルし、JavaScriptの実行効率を大幅に改善します。

現実世界でのJavaScriptのアプリケーションには、フロントエンドとバックエンドの開発が含まれます。 1)DOM操作とイベント処理を含むTODOリストアプリケーションを構築して、フロントエンドアプリケーションを表示します。 2)node.jsを介してRestfulapiを構築し、バックエンドアプリケーションをデモンストレーションします。

Web開発におけるJavaScriptの主な用途には、クライアントの相互作用、フォーム検証、非同期通信が含まれます。 1)DOM操作による動的なコンテンツの更新とユーザーインタラクション。 2)ユーザーエクスペリエンスを改善するためにデータを提出する前に、クライアントの検証が実行されます。 3)サーバーとのリフレッシュレス通信は、AJAXテクノロジーを通じて達成されます。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

WebStorm Mac版
便利なJavaScript開発ツール

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

Safe Exam Browser
Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

ホットトピック









