老大见小T终于摸清了用AOP装饰函数的一些套路,很是欣慰,决定用实际情景让他试一试,老大拿出了一个最常见的AOP的经典应用之一—数据统计上报的情景,分离业务代码和数据统计上报的代码,在实际开发中项目结尾阶段难免要加上很多统计数据的代码,这个过程可能被迫改动早已封装好的函数.
1.老大给小T设定了一个情景如下:页面中有一个登录的button,点击这个button会弹出登录的浮层,与此同时需要进行数据上报来统计有多少用户点击了这个登录的button(这个任务可能是在项目结尾阶段进行的),让小T发现问题并进行改写:
<html> <input type="button" value="login" id="login" /> <script> const login = document.getElementById('login'); const textlogin = login.tagName; let x = 0; let showLogin = function () { console.log('打开登录浮层'); log(textlogin); } let log = function (tag) { x = x + 1; console.log('上报标签为:' + tag +','+ '上报次数为:' + x); // 这里我简单的用login按钮单击的次数来模拟,上报过程略 } login.onclick = showLogin; </script> </html>
小T发现在showLogin函数里既要弹层又要上报点击次数,两个层面的功能,却被耦合在一个函数中,决定用昨天刚写好的AOP试一试:
<html> <input type="button" value="login" id="login" /> <script> Function.prototype.after = function(afterfn){ let _self = this; return function(){ let ret = _self.apply(this,arguments); afterfn.apply(this,arguments); return ret; } } const login = document.getElementById('login'); const textlogin = login.tagName; let x = 0; let showLogin = function(){ console.log('打开登录浮层'); } let log = function(){ x = x+1; console.log('上报标签为:' + tag +','+ '上报次数为:' + x); } showLogin = showLogin.after(log); // 打开登录浮层后上报数据 login.onclick = showLogin; </script> </html>
小T欣喜若狂,这样两个不同层面功能的函数就可以单独维护,不存在耦合问题,决定把自己的成果给老大展示一番,老大看了微微一笑点了点头,觉得小T的进步着实很快,决定让他尝试一下用AOP动态改变函数的参数: