


Introduction détaillée à DefineProperty et proxy dans ES6 (exemple de code)
Cet article vous apporte une introduction détaillée (exemple de code) sur DefineProperty et proxy dans ES6. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Nous avons tous plus ou moins entendu le mot « liaison de données ». La clé de la « liaison de données » est de surveiller les changements dans les données, mais pour un tel objet : var obj = {value: 1}
, comment savons-nous obj Quoi ? a changé ?
definePropety
ES5 fournit la méthode Object.defineProperty, qui peut définir une nouvelle propriété sur un objet, ou modifier une propriété existante d'un objet et renvoyer l'objet.
Syntaxe
Object.defineProperty(obj, prop, descriptor)
Paramètres
obj: 要在其上定义属性的对象。 prop: 要定义或修改的属性的名称。 descriptor: 将被定义或修改的属性的描述符。
Par exemple :
var obj = {}; Object.defineProperty(obj, "num", { value : 1, writable : true, enumerable : true, configurable : true }); // 对象 obj 拥有属性 num,值为 1
Bien que nous puissions ajouter des propriétés et des valeurs directement, en utilisant cette méthode, nous pouvons effectuer davantage de configuration. Le descripteur d'attribut représenté par le troisième descripteur de paramètre de la fonction
a deux formes : descripteur de données et descripteur d'accès .
Les deux ont les deux valeurs clés suivantes :
configurable
si et seulement si l'attribut configurable est Quand vrai, le descripteur de propriété peut être modifié ou supprimé. La valeur par défaut est fausse.
enumerable
Si et seulement si l'énumérable de l'attribut est vrai, l'attribut peut apparaître dans l'attribut d'énumération de l'objet. La valeur par défaut est fausse.
Le descripteur de données possède également les valeurs clés facultatives suivantes :
valeur
La valeur correspondant à cet attribut. Il peut s'agir de n'importe quelle valeur JavaScript valide (nombre, objet, fonction, etc.). La valeur par défaut n'est pas définie.
writable
Cette propriété peut être modifiée par l'opérateur d'affectation si et seulement si l'écriture de la propriété est vraie. La valeur par défaut est fausse.
Le descripteur d'accès a également les valeurs de clés facultatives suivantes :
get
celle fournie pour la méthode Getter d'attribut, s'il n'y a pas de getter, il n'est pas défini. La valeur de retour de cette méthode est utilisée comme valeur d'attribut. La valeur par défaut n'est pas définie.
set
Une méthode qui fournit un setter pour une propriété. S'il n'y a pas de setter, elle n'est pas définie. . Cette méthode acceptera un paramètre unique et attribuera la nouvelle valeur du paramètre à la propriété. La valeur par défaut n'est pas définie.
Il convient de noter :
Les descripteurs d'attribut doivent être soit des descripteurs de données, soit des descripteurs d'accès, pas les deux en même temps. Cela signifie que vous pouvez :
Object.defineProperty({}, "num", { value: 1, writable: true, enumerable: true, configurable: true });
Également :
var value = 1; Object.defineProperty({}, "num", { get : function(){ return value; }, set : function(newValue){ value = newValue; }, enumerable : true, configurable : true });
Mais pas :
// 报错 Object.defineProperty({}, "num", { value: 1, get: function() { return 1; } });
De plus, toutes les descriptions d'attributs Les descripteurs ne sont pas obligatoires , mais le champ descripteur est obligatoire. Si vous n'effectuez aucune configuration, vous pouvez faire ceci :
var obj = Object.defineProperty({}, "num", {}); console.log(obj.num); // undefined
Setters et Getters
La raison pour laquelle nous parlons de DefineProperty est parce que nous en avons besoin. pour utiliser get et set dans le descripteur d'accès. Ces deux méthodes sont également appelées getters et setters. Les propriétés définies par les getters et les setters sont appelées « propriétés d'accesseur ».
Lorsqu'un programme interroge la valeur d'une propriété d'accesseur, JavaScript appelle la méthode getter. La valeur de retour de cette méthode est la valeur de l'expression d'accès à l'attribut. Lorsqu'un programme définit la valeur d'une propriété d'accesseur, JavaScript appelle la méthode setter, en transmettant la valeur située à droite de l'expression d'affectation en tant que paramètre au setter. Dans un sens, cette méthode est chargée de « définir » la valeur de la propriété. La valeur de retour de la méthode setter peut être ignorée.
Par exemple :
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
N'est-ce pas la méthode avec laquelle nous souhaitons surveiller les modifications des données ? Encapsulons-le à nouveau :
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
Étant donné que les modifications des données peuvent être surveillées, je peux imaginer que lorsque les données changent, le travail de rendu sera automatiquement effectué. Par exemple :
Il y a une balise span et une balise bouton en HTML
<span id="container">1</span> <button id="button">点击加 1</button>
Lorsque l'on clique sur le bouton, la valeur de la balise span est augmentée de 1.
L'approche traditionnelle est :
document.getElementById('button').addEventListener("click", function(){ var container = document.getElementById("container"); container.innerHTML = Number(container.innerHTML) + 1; });
Si DefineProperty est utilisé :
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; });
Le code semble augmenter, mais lorsque nous devons changer la valeur dans le span tagQuand, modifiez simplement la valeur de obj.value directement.
Cependant, avec la façon actuelle d'écrire, nous devons toujours déclarer une variable distincte pour stocker la valeur de obj.value, car si vous obj.value = newValue
directement dans set, vous tomberez dans une boucle infinie. De plus, nous devrons peut-être surveiller les changements dans de nombreuses valeurs d'attributs. Il serait fastidieux de les écrire une par une, nous écrivons donc simplement une fonction de surveillance. L'effet d'utilisation est le suivant :
var obj = { value: 1 } watch(obj, "num", function(newvalue){ document.getElementById('container').innerHTML = newvalue; }) document.getElementById('button').addEventListener("click", function(){ obj.value += 1 });
Écrivons cette fonction de surveillance :
(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; })()
Nous pouvons maintenant surveiller les changements dans les valeurs d'attribut de l'objet, et en fonction des changements dans le valeurs d'attribut, ajoutez une fonction de rappel, génial ~
proxy
L'utilisation de definitionProperty ne peut redéfinir que les comportements de lecture (get) et de définition (set) des propriétés Dans ES6, le proxy est fourni et peut être. redéfini. Plus de comportements, tels que l'entrée, la suppression, les appels de fonction et plus encore.
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 的实例才可以触发拦截。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Le langage Go propose deux technologies de création de fonctions dynamiques : la fermeture et la réflexion. les fermetures permettent d'accéder aux variables dans la portée de la fermeture, et la réflexion peut créer de nouvelles fonctions à l'aide de la fonction FuncOf. Ces technologies sont utiles pour personnaliser les routeurs HTTP, mettre en œuvre des systèmes hautement personnalisables et créer des composants enfichables.

Dans la dénomination des fonctions C++, il est crucial de prendre en compte l’ordre des paramètres pour améliorer la lisibilité, réduire les erreurs et faciliter la refactorisation. Les conventions courantes d'ordre des paramètres incluent : action-objet, objet-action, signification sémantique et conformité de la bibliothèque standard. L'ordre optimal dépend de l'objectif de la fonction, des types de paramètres, de la confusion potentielle et des conventions du langage.

La clé pour écrire des fonctions Java efficaces et maintenables est la suivante : restez simple. Utilisez un nom significatif. Gérer des situations particulières. Utilisez une visibilité appropriée.

1. La fonction SOMME permet de sommer les nombres d'une colonne ou d'un groupe de cellules, par exemple : =SOMME(A1:J10). 2. La fonction MOYENNE permet de calculer la moyenne des nombres dans une colonne ou un groupe de cellules, par exemple : =AVERAGE(A1:A10). 3. Fonction COUNT, utilisée pour compter le nombre de nombres ou de texte dans une colonne ou un groupe de cellules, par exemple : =COUNT(A1:A10) 4. Fonction IF, utilisée pour effectuer des jugements logiques basés sur des conditions spécifiées et renvoyer le résultat correspondant.

Les avantages des paramètres par défaut dans les fonctions C++ incluent la simplification des appels, l’amélioration de la lisibilité et l’évitement des erreurs. Les inconvénients sont une flexibilité limitée et des restrictions de dénomination. Les avantages des paramètres variadiques incluent une flexibilité illimitée et une liaison dynamique. Les inconvénients incluent une plus grande complexité, des conversions de types implicites et des difficultés de débogage.

Les avantages des fonctions renvoyant des types référence en C++ incluent : Améliorations des performances : le passage par référence évite la copie d'objets, économisant ainsi de la mémoire et du temps. Modification directe : L'appelant peut modifier directement l'objet de référence renvoyé sans le réaffecter. Simplicité du code : le passage par référence simplifie le code et ne nécessite aucune opération d'affectation supplémentaire.

La différence entre les fonctions PHP personnalisées et les fonctions prédéfinies est la suivante : Portée : les fonctions personnalisées sont limitées à la portée de leur définition, tandis que les fonctions prédéfinies sont accessibles tout au long du script. Comment définir : les fonctions personnalisées sont définies à l'aide du mot-clé function, tandis que les fonctions prédéfinies sont définies par le noyau PHP. Passage de paramètres : les fonctions personnalisées reçoivent des paramètres, tandis que les fonctions prédéfinies peuvent ne pas nécessiter de paramètres. Extensibilité : des fonctions personnalisées peuvent être créées selon les besoins, tandis que les fonctions prédéfinies sont intégrées et ne peuvent pas être modifiées.

La gestion des exceptions en C++ peut être améliorée grâce à des classes d'exceptions personnalisées qui fournissent des messages d'erreur spécifiques, des informations contextuelles et effectuent des actions personnalisées en fonction du type d'erreur. Définissez une classe d'exception héritée de std::exception pour fournir des informations d'erreur spécifiques. Utilisez le mot-clé throw pour lancer une exception personnalisée. Utilisez Dynamic_cast dans un bloc try-catch pour convertir l'exception interceptée en un type d'exception personnalisé. Dans le cas réel, la fonction open_file lève une exception FileNotFoundException. La capture et la gestion de l'exception peuvent fournir un message d'erreur plus spécifique.
