使用函数装饰器巧妙实现数据埋点上报、表单验证

函数装饰器(AOP面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些跟业务逻辑无关的功能通常包括日志统计,安全控制,异常处理等。把这些功能抽离出来后,再通过动态织入的方式掺入业务逻辑模块中

实现一个简单的AOP

js 复制代码
Function.prototype.before = function(beforeFn) {
  var _self = this;
  return function() {
    beforeFn.apply(this,arguments);
    return _self.apply(this,arguments);
  }
}
Function.prototype.after = function(afterFn) {
  var _self = this;
  return function() {
    var ret = _self.apply(this,arguments);
    afterFn.apply(this,arguments);
    return ret
  }
}

// 使用
var func = function() {
  console.log(2);
}
func = func.before(function(){
  console.log(1);
}).after(function(){
  console.log(3);
})
func(); // 1 2 3

不污染原型的实现

js 复制代码
function before(fn, beforeFn) {
    return function() {
        beforeFn.apply(this, arguments)
        return fn.apply(this, arguments)
    }
}

function after(fn, afterFn) {
    return function() {
        var ret = fn.apply(this, arguments)
        afterFn(this, arguments)
        return ret
    }
}

应用实例一:数据埋点上报。

分离业务代码和数据统计代码,无论在什么语言中,都是AOP的经典应用之一。

html 复制代码
<button id="btnLogin">点击打开登录浮层</button>
js 复制代码
// 数据上报
Function.prototype.before = function (beforeFn) {
  var _self = this;
  return function () {
    beforeFn.apply(this, arguments);
    return _self.apply(this, arguments);
  }
}
Function.prototype.after = function (afterFn) {
  var _self = this;
  return function () {
    var ret = _self.apply(this, arguments);
    afterFn.apply(this, arguments);
    return ret;
  }
}
var showLogin = function() {
  console.log('打开登录浮层');
}

// 依次输出:按钮点击之前上报  打开登录浮层  按钮点击之后上报
document.getElementById('btnLogin').onclick = showLogin.before(function(){
  console.log('按钮点击之前上报');
}).after(function() {
  console.log('按钮点击之后上报');
});

应用实例一:表单验证

html 复制代码
用户名:<input type="text" id="username">
密码:<input type="password" id="password">
<button id="loginBtn">登录</button>
js 复制代码
Function.prototype.before = function (beforeFn) {
  var _self = this;
  return function () {
    if(beforeFn.apply(this,arguments)===false) {
      // 未验证通过,不再执行原函数
      return ;
    }
    return _self.apply(this, arguments);
  }
}
var username = document.getElementById('username');
var password = document.getElementById('password');
var loginBtn = document.getElementById('loginBtn');
// 验证函数
var validate = function() {
  if(username.value === '') {
    console.log('用户名不能为空');
    return false;
  }
  if(password.value === '') {
    console.log('密码不能为空');
    return false;
  }
}
// 登录ajax
var formSubmit = function() {
  var params = {
    username: username,
    password: password
  }
  console.log('登录ajax...');
}
// 登录按钮点击
formSubmit = formSubmit.before(validate);
loginBtn.onclick = function() {
  formSubmit();
};

点个赞~~, 一起学习,一起进步

相关推荐
Y.O.U..13 分钟前
八股-2025.10.24
面试
你的电影很有趣17 分钟前
lesson77:Vue组件开发指南:从基础使用到高级通信
javascript·vue.js·1024程序员节
我是华为OD~HR~栗栗呀33 分钟前
华为OD-Java面经-21届考研
java·c++·后端·python·华为od·华为·面试
Mr.Jessy37 分钟前
JavaScript学习第六天:函数
开发语言·前端·javascript·学习·html·1024程序员节
code_YuJun1 小时前
管理系统——应用初始化 Loading 动画
前端
oak隔壁找我1 小时前
JavaScript 模块化演进历程:问题与解决方案。
前端·javascript·架构
Elieal1 小时前
AJAX 知识
前端·ajax·okhttp
sulikey2 小时前
Qt 入门简洁笔记:从框架概念到开发环境搭建
开发语言·前端·c++·qt·前端框架·visual studio·qt框架
烟袅2 小时前
JavaScript 变量声明报错指南:var、let、const 常见错误解析
javascript
烟袅2 小时前
告别 var!深入理解 JavaScript 中 var、let 和 const 的差异与最佳实践
javascript·面试