In traditional object-oriented languages, inheritance is often used to add functionality to objects, but inheritance can cause problems: when the parent class changes, all its subclasses will change accordingly.
When a JavaScript script is run, adding behavior to an object (or its prototype) will affect all instances of the object.
Decorator is a An alternative to implementing inheritance, which adds new functionality in the form of overloaded methods. This pattern can add your own behavior before or after the decorator to achieve a specific purpose.
The decorator pattern is a way to dynamically add more functions to existing functions. Put each function to be decorated in a separate function, and then use this function to wrap the function to be decorated. There are function objects, so when special behavior needs to be performed, the calling code can selectively and sequentially wrap the object with decorative functions as needed. The advantage is that the core responsibilities of the class (function) and the decoration function are separated.
We can define tool functions as follows:
Function.prototype.before = function (beforeFn) { var self = this; //保存原函数的引用 return function () { //返回包含了新函数和原函数的代理函数 beforeFn.apply(this,arguments); //执行新函数,且保证this不被劫持 return self.apply(this,arguments); //执行原函数,并返回原函数的执行结果,并保证this不被劫持 } }; Function.prototype.after = function (afterFn) { var self = this; return function () { var ret = self.apply(this,arguments); afterFn.apply(this,arguments); return ret; } };
The parameters beforeFn and afterFn here are new functions (adding decorations) that want to extend new functions for the original function. Their unique The difference is the order of execution. If you don’t want to pollute the Function prototype, you can use the following method:
var before = function (fn, beforeFn) { return function () { beforeFn.apply(this,arguments); return fn.apply(this,arguments); } }; var after = function (fn, afterFn) { return function () { var ret = fn.apply(this,arguments); afterFn.apply(this,arguments); return ret; } };
Example: Bring a parameter to the HTTP request to prevent CSRF attacks
var ajax = function (type, url, param) { console.log(param); //发送ajax请求代码略... }; var beforeFn = function (type, url, param) { param.Token = 'Token'; }; ajax = ajax.before(beforeFn); ajax('get','http://...com/userinfo',{name:'SuFa'}); //{ name: 'SuFa', Token: 'Token' }
By giving the ajax function Dynamically decorating the Token parameter instead of modifying the parameters directly on the original function ensures that the ajax function is still a pure function and improves its reusability. It can be directly obtained from other functions without any modification. used in the project.
Example: Form verification (separate the code for verification input and form submission, and then dynamically decorate the verification input function before form submission. In this way, we can put the verification input part Written in the form of a plug-in and used in different projects)
//验证输入函数 var validata = function () { if(username.value === ''){ alert('用户名不能为空'); return false; } if(password.value === ''){ alert('密码不能为空'); return false; } }; //表单提交函数 var formSubmit = function () { var param = { username: username.value, password: password.value }; ajax('http://xxx.com/login',param); }; formSubmit = formSubmit.before(validata); submitBtn.onclick = function(){ formSubmit(); };
The above is the entire content of this article. I hope it will be helpful to everyone's learning, and I also hope that everyone will support the PHP Chinese website.
For more articles related to the JavaScript decorator pattern, please pay attention to the PHP Chinese website!