ES6 でのdefineProperty と proxy の詳細な紹介 (コード例)
この記事では、ES6 の defineProperty と proxy について詳しく説明します (コード例)。必要な方は参考にしていただければ幸いです。
私たちは皆、多かれ少なかれ「データ バインディング」という言葉を聞いたことがあるでしょう。「データ バインディング」の鍵はデータの変更を監視することですが、そのようなオブジェクトの場合は次のようになります。 obj が変更されたことを知っていますか?
definePropety
ES5 は、オブジェクトの新しいプロパティを定義したり、オブジェクトの既存のプロパティを変更したり、このオブジェクトを返すことができる Object.defineProperty メソッドを提供します。 。
構文
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
属性の構成可能値が When である場合に限り、次の 2 つのキー値を持ちます。 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); // undefined
Setters と Getters
defineProperty について説明する理由は、次のとおりです。アクセス記述子で 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 id="container">1</span> <button id="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; })()
これで、オブジェクトの属性値の変化を監視し、属性値の変化に基づいてコールバック関数を追加できるようになりました。素晴らしい ~
proxy
defineProperty を使用すると、プロパティの読み取り (get) と設定 (set) の動作のみを再定義できます。ES6 では Proxy が提供されるため、次のことが可能です。 in、delete、関数呼び出しなど、さらに多くの動作を再定義します。
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 サイトの他の関連記事を参照してください。

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

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

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが

使用法: JavaScript では、insertBefore() メソッドを使用して、DOM ツリーに新しいノードを挿入します。このメソッドには、挿入される新しいノードと参照ノード (つまり、新しいノードが挿入されるノード) の 2 つのパラメータが必要です。
