Page 1 of 1

Aspect Oriented Javascript: The "Prefix" Rate Topic: -----

#1 Asusultra  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 7
  • View blog
  • Posts: 39
  • Joined: 24-March 09

Posted 20 May 2011 - 06:23 PM

This tutorial is focused on Aspect-Oriented Javascript, specifically the Prefix method implementation and use.

Aspect-Oriented Programming is a way to handle "cross-cutting concerns". -More detail on aspect oriented programming is given as a link at the end of this tutorial.

The Prefix method is designed to allow a method to be called right before another method without having to write:
aMethod();
anotherMethod();


everytime it is needed.

Using the Prefix method can also replace replicated code within your functions. If you have the same code written in 100 methods, besides being poor design, the maintenance is deadly. Place that code within a function and use Prefix on the methods that need it. The functions will still use the code and the repeated code is now in one location. This can tremendously increase the maintainability of your code.

I'll first give you the implementation. The code is heavily commented for more clarity.
If it is too noisy let me know :/

//Arguments:
// - OwnerObject - This is the object that contains the given "MethodName".
// - MethodName - This is the string name of the method that will be called after the prefix function.
// - PrefixFunc - This is the method that will be called right before the specified method "MethodName".
// - PrefixFuncArgs - These are the arguments that the prefix method takes (if any).
//Returns:
// - returns the return result of the MethodName call.
function Prefix(OwnerObject, MethodName, PrefixFunc, PrefixFuncArgs) {
	//store the original method locally -so we don't lose it, and to call it later
	var OriginalRef = OwnerObject[MethodName];
	//overwrite the original method with our prefixProxy function
	//this will cause prefixProxy to run everytime the original function is called
	OwnerObject[MethodName] = function prefixProxy() {
		//test to see whether there are any arguments.
		if (typeof PrefixFuncArgs != 'undefined' && PrefixFuncArgs != null) {
			//if there are, pass them along with the call to the prefix function.
			//Additional handling of arguments should be done in the prefix function
			PrefixFunc.call(window, PrefixFuncArgs);
		}
		//if all tests fail for PrefixFuncArgs, then there were no arguments!
		//So just call the prefix method
		else { PrefixFunc.call(); }
		//OwnerObject[MethodName] = OriginalRef; //use this to "de-prefix" the method.
		//call the original method and get the return value (if any).
		var res = OriginalRef.call(this, arguments[0]);
		//return the result of the orginal function.
		return res;
	};
}



how do we know this works? we test!

Lets test the 'no args' condition of Prefix
//global var to gather function data.
var str = new String();

//used to test the "no arguments" condition in the Prefix method.
//this is our prefix method.
function prefixFuncNoArgs()
{
	//indicate that this method has been called with no arguments received.
	str += "\nprefixFuncNoArgs - called";
}
//this is the function that will be prefixed.
//everytime this method is called, the prefix method will call right before it.
function originalFunc()
{
	//below indicates that this has been called.
	str += "\noriginalFunc - called";
}

//Prefix the 'originalFunc' method with the 'prefixFuncNoArgs' method.
//Arguments:
//OwnerObject "this" - in this case, this is the 'window' object.
//MethodName "originalFunc" - 'MethodName' takes a string representing the name of the method. in this case, the method is "originalFunc".
//PrefixFunc "prefixFuncNoArgs" - this is the prefix method (with no parenthases or arguments).
//PrefixFuncArgs "null" - in this case, there are no arguments to pass to the "PrefixFunc".
Prefix(this, "originalFunc", prefixFuncNoArgs, null);

//now call the original function "originalFunc"
originalFunc();

//see that "str" now contains:
// prefixFuncNoArgs - called
// originalFunc - called
//notice the "prefixFuncNoArgs - called" is BEFORE "originalFunc - called".
//this is because out Prefix method did its job.
alert(str);

//since we did not "de-prefix" -remove the prefix of- originalFunc, the prefix will still be called
//each time the originalFunc method is called.
originalFunc();

//see that "str" now contains:
// prefixFuncNoArgs - called
// originalFunc - called
// prefixFuncNoArgs - called
// originalFunc - called
alert(str);



The test above does not include testing the "return" functionality, "de-prefix"-ing the original method, or adding arguments for the prefix function.

Note: to de-prefix the original method, uncomment line 23 in the implementation above.
Another Note: to add arguments for the prefix function using this implementation of Prefix just add your arguments to an array and pass it to Prefix.

The prefix function can contain any Javascript code that you need. For example, if you need to be sure a javascript library is existent before you can execute your code:
  • define a function that adds the the needed javascript library
  • prefix the function that needs the javascript library with the function that adds it.
  • use your function without worry that the library does not exist! ..unless your server fails to send it over :/



There are certainly enhancements that can be made to the Prefix function:
  • allow multiple functions to be prefixed at once
  • allow multiple prefixes to be added to a function at once
  • allow a function to be prefixed only for a certain amount of calls


Other possibilities exist with Aspect-Oriented programming as well. such as the "Suffix" method which calls a method AFTER the original method is called.

For more info see: http://en.wikipedia....are_development

...yup..that is wikipedia heh..

Is This A Good Question/Topic? 2
  • +

Replies To: Aspect Oriented Javascript: The "Prefix"

#2 Atspulgs  Icon User is offline

  • D.I.C Regular

Reputation: 68
  • View blog
  • Posts: 380
  • Joined: 29-July 09

Posted 04 July 2011 - 03:54 AM

Sorry x.x its way too noisy, however i think the comments are a good idea.
Could you provide clean code as well as the commented one?
Was This Post Helpful? 0
  • +
  • -

#3 Asusultra  Icon User is offline

  • New D.I.C Head
  • member icon

Reputation: 7
  • View blog
  • Posts: 39
  • Joined: 24-March 09

Posted 10 August 2011 - 04:24 AM

As per Atspulgs 's request (and most likely from here on out with tutorials/snippets and the like:

-Clean Code-

Imlementation:
function Prefix(OwnerObject, MethodName, PrefixFunc, PrefixFuncArgs) {
	var OriginalRef = OwnerObject[MethodName];
	OwnerObject[MethodName] = function prefixProxy() {
		if (typeof PrefixFuncArgs != 'undefined' && PrefixFuncArgs != null) {
			PrefixFunc.call(window, PrefixFuncArgs);
		}
		else { PrefixFunc.call(); }

		var res = OriginalRef.call(this, arguments[0]);
		return res;
	};
}



Test the "no arguments" condition in the Prefix method.:
var str = new String();

function prefixFuncNoArgs()
{
    str += "\nprefixFuncNoArgs - called";
}

function originalFunc()
{
    str += "\noriginalFunc - called";
}

Prefix(this, "originalFunc", prefixFuncNoArgs, null);

originalFunc();

alert(str);

originalFunc();

alert(str);


Was This Post Helpful? 0
  • +
  • -

#4 Dormilich  Icon User is online

  • 痛覚残留
  • member icon

Reputation: 3480
  • View blog
  • Posts: 10,032
  • Joined: 08-June 10

Posted 13 October 2011 - 04:47 AM

I’d rather call it a Decorator than a Proxy …

anyways, there is a problem in certain cases:
- if PreficFunc is not a global function (but an object’s method) its call will fail (wrong scope)
- if PreficFunc expects more then one parameter, its call will fail due to only one parameter being given. use apply() instead of call().
var args = [].slice.call(arguments, 3);
PrefixFunc.apply(window, args);

- the same applies to OriginalRef
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1