Home > Article > Web Front-end > Talk about AOP programming in Javascript
Let’s not talk about AOP programming first, let’s start with Talk about AOP programming in Javascript punch programming.
If you search for Talk about AOP programming in Javascript punch in Wikipedia, the entry you should find is monkey patch. According to the explanation, the word monkey patch comes from guerrilla patch, which means quietly changing the code during operation. The word guerrilla has the same pronunciation as gorilla, and the latter means similar to monkey (the former means "gorilla"), and finally evolved into For monkey patch.
If you haven’t heard of Talk about AOP programming in Javascript punch, you may have heard of Talk about AOP programming in Javascript typing. To give a popular example, how to identify a Talk about AOP programming in Javascript:
When I see a bird that walks like a Talk about AOP programming in Javascript and swims like a Talk about AOP programming in Javascript and quacks like a Talk about AOP programming in Javascript, I call that bird a Talk about AOP programming in Javascript.
Yes, if I find an animal that quacks like a Talk about AOP programming in Javascript and swims like a Talk about AOP programming in Javascript, then it would be a Talk about AOP programming in Javascript!
This test may seem a little obvious and nonsensical, but it is very practical. And it can be used to solve a type of problem in programming - for Javascript or similar dynamic languages, how to implement "interface" or "base class"? We don’t need to care about their past at all. We only care about whether the method type or parameters are what we need when using them:
var quack = someObject.quack; if (typeof quack == "function" && quck.length == arguLength) { // This thing can quack }
I’m going too far. In fact, what I want to express is Talk about AOP programming in Javascript punch. It evolved from Talk about AOP programming in Javascript typing:
if it walks like a Talk about AOP programming in Javascript and talks like a Talk about AOP programming in Javascript, it's a Talk about AOP programming in Javascript, right? So if this Talk about AOP programming in Javascript is not giving you the noise that you want, you've got to just punch that Talk about AOP programming in Javascript until it returns what you expect. By the way, this reminds me of a very vivid joke:
In order to test the strength of the police in the United States, Hong Kong, and Mainland China, the United Nations placed three rabbits in three forests to watch the police from the three places. Who finds the rabbit first. Task: Find the rabbit. (The middle is omitted...) Finally, there were only four policemen from a certain country. They played mahjong for a day. At dusk, each of them took a baton and entered the forest. Within five minutes, they heard the screams of animals coming from the forest. He came out talking and laughing while smoking a cigarette, and behind him was a bear with a bruised nose and swollen face. The bear was dying and said: "Don't fight anymore, I am just a rabbit..."
At the same time, the Talk about AOP programming in Javascript punch mode can be overridden, but it is just like this:Although Talk about AOP programming in Javascript punch Somewhat violent, but still an effective method. When it comes to code implementation, it means making the original code compatible with the functions we need. For example, this example on Paul Irish's blog:
/** 我们都知道jQuery的`$.css`方法可以通过使用颜色的名称给元素进行颜色赋值。 但jQuery内置的颜色并非是那么丰富,如果我们想添加我们自定义的颜色名称应该怎么办?比如我们想添加`Burnt Sienna`这个颜色 */ (function($){ // 把原方法暂存起来: var _oldcss = $.fn.css; // 重写原方法: $.fn.css = function(prop,value){ // 把自定义的颜色写进分支判断里,特殊情况特殊处理 if (/^background-?color$/i.test(prop) && value.toLowerCase() === 'burnt sienna') { return _oldcss.call(this,prop,'#EA7E5D'); // 一般情况一般处理,调用原方法 } else { return _oldcss.apply(this,arguments); } }; })(jQuery); // 使用方法: jQuery(document.body).css('backgroundColor','burnt sienna')
(function($){ var _old = $.fn.method; $.fn.method = function(arg1,arg2){ if ( ... condition ... ) { return .... } else { // do the default return _old.apply(this,arguments); } }; })(jQuery);But there is a problem with this: the original method needs to be modified. This violates the "open-closed" principle, which should be open for expansion and closed for modification. How to solve this problem? Use AOP programming. AOP Getting Started AOP stands for Aspect-oriented programming, which is obviously relative to Object-oriented programming. Aspect can be translated as "aspect" or "side", so AOP is aspect-oriented programming. How to understand aspects? In object-oriented programming, the classes we define are usually domain models, and the methods they have are usually related to pure business logic. For example:
Class Person { private int money; public void pay(int price) { this.money = this.money - price; } }But usually the actual situation is more complicated. For example, we need to add authorization detection to the payment method, or send logs for statistics, or even fault-tolerant code. So the code will become like this:
Class Person { private int money public void pay(price) { try { if (checkAuthorize() == true) { this.money = this.money - price; sendLog(); } } catch (Exception e) { } } }What's even more frightening is that similar code must be added to other methods, so the maintainability and readability of the code become a big problem. We hope to collect these scattered but common non-business codes and use and manage them more friendly. This is aspect programming. Aspect programming achieves code reuse on the basis of avoiding modification of remote code. It's like cutting different objects horizontally and focusing on the transformation of internal methods. Object-oriented programming pays more attention to the overall architectural design. Implementation The Talk about AOP programming in Javascript punch introduced in the previous section is similar to aspect programming, both of which ensure the functionality of the original method while transforming it. But as mentioned at the end, the pattern of directly modifying the original method goes against the principles of object-oriented best practices. Javascript can use the decorator pattern (adding additional responsibilities to the original object but avoiding modifying the original object) to implement AOP programming. Note that the emphasis here is implementation. What I further want to emphasize is that aspect programming is just an idea, and the decorator pattern is just a means of practicing this idea. For example, in Java, you can use the proxy pattern, etc. Aspect programming has more room to play in Java and is more standard. I wanted to introduce Java's implementation model into this article, but my Java level is limited and I don't understand Java's implementation very well. Only the Javascript implementation is shown here.
AOP中有一些概念需要介绍一下,虽然我们不一定要严格执行
joint-point:原业务方法;
advice:拦截方式
point-cut:拦截方法
关于这三个概念我们可以串起来可以这么理解:
当我们使用AOP改造一个原业务方法(joint-point)时,比如加入日志发送功能(point-cut),我们要考虑在什么情况下(advice)发送日志,是在业务方法触发之前还是之后;还是在抛出异常的时候,还是由日志发送是否成功再决定是否执行业务方法。
比如gihub上的meld这个开源项目,就是一个很典型的AOP类库,我们看看它的API:
// 假设我们有一个对象myObject, 并且该对象有一个doSomething方法: var myObject = { doSomething: function(a, b) { return a + b; } }; // 现在我们想拓展它,在执行那个方法之后打印出刚刚执行的结果: var remover = meld.after(myObject, 'doSomething', function(result) { console.log('myObject.doSomething returned: ' + result); }); // 试试执行看: myObject.doSomething(1, 2); // Logs: "myObject.doSomething returned: 3" // 这个时候我们想移除刚刚的修改: remover.remove();
由此可以看出,AOP接口通常需要三个参数,被修改的对象,被修改对象的方法(joint-point),以及触发的时机(apce),还有触发的动作(point-cut)。上面说了那么多的概念,现在可能要让各位失望了,Javascript的实现原理其实非常简单
function doAfter(target, method, afterFunc){ var func = target[method]; return function(){ var res = func.apply(this, arguments); afterFunc.apply(this, arguments); return res; }; }
当然,如果想看到更完备的解决方案和代码可以参考上面所说的meld项目
这一篇一定让你失望了,代码简单又寥寥无几。本篇主要在于介绍有关Talk about AOP programming in Javascript和AOP的这几类思想,我想编程的乐趣不仅仅在于落实在编码上,更在于整个架构的设计。提高代码的可维护性和可拓展性会比高深莫测的代码更重要。
以上就是聊Javascript中的AOP编程的内容,更多相关内容请关注PHP中文网(www.php.cn)!