Maison >interface Web >js tutoriel >Javascript aop (programmation orientée aspect) autour des compétences d'analyse_javascript
Aop est également appelé programmation orientée aspect, dans laquelle la « notification » est l'implémentation spécifique des aspects, qui est divisée en avant (pré-notification), après (post-notification) et autour (notification surround des étudiants). ceux qui ont utilisé Spring doivent le connaître très bien, mais en js, AOP est un point technique sérieusement ignoré. Cependant, l'utilisation d'aop peut améliorer efficacement la logique du code js. Par exemple, dans les frameworks frontaux dojo et yui3, AOP est promu au rang de mécanisme interne d'événements personnalisés, visible partout dans le code source. Grâce à cette abstraction, les événements personnalisés de Dojo sont extrêmement puissants et flexibles. L'implémentation d'aop dans le dojo se fait dans le module dojo/aspect. Il existe trois méthodes principales : avant, après et autour. Cet article vous guidera étape par étape pour implémenter la méthode autour. Les articles suivants fourniront une analyse approfondie. du système structurel du module dojo/aspect.
Pour implémenter la notification surround dans js, le moyen le plus simple et le plus stimulant est d'utiliser le rappel
advice = function(originalFunc){ console.log("before function"); originalFunc(); console.log("after function"); } var obj = { foo: function(){ console.log('foo'); } } advice(obj.foo)
Résultat :
avant la fonction
foo
après la fonction
Haha, c'est trop simple. Peux-tu te rendormir ? . . .
Mais n’est-ce pas un peu trop dur ? . . . Le cadre promis. . . . Au moins le prochain appel à obj.foo devrait avoir ce résultat, au lieu d'un "foo" sec pour cela, nous devons apporter quelques modifications et utiliser des fermetures
;advice = function(originalFunc){ return function() { console.log("before function"); originalFunc(); console.log("after function"); } } var obj = { foo: function(){ console.log(this.name); }, name: "obj" } obj.foo = advice(obj.foo) obj.foo()
Sortie :
avant la fonction
après la fonction
Il semble que l'effet surround ait été atteint, mais où est passé le nom promis ? . . .
Dans la clôture renvoyée par les conseils, nous devons également régler les problèmes de portée
advice = function(originalFunc){ return function() { console.log("before function"); originalFunc(); console.log("after function"); } } var obj = { foo: function(){ console.log(this.name); }, name: "obj" } keepContext = function() { return obj['foo'].call(obj); } obj.foo = advice(keepContext);
Il semble que le problème de portée soit résolu en utilisant call. Lançons-le et voyons :
Bon sang, c'est la légendaire boucle sans fin ? . . .
Il semble que nous devions encore apporter quelques modifications et utiliser une variable intermédiaire pour éliminer la boucle infinie
advice = function(originalFunc){ return function() { console.log("before function"); originalFunc(); console.log("after function"); } } var obj = { foo: function(){ console.log(this.name); }, name: "obj" } var exist = obj.foo; keepContext = function() { return exist.call(obj); } obj.foo = advice(keepContext); obj.foo();
Sortie :
avant la fonction
obj
après la fonction
Haha, le monde est soudainement devenu un endroit magnifique. . . .
Mais ce tas de code semble-t-il trop bas ? Devrions-nous proposer des abstractions de haut niveau ? Eh bien, je le pense aussi
function around(obj, prop, advice){ var exist = obj[prop]; var advised = advice(function(){ return exist.call(obj, arguments); }); obj[prop] = advised; } advice = function(originalFunc){ return function() { console.log("before function"); originalFunc(); console.log("after function"); } } var obj = { foo: function(){ console.log(this.name); }, name: "obj" } around(obj, 'foo', advice); obj.foo();
La méthode autour dissocie le processus de traitement de l'objet spécifique ; tant que les conseils sont rédigés dans le format suivant, l'effet autour peut être obtenu
advice = function(originalFunc){ return function() { //before originalFunc(); //after } }
Haha, tu es si grand et cool en un instant, tellement cool. . . .
Ensuite, la question se pose : que dois-je faire si j'appelle accidentellement la méthode around une fois de plus ? . . . Front. . . . C'est une question. Devrions-nous laisser revenir un handle avec une méthode de suppression pour éliminer la liaison, tout comme les événements de liaison/suppression.
Ce que supprimer signifie, c'est que la prochaine fois que la fonction sera exécutée, elle n'exécutera plus la méthode around correspondante, mais exécutera uniquement la méthode originalFunc
function around(obj, prop, advice){ var exist = obj[prop]; var previous = function(){ return exist.call(obj, arguments); }; var advised = advice(previous); obj[prop] = advised; return { remove: function(){ obj[prop] = exist; advice = null; previous = null; exist = null; obj = null; } } } var count = 1; advice = function(originalFunc){ var current = count++; return function() { console.log("before function " + current); originalFunc(arguments); console.log("after function " + current); } } var obj = { foo: function(arg){ console.log(this.name + " and " + arg); }, name: "obj" } h1 = around(obj, 'foo', advice); h2 = around(obj, 'foo', advice); obj.foo(); h1.remove(); obj.foo(); h2.remove(); obj.foo();
Sortie :
before function 2 before function 1 obj and [object Arguments] after function 1 after function 2 obj and undefined before function 1
Ceci. . Non seulement cela s’avère un peu compliqué. . . A également signalé une erreur. . . . Oui, c'est supportable, mais mon oncle ne peut pas le supporter. Mon oncle ne peut pas le supporter, mais ma belle-sœur ne peut pas le supporter !
Ah, clôture. . . S'il vous plaît, donnez-moi de la force !
function around(obj, prop, advice){ var exist = obj[prop]; var previous = function(){ return exist.apply(obj, arguments); }; var advised = advice(previous); obj[prop] = function(){ //当调用remove后,advised为空 //利用闭包的作用域链中可以访问到advised跟previous变量,根据advised是否为空可以来决定调用谁 return advised ? advised.apply(obj, arguments) : previous.apply(obj, arguments); }; return { remove: function(){ //利用闭包的作用域链,在remove时将advised置空,这样执行过程中不会进入本次around //这几个不能删 //obj[prop] = exist; advised = null; advice = null; //previous = null; //exist = null; //obj = null; } } } var count = 1; advice = function(originalFunc){ var current = count++; return function() { console.log("before function " + current); originalFunc.apply(this, arguments); console.log("after function " + current); } } var obj = { foo: function(arg){ console.log(this.name + " and " + arg); }, name: "obj" } h1 = around(obj, 'foo', advice); h2 = around(obj, 'foo', advice); obj.foo('hello world'); h1.remove(); obj.foo('hello world'); h2.remove(); obj.foo('hello world');
Sortie :
before function 2 before function 1 obj and hello world after function 1 after function 2 before function 2 obj and hello world after function 2 obj and hello world
Après le combat, arrêtez-vous !
La première fois que je suis resté éveillé toute la nuit pour bloguer, j'étais aussi ivre. À deux heures, j'ai entendu me baiser à côté. À quatre heures, j'ai entendu le chant des corbeaux. Des oiseaux inconnus gazouillaient. A cinq heures, il y avait beaucoup de monde. Les oiseaux gazouillaient. . . .
Article de référence :
Utilisez AOP pour améliorer le code javascript
AOP (programmation orientée aspect) et POO (programmation orientée objet) de yui3