Aspect Oriented Programming without Modification of Original - javascript

So, I have seen examples on AOP in Javascript and most of them either are something like this:
var foo = somefunc.after(function() { // after is some function already made
console.log("after!");
});
foo(); // logs "after"
Like this:
var foo = function() {
console.log("something");
};
foo = (function() {
var original = foo;
return function() {
console.log("before!");
original.apply(this, arguments);
}
})();
foo(); // logs "before" then "after"
Or like this:
function Foo() {
console.log("foo");
}
var original = Foo;
Foo = function() {
original();
moreStuff();
}
function moreStuff() {
console.log("hi");
}
Foo();
// logs "foo" then "hi"
But, what want is a way that does not modify the original function and you do not have to set it to a variable. What I am looking where the you can do this:
function foo() {
console.log("foo!");
}
foo.after(function() {
console.log("after");
});
// and then
console.log(foo);
/* and it will log:
*
* function foo() {
* console.log("foo!");
* }
*
* Original function stays the same
*/
foo();
// logs "something" then "before"
Basically, when the person calls the function it uses the modified version, but when a person just receives the value of the function, foo;, it returns the original.
How would one achieve this?

Related

get function execution context

I have a function foo:
function foo() {
return 'foo';
}
While foo got executed is there a way to know if foo was called inside object declaration ? I want to distinguish these two cases:
var bar = {
prop1: foo()
}
var var1 = foo();
Here's one approach demonstrating the suggestions in the comments and assuming you'd rather call bar.prop1 instead of bar.prop1().
function foo (ctx) {
console.log(ctx == window)
return 'foo'
}
class Bar {
get prop1() {
return foo(this)
}
}
var var1 = foo(this);
var bar = new Bar();
bar.prop1;

Change function in function

I have ready code something like this and
I can't change function Foo() because it's alias framework.
function Foo(){
this.prop = {
width: 200
}
this.do = function(s1,s2){
alert(s1+s2);
}
}
I need change do function.
After function Foo() and before var foo1 = new Foo(); foo1.do(1,0); I try write
Foo.do = function(){
alert('changed');
}
I can't change do function. I used defineProperty and even constructor) I haven't prototype.
Full uncorrect demo code
function Foo(){
this.prop = {
width: 200
}
this.do = function(s1,s2){
alert(s1+s2);
}
}
Foo.do = function(){
alert('changed');
}
var foo1 = new Foo();
foo1.do(1,0);
var foo2 = new Foo();
foo2.do(1,1);
var foo3 = new Foo();
foo3.do(1,2);
I can change it for foo1, foo2 and etc. I need cange it ine time.
I'd suggest creating your own constructor that implements Foo.
function Foo() {
this.prop = {
width: 200
}
this.do = function (s1, s2) {
console.log(s1 + s2);
}
}
Foo.prototype.someMethod = function () {};
// can't change any of the above..
function MyFoo() {
Foo.call(this);
this.oldDo = this.do;
this.do = function (s1, s2, s3) {
// do something else!
console.log(s1 + s2 + s3);
}
}
MyFoo.prototype = Object.create(Foo.prototype);
// tests...
var foo = new Foo();
foo.do(2, 2, 2); // 4
console.log(foo.prop.width); // 200
var myFoo = new MyFoo();
myFoo.do(2, 2, 2); //6
console.log(myFoo.prop.width); // 200
Your new constructor only has to override the methods you want to change, the rest will stay the same and the original isn't changed. Notice how instances of MyFoo also have a .prop property even though that was done in Foo's constructor, not MyFoo.
newDo = function(){}; // your new do function
var foo1 = new Foo()'
foo1.do = newDo;
foo1.do(1,0)
and so on. If you can't change the Foo function, and you can't restrict yourself to ES6 or Firefox (they have ways to modify the prototype), then the best option is to overwrite do after creating a new Foo.
This is also a good point to plug learning the module pattern so that you can create your own nested versions of things:
function Foo() {}; //your original foo
(function() {
function Foo() {}; //your new foo with a new do method
// do stuff with the modified do here
})()

Apply Object In Function

What is the purpose of this.apply(obj); when function is invoked. For example this code.
Function.prototype.blio = function (a) {
this.hurka = 'hurka';
var obj = {};
this.apply(obj); // what exactly happens here ?
}
Let's try it out!
function foo() {
console.log(this);
}
foo(); // logs window
console.log(foo.hurka); // undefined
foo.blio(); // logs {}
console.log(foo.hurka); // "hurka"
But wait, foo.blio invoked foo!
Therefore, when invoked as foo.blio()
this in blio is foo
this.apply is equivalent to foo.apply
this inside foo was set to {} through the apply
You can read more on Function.prototype.apply on MDN docs here

How to call Parent Method from the Overriding Method in Child class

How can I access a method from a parent class that was overridden in the child class?
In My example below I want to call the bar.my_name() method inside the overriding
method in foo.my_name()
function bar() {
this.my_name = function() {
alert("I Am Bar");
}
}
function foo() {
this.my_name = function() {
alert("I Am Foo");
//access parent.my_name()
}
}
foo.prototype = Object.create(bar.prototype);
foo.prototype.constructor = foo;
var test = new foo();
test.my_name();
You could do this:
(new bar()).my_name.call(this);
I think you're a little confused about how prototypes work though, as they're not really helping you here.
This might be slightly better:
var bar = {
my_name: function () {
console.log('bar name');
}
};
var foo = Object.create(bar);
foo.my_name = function () {
console.log('foo name');
bar.my_name.call(this);
};
Or if you want to use constructors, something like this:
function Bar () {}
Bar.prototype.my_name = function () {
console.log('bar name');
};
var foo = Object.create(Bar.prototype);
foo.my_name = function () {
console.log('foo name');
bar.my_name.call(this);
};
But I'm not really sure what you're trying to do or why, so with more context it will be easier to give you better advice.
One of possible solutions is to move the method to the base class prototype.
function bar() {
}
bar.prototype.my_name = function() {
alert("I am bar");
}
function foo() {
}
foo.prototype = Object.create(bar.prototype);
foo.prototype.my_name = function() {
alert("I Am Foo");
bar.prototype.my_name.call(this);
}
foo.prototype.constructor = foo;
var test = new foo();
test.my_name();

How to get 'this' value of caller function?

If I have a function like this:
function foo(_this) {
console.log(_this);
}
function bar() {}
bar.prototype.func = function() {
foo(this);
}
var test = new bar();
test.func();
then the test instance of bar gets logged.
However, for this to work I have to pass the this in the bar.prototype.func function. I was wondering whether it is possible to obtain the same this value without passing this.
I tried using arguments.callee.caller, but this returns the prototype function itself and not the this value inside the prototype function.
Is it possible to log the test instance of bar by only calling foo() in the prototype function?
If the question is 'without passing this (by any means)' then answer is no
value can be passed by alternative methods though. For example using global var (within Bar class) or session or cookies.
function bar() {
var myThis;
function foo() {
console.log(myThis);
}
bar.prototype.func = function() {
myThis = this;
foo();
}
}
var test = new bar();
test.func();
I think calling foo within the context of bar should work:
function foo() {
console.log(this.testVal);
}
function bar() { this.testVal = 'From bar with love'; }
bar.prototype.func = function() {
foo.call(this);
}
var test = new bar();
test.func(); //=> 'From bar with love'
You can do this without changing the external function, but you must change the way you call it.
You can't get the context of the caller, but you can set the this property on a function you call with the method apply or call. See this reference for an explanation on this.
function foo()
{
console.log( this );
}
function bar()
{
bar.prototype.func = function func()
{
foo.apply( this );
};
}
var test = new bar();
test.func();
Usually if this is used, it's in an object oriented context. Trying to call a method of an object with another this might indicate poor design. Explain a bit more what you are trying to achieve for more applicable design patterns.
For an example of a javascript OOP paradigm, check my answer here.
What about this?
"use strict";
var o = {
foo : function() {
console.log(this);
}
}
function bar() {}
bar.prototype = o;
bar.prototype.constructor = bar;
bar.prototype.func = function() {
this.foo();
}
var test = new bar();
test.func();
Or this:
"use strict";
Function.prototype.extender = function( o ){
if(typeof o == 'object'){
this.prototype = o;
}else if ( typeof o == 'function' ) {
this.prototype = Object.create(o.prototype);
}else{
throw Error('Error while extending '+this.name);
}
this.prototype.constructor = this;
}
var o = {
foo : function() {
console.log(this);
}
}
function bar() {}
bar.extender(o);
bar.prototype.func = function() {
this.foo();
}
var test = new bar();
test.func();

Categories