By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,183 Members | 1,311 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,183 IT Pros & Developers. It's quick & easy.

Injecting local variable to a function - Can it be done?

P: n/a
tai
Hi.

I'm looking for a way to define a function that's only effective inside
specified function.

Featurewise, here's what I want to do:

bar_plugin_func = function() { ...; setTimeout(...); ... };
wrap_func(bar_plugin_func);
bar_plugin_func(); // calls custom "setTimeout"

So while plugin developer thinks s/he's calling top-level function,
I want to hook it by somehow injecting local variable with the same
name.

Simply doing something like

;(function() { setTimeout = function() { ...my custom implementation
})();

is not ideal, as that'll taint global scope. Actually, I can live with
that for now,
but it's my technical interest to find a way to define it locally.
>From the quote in following reference, it says:
- http://www.unix.org.ua/orelly/web/jscript/ch11_05.html
Variable Scope
We saw above that top-level variables are implemented as properties of the current window
or frame object. In Chapter 6, Functions, we saw that local variables in a function are
implemented as transient properties of the function object itself.
So how can I manipulate "transient properties of the function object
itself"?

Thanks in advance.

Nov 17 '06 #1
Share this Question
Share on Google+
9 Replies


P: n/a

tai wrote:
Hi.

I'm looking for a way to define a function that's only effective inside
specified function.

Featurewise, here's what I want to do:

bar_plugin_func = function() { ...; setTimeout(...); ... };
wrap_func(bar_plugin_func);
bar_plugin_func(); // calls custom "setTimeout"

So while plugin developer thinks s/he's calling top-level function,
I want to hook it by somehow injecting local variable with the same
name.

Simply doing something like

;(function() { setTimeout = function() { ...my custom implementation
})();

is not ideal, as that'll taint global scope. Actually, I can live with
that for now,
but it's my technical interest to find a way to define it locally.
From the quote in following reference, it says:

- http://www.unix.org.ua/orelly/web/jscript/ch11_05.html
Variable Scope
We saw above that top-level variables are implemented as properties of the current window
or frame object. In Chapter 6, Functions, we saw that local variables in a function are
implemented as transient properties of the function object itself.

So how can I manipulate "transient properties of the function object
itself"?

Thanks in advance.
I can't really tell what you want to do from this post. It looks like
you're trying to program JS using some other language's syntax.

Is this this sort of thing you had in mind?

function bar_plugin_func() {
setTimeout(function() {
// logic goes here
}, 1000);
}

Google function closures. You'll find

http://www.jibbering.com/faq/faq_notes/closures.html

written by our very own Richard Cornford.

Perhaps though all you want is a local function. In JS, a function has
scrope, can be assigned, and is generally treated just like any other
variable.

Perhaps some more clarification would be in order?

Nov 17 '06 #2

P: n/a
tai
Perhaps some more clarification would be in order?

OK...let me try again.

I'm currently developing a JS-based framework that handles
user-registered functions. Just before executing these registered
functions, the framework redefines, or newly defines several
"top-level" methods to coordinate interaction between each
registered functions. So it's not limited to "setTimeout" method only.

Here's somewhat different, but more concrete example.
One of my framework components is FSM (finite state machine)
class, and it can be used in following manner:

var func0 = function func0(arg) { alert("func0"); goto(func2);
alert("notreached") };
var func1 = function func1(arg) { alert("func1"); goto(-1) };
var func2 = function func2(arg) { alert("func2"); goto(-1, true) };

var sm = new StateMachine(func0, func1, func2);
sm.start(func0, arg); // alerts in order of: func0, func2, func1

In above example, the framework defines "goto" method, which
cause a immediate transition to specified state. And this is
where my initial question comes in.

To provide "goto" or any other external functions, I currently
add them to global scope. However, I feel that's an overkill -
these just need to be effective in registered functions. I want
to use them as if they are "top-level", but I also want global
namespace kept clean.

I know JS's scoping rule will make any attempt void once these
registered functions do a nested function call (which resets
scope chain). However, how about directly inside these registered
functions? Is it possible to re-define top-level functions just
directly inside these (= func0, func1, func2) registered methods?
Featurewise, here's what I want to do:

bar_plugin_func = function() { ...; setTimeout(...); ... };
wrap_func(bar_plugin_func);
bar_plugin_func(); // calls custom "setTimeout"

So while plugin developer thinks s/he's calling top-level function,
I want to hook it by somehow injecting local variable with the same
name.

Simply doing something like

;(function() { setTimeout = function() { ...my custom implementation
})();

is not ideal, as that'll taint global scope. Actually, I can live with
that for now, but it's my technical interest to find a way to define it locally.
Nov 18 '06 #3

P: n/a
VK
I know JS's scoping rule will make any attempt void once these
registered functions do a nested function call (which resets
scope chain). However, how about directly inside these registered
functions? Is it possible to re-define top-level functions just
directly inside these (= func0, func1, func2) registered methods?
Other words, is it possible to re-compile run-time the execution
context? Actually JavaScript is one of few programming languages (if
not the single one at all) that allows you to do such things, but for
that you have of course to abandon the idea of working with the
compiled code itself and use new Function(strSource) instead.

By carefully tweaking and a bit memory leaking :-) you can emulate
Perl-like local scope for a set of function (var visible in this
function and all functions called from within this function). But
AFAICT it doesn't help in your situation because you want the effect
for *any* random function sent to the constructor.

Nov 18 '06 #4

P: n/a

tai wrote:
Perhaps some more clarification would be in order?

OK...let me try again.

I'm currently developing a JS-based framework that handles
user-registered functions. Just before executing these registered
functions, the framework redefines, or newly defines several
"top-level" methods to coordinate interaction between each
registered functions. So it's not limited to "setTimeout" method only.

Here's somewhat different, but more concrete example.
One of my framework components is FSM (finite state machine)
class, and it can be used in following manner:

var func0 = function func0(arg) { alert("func0"); goto(func2);
alert("notreached") };
var func1 = function func1(arg) { alert("func1"); goto(-1) };
var func2 = function func2(arg) { alert("func2"); goto(-1, true) };

var sm = new StateMachine(func0, func1, func2);
sm.start(func0, arg); // alerts in order of: func0, func2, func1

In above example, the framework defines "goto" method, which
cause a immediate transition to specified state. And this is
where my initial question comes in.

To provide "goto" or any other external functions, I currently
add them to global scope. However, I feel that's an overkill -
these just need to be effective in registered functions. I want
to use them as if they are "top-level", but I also want global
namespace kept clean.

I know JS's scoping rule will make any attempt void once these
registered functions do a nested function call (which resets
scope chain). However, how about directly inside these registered
functions? Is it possible to re-define top-level functions just
directly inside these (= func0, func1, func2) registered methods?
Hm, this is a distinctly non-JavaScript way of going about things,
which leads me to think that you're experience in a different language
(Java, perhaps?) and are trying out techniques that may be appropriate
in a different language but are quite non-idiomatic to JavaScript.

For starters, "goto" is a reserved keyword, so you'll need a different
name for your function there.
var func0 = function func0(arg) { alert("func0"); goto(func2);
alert("notreached") };
var func1 = function func1(arg) { alert("func1"); goto(-1) };
var func2 = function func2(arg) { alert("func2"); goto(-1, true) };

var sm = new StateMachine(func0, func1, func2);
sm.start(func0, arg); // alerts in order of: func0, func2, func1

I would do this (if I understand you correctly) like so:

function StateMachine() {
// assumes all arguments are callable as functions -
// in real life you'll want to verify this
this.funcs = arguments;
}
StateMachine.prototype.callFunc = function(args) {
var num = -1;
if (args.length && args.length >= 1) {
num = args[0];
args = args[1];
}
if (num >= 0) {
this.callFunc(this.funcs[num](args));
}
}

// You can either pass in the functions as anonymous like so,
// or first define some functions and pass them in by name
var sm = new StateMachine(function() {
alert(1);
// return value determines next function to be called
// you can also have some logic here to decide what
// that should be
return [2];
},
function(arg) {
alert(arg);
return [-1];
},
function() {
alert(3);
return [1, 'howdy!'];
});

// then you call the number you want to start with as first item in an
array
// if you want multiple args you can pass those as a nested array
// remember in JS you can mix types in a single array
sm.callFunc([0]);

Nov 18 '06 #5

P: n/a
tai
Hmm...maybe some clever use of "eval" might solve this problem.
Say there's a method like

var replacements = { needtrap: function() { ... } };
var func0 = function() { needtrap() };

What I want to do is something like

with (replacements) { // install intercepting scope
func0();
}

Of course this won't work because scope chain gets reset when calling
func0 method. But with eval, maybe I can redefine it dynamically to

var func0 = function() { with (replacements) { func0 } };

But evaling function definition has a issue of "free"ing a binding to a
local scope at the time of initial definition. So I guess the real
solution
is to redefine it as

var func0 = function() {
with (original_func0_scope) { // preserve original scope at the
time of initial definition
with (replacements) { // install intercepting scope
// "needtrap" will be intercepted, bu others will work as
originally defined
func0;
}
}
};

which I'm not sure if it's possible or not.

Maybe I need to require registering functions to provide an API to
return such information (original_func0_scope = func0.get_scope()) ,
or just go with global override.
I know JS's scoping rule will make any attempt void once these
registered functions do a nested function call (which resets
scope chain). However, how about directly inside these registered
functions? Is it possible to re-define top-level functions just
directly inside these (= func0, func1, func2) registered methods?

Other words, is it possible to re-compile run-time the execution
context? Actually JavaScript is one of few programming languages (if
not the single one at all) that allows you to do such things, but for
that you have of course to abandon the idea of working with the
compiled code itself and use new Function(strSource) instead.

By carefully tweaking and a bit memory leaking :-) you can emulate
Perl-like local scope for a set of function (var visible in this
function and all functions called from within this function). But
AFAICT it doesn't help in your situation because you want the effect
for *any* random function sent to the constructor.
Nov 19 '06 #6

P: n/a
tai
For starters, "goto" is a reserved keyword, so you'll need a different
name for your function there.
Thanks, I simply thought "goto" was OK as JS does not have "goto" and
IE JScript accepted it - I'll change that.
Hm, this is a distinctly non-JavaScript way of going about things,
which leads me to think that you're experience in a different language
(Java, perhaps?) and are trying out techniques that may be appropriate
in a different language but are quite non-idiomatic to JavaScript.
Close, but not really. For FSM, I first started with something similar
to your example, but following two goals drove me to this state:

1. I wanted the use of this framework straightforward and transparent
2. Asynchronous operation support (like XmlHttpRequest)

For goal #1, I wanted to keep registering function look clean as
possible so they would not depend too much on this framework.
This helps porting/reusing existing functions.

And due to goal #2, I had to abandon use of "return <next>;" way
to initiate state shift - thus introduction of "goto". This is somewhat
off-topic, but things start to look interesting when you think about
integrating async op like below into FSM:

var func0 = function() {
var img = new Image(); img.src = "..."; img.onload = function() {
.... }; ...;
}
...
var sm = new StateMachine(func0, func1, ...);
sm.start(func0, arg);

But I must agree this is "quite non-idiomatic to JavaScript" like
you said, as this implementation was really tricky. OTOH, I think
I'm getting close to establishing goal #1.
var func0 = function func0(arg) { alert("func0"); goto(func2);
alert("notreached") };
var func1 = function func1(arg) { alert("func1"); goto(-1) };
var func2 = function func2(arg) { alert("func2"); goto(-1, true) };

var sm = new StateMachine(func0, func1, func2);
sm.start(func0, arg); // alerts in order of: func0, func2, func1


I would do this (if I understand you correctly) like so:

function StateMachine() {
// assumes all arguments are callable as functions -
// in real life you'll want to verify this
this.funcs = arguments;
}
StateMachine.prototype.callFunc = function(args) {
var num = -1;
if (args.length && args.length >= 1) {
num = args[0];
args = args[1];
}
if (num >= 0) {
this.callFunc(this.funcs[num](args));
}
}

// You can either pass in the functions as anonymous like so,
// or first define some functions and pass them in by name
var sm = new StateMachine(function() {
alert(1);
// return value determines next function to be called
// you can also have some logic here to decide what
// that should be
return [2];
},
function(arg) {
alert(arg);
return [-1];
},
function() {
alert(3);
return [1, 'howdy!'];
});

// then you call the number you want to start with as first item in an
array
// if you want multiple args you can pass those as a nested array
// remember in JS you can mix types in a single array
sm.callFunc([0]);
Nov 19 '06 #7

P: n/a

tai wrote:
For starters, "goto" is a reserved keyword, so you'll need a different
name for your function there.

Thanks, I simply thought "goto" was OK as JS does not have "goto" and
IE JScript accepted it - I'll change that.
Hm, this is a distinctly non-JavaScript way of going about things,
which leads me to think that you're experience in a different language
(Java, perhaps?) and are trying out techniques that may be appropriate
in a different language but are quite non-idiomatic to JavaScript.

Close, but not really. For FSM, I first started with something similar
to your example, but following two goals drove me to this state:

1. I wanted the use of this framework straightforward and transparent
2. Asynchronous operation support (like XmlHttpRequest)

For goal #1, I wanted to keep registering function look clean as
possible so they would not depend too much on this framework.
This helps porting/reusing existing functions.
Sure. Then send add your functions to the constructor and add internal
wrappers instead of explicit external wrappers:

function FSM() {
this.funcs = arguments;
}

FSM.prototype.callFunc = function(num) {
switch (this.funcs[num]) {
case 0: return this.callFunc(3);
case 1: return this.callFunc(2);
// or whatever
default: return;
}
}

my question is: how are you going to determine the proper (Markovian)
sequence of functions, without some return value from the functions?
Will it be hardcoded? Or will it be passed in as an argument?
>
And due to goal #2, I had to abandon use of "return <next>;" way
to initiate state shift - thus introduction of "goto". This is somewhat
off-topic, but things start to look interesting when you think about
integrating async op like below into FSM:

var func0 = function() {
var img = new Image(); img.src = "..."; img.onload = function() {
... }; ...;
}
...
var sm = new StateMachine(func0, func1, ...);
sm.start(func0, arg);
The proper way to handle async stuff is just to put a callback at the
end of your onload/onreadystatechange handler, and "break out" of the
state machine in your calling function. It really doesn't change the
logic in any way with this problem.
But I must agree this is "quite non-idiomatic to JavaScript" like
you said, as this implementation was really tricky. OTOH, I think
I'm getting close to establishing goal #1.
I would still like to know more about this problem:

- what do these functions do (in general)?
- is their return value used for anything?
- are they generally going to need arguments, and if so, where will
they get them from within your FSM?
- how are they going to know about each other & which one to call next?

So you will need an API after all, and you're going to need to define
some parameters here, otherwise we can't help you. It seems your
problem here is not with the JavaScript language, but with clearly and
sufficiently defining the domain and parameters of your particular
problem. But it sounds interesting and I would like to know where
you're going with this and what problem it is you've decided to tackle
this way (unless you're just doing it for fun).

Nov 19 '06 #8

P: n/a
VK

tai wrote:
Hmm...maybe some clever use of "eval" might solve this problem.
Say there's a method like

var replacements = { needtrap: function() { ... } };
var func0 = function() { needtrap() };

What I want to do is something like

with (replacements) { // install intercepting scope
func0();
}

Of course this won't work because scope chain gets reset when calling
func0 method. But with eval, maybe I can redefine it dynamically to

var func0 = function() { with (replacements) { func0 } };
I am still not sure if I got right the architecture you are willing to
achieve, so sorry if a useless advise below.

Unless you need to run your code in JScript.NET compiled with /quick -
unless that you can always augment the function object:

<script type="text/javascript">
function CallDispatcher() {
for (var i=0; i<arguments.length; ++i) {
if (typeof arguments[i] == 'function') {
arguments[i]['$goto'] = new Function('window.alert('+i+');');
arguments[i]();
}
}
}

function f1() {
if (f1.$goto) {
f1.$goto();
}
}

function f2() {
if (f2.$goto) {
f2.$goto();
}
}

function f3() {
if (f3.$goto) {
f3.$goto();
}
}
function init(arg) {
CallDispatcher(f2,f3,f1);
}

window.onload = init;
</script>
>From the other side (as other poster pointed out) it looks like you are
brute force trying to emplement a structure of one language into all
another language. Usually it doesn't work or it leads to ugly and
unstable solutions. Maybe instead of code samples it would be more
helpful to see the block-schema you want to implement: so some standard
OOP solution could be suggested.

Nov 19 '06 #9

P: n/a
tai wrote:
>Simply doing something like

;(function() { setTimeout = function() { ...my custom implementation
})();

is not ideal, as that'll taint global scope. Actually, I can live with
that for now,
but it's my technical interest to find a way to define it locally.
make setTimeout a (local) var?

var setTimeout = function () { .... };

--
Bart.
Nov 19 '06 #10

This discussion thread is closed

Replies have been disabled for this discussion.