This is a function that weaves AOP advices dynamically. Unlike dcl.advise()
it works on objects, rather than when defining “classes”. All advices can be “unadvised” at any moment.
Description
advise() is a function, which takes three parameters:
obj - the object to advise. Any object would do, including objects produced without dcl-made constructors.
name - the method name. If the method had AOP advices defined by dcl(), and/or previous calls
to advise(), they will be properly combined.
advice - the object with properties before, around, and/or after. See dcl.advise() for more details.
It returns the object, which defines the method unadvise(). When called without parameters, it removes the corresponding advice from the object, no matter when it was defined. For convenience, this method is aliased as remove(), and destroy().
How to use advices is described in details in dcl.advise().
advise()
1234567891011121314151617181920212223242526
vara={method:function(msg){cosole.log("MSG: "+msg);}};varmethodAdv=advise(a,"method",{before:function(msg){console.log("Method was called with msg = "+msg);},after:function(args,result){console.log("Method has finished.");},around:function(sup){returnfunction(msg){// let's ignore our parametersub.call(this,"Canned response no matter what.");};}});a.method("Hey!");// Method was called with msg = Hey!// MSG: Canned response no matter what.// Method has finished.methodAdv.unadvise();// Now all previous advices are removed from the object.
Like dcl.advise(), advise() can be used to advise getters and setters. Unlike dcl.advise(), it cannot dynamically convert values to getters, and getters to values. So if you want to advise a getter (or a setter), they should be already defined.
advise() with getters/setters
12345678910111213141516171819202122232425262728
vara={getx(){returnthis.v||0;},setx(v){this.v=v;}};varpropAdv=advise(a,"x",{get:{before:function(){console.log("getting x");},after:function(){console.log("Getter has finished.");},around:function(sup){returnfunction(){return2*sup.call(this);};}},set:{before:function(v){console.log("setting x to "+v);},after:function(){console.log("Setter has finished.");}}});
Examples
advise() changes return values
1234567891011
vara=...;advise(a,'m',{after:function(args,result,makeReturn,makeThrow){if(result%2){makeReturn(1);return;}makeThrow(newError("evil even number!"));}});
Notes
Shortcuts
If you want to weave just one advice, you may want to use a shortcut:
advise.before()
123456789
advise.before(a,"method",function(msg){console.log("Method was called with msg = "+msg);});// is equivalent toadvise(a,"method",{before:function(msg){console.log("Method was called with msg = "+msg);}});
advise.after()
123456789
advise.after(a,"method",function(){console.log("Method has finished.");});// is equivalent toadvise(a,"method",{after:function(){console.log("Method has finished.");}});
advise.around()
123456789101112131415
advise.around(a,"method",function(sup){returnfunction(msg){// let's ignore our parametersub.call(this,"Canned response no matter what.");};});// is equivalent toadvise(a,"method",{around:function(sup){returnfunction(msg){// let's ignore our parametersub.call(this,"Canned response no matter what.");};}});