


Aop is also called aspect-oriented programming, in which "notification" is the specific implementation of aspects, which is divided into before (pre-notification), after (post-notification), and around (surround notification). Students who have used spring must be familiar with it. Very familiar, but in js, AOP is a seriously ignored technical point. However, using aop can effectively improve js code logic. For example, in front-end frameworks dojo and yui3, AOP is promoted to an internal mechanism of custom events, which can be seen everywhere in the source code. Thanks to this abstraction, Dojo's custom events are extremely powerful and flexible. The implementation of aop in dojo is in the dojo/aspect module. There are three main methods: before, after, and around. This article will lead you step by step to implement the around method. Subsequent articles will provide an in-depth analysis of the structural system of the dojo/aspect module.
To implement surround notification in js, the simplest and most thought-provoking way is to use callback
advice = function(originalFunc){ console.log("before function"); originalFunc(); console.log("after function"); } var obj = { foo: function(){ console.log('foo'); } } advice(obj.foo)
Result:
before function
foo
after function
Haha, it’s too simple. Can you go back to sleep? . . .
But, isn’t it a bit too rough? . . . The promised surroundings. . . . At least the next call to obj.foo should have this result, instead of a dry "foo"; for this we need to make some changes and use closures
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()
Output:
before function
after function
It seems that the surround effect has been achieved, but where has the promised name gone? . . .
In the closure returned by advice, we also need to deal with scope issues
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);
It seems that the scope problem is solved by using call. Let’s run it and see:
Damn it, is this the legendary endless loop? . . .
It seems that we still need to make some changes and use an intermediate variable to eliminate the infinite loop
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();
Output:
before function
obj
after function
Haha, the world suddenly became a beautiful place. . . .
But does this bunch of code seem too low? Should we come up with some high-level abstractions? Well, I think so too
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();
The around method decouples the processing process from the specific object; as long as advice is written in the following format, the around effect can be achieved
advice = function(originalFunc){ return function() { //before originalFunc(); //after } }
Haha, you are so tall and cool in an instant, so cool. . . .
Then the question comes: What should I do if I accidentally call the around method one more time? . . . Forehead. . . . This is a question. Should we let around return a handle with a remove method to eliminate the binding, just like binding/removing events.
What remove means is that the next time the function is executed, it will no longer execute the corresponding around method, but only run the originalFunc method
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();
Output:
before function 2 before function 1 obj and [object Arguments] after function 1 after function 2 obj and undefined before function 1
This. . Not only does it turn out to be a bit messy. . . Also reported an error. . . . Yes, it's bearable, but my uncle can't bear it. My uncle can't bear it, but my sister-in-law can't bear it!
Ah, closure. . . Please give me strength!
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');
Output:
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
After the fight, call it a day!
The first time I stayed up all night to blog, I was also drunk. At two o'clock, I heard the fuck me next door. At four o'clock, I heard the crow of crows. There was also an unknown bird chirping. At five o'clock, there were a lot of people. Birds chirp. . . .
Reference article:
Use AOP to improve javascript code
AOP (aspect-oriented programming) and OOP (object-oriented programming) of yui3

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

SublimeText3 English version
Recommended: Win version, supports code prompts!

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)
