Access javascript variables from calling scope - javascript

I am trying to define a function which can access variables which are in the scope of the function that is calling it.
( I am attempting to build a string formatter that is prettier than "a" + b, and more terse than String.format("a{0}",b). So I can get SF("a{b}"), and I don't know if it is possible )
so
function magic(str) {
return parentScope[str]; // or return eval( str );
// or something like that
}
function call() {
var a = 1;
alert( magic( "a" ) );
}
call();
would alert "1".
currently I can do this by having the function return code to be eval'd, but it seems like there must be a better way.

Just put your 'magic' function into the call function:
function call() {
function magic(str) {
return a;
}
var a = 1;
alert( magic() );
}
call();
This mechanism behind the scenes is called closures and which are very powerful concept. Just think of an AJAX request where the callback function still can access the local variables of the calling function.
UPDATE
I misunderstood your question. The thing you actually want to build is impossible to implement in JavaScript because the is no way to access the caller's scope.
UPDATE 2
Here is my string formatting function. Not as concise as you may want it, but still very usable.
String.prototype.arg = function()
{
result = this;
// This depends on mootools, a normal for loop would do the job, too
$A(arguments).each((function(arg)
{
result = result.replace("%", arg);
}).bind(this));
return result;
}
You can use it like:
"%-% %".arg(1,2).arg(3)
and receive
"1-2 3"

As far as I know it is impossible to reach out and grab an arbitrary variable from a function in javascript. From an object yes, but not from an executing method.
I can't think of any function method (apply, call, otherwise) which helps you here: frankly I think you're trying too hard for a marginal benefit over the normal string.format, er... format.

Related

Executing a method inside a method

I'm currently working on a JavaScript exercise in FreeCodeCamp, and one of the test-cases my code should work with is a function call that looks like this:
addTogether(2)(3);
here is the bare-bones function I'm given:
function addTogether() {
return;
}
When I run the code below:
function addTogether() {
return arguments;
}
In the console, that the editor provides, I get:
TypeError: addTogether(...) is not a function
The instructions hint at using the arguments object, and it works well with test-case function calls that only have one argument object (i.e. addTogether(2, 3);), but not with the one I've shown above.
Is there a way to access/utilize the separate argument objects when they're in the format I showed above?
Note: I don't want any sort of answer to solve the problem, just info on any techniques on accessing the arguments of these type of function calls.
Help, is greatly appreciated.
Don't think of it as two separate sets of arguments. Think of it as you're calling another function (which you are). Functions are first-class values in JavaScript so you can use them just like any other value. This includes returning them from functions.
var f = function(y) {
console.log('f:', y);
};
var getF = function(x) {
console.log('getF:', x);
return f;
};
getF(1)(2);
Functions can also use values that exist in any parent scope. Loosely speaking, functions which do this are called closures.
function createGetX(x) {
return function() {
// Since x is in the parent scope, we can use it here
return x;
}
}
var one = createGetX(1);
console.log(one()); // Always
console.log(one()); // returns
console.log(one()); // one
Sometimes it helps me to think in a certain order. You can read the code "addTogether(2)" and stop before reading the "(3)".
From there you can see the exercise wants you to have that first part "addTogether(2)" return a function...since anytime there are "()" that means a function is getting called.
So "addTogether(2)" needs to return a function that takes one argument. Later that 3 will be one example of an input.
I think the name "addTogether" is a bit confusing..since that function's job is to make up and return the actual function that adds.
Sort of hard to explain this one without helping too much, but the bulk of your job here is to return a custom function, which includes the first variable (from it's scope) and expects another variable when it's called.
You could do this with closures.
function addTogether(x) {
return function(y) {
return x+y;
}
}

Execute private function inside the class by its name (string)

At the moment I have simple JavaScript class like this:
function MyClass() {
// ... some code ...
this.Create = function() {
funcName = 'myTestFunc()';
cTimer = setTimeout(funcName, 1000);
}
// ... more code ...
var myTestFunc = function() {
alert ('everything\'s OK!');
}
// ... more code ...
}
and to test it I'm using this code:
x = new MyClass();
x.Create();
I have some troubles to execute this function by it's name. If I put just eval(funcName); instead of setTimeout call it works fine but can't figure out why it doesn't work this way.
Course, this is part of more complex code but rest of code is irrelevant to this problem.
My question is obvious - How to execute function by its name set as setTimeout function's argument? Is it possible?
Note: Making this function public (this.myTestFunc = ...) isn't an option!
Update:
funcName = "myTestFunc()"; is just an example. In real code it looks like funcName = getRandomEffectFunctionName();! It's just a random value.
Referring to the update:
Instead of setting:
var funcName = "getRandomEffectFunctionNeme()";
Thus, setting a reference to the function's name you should do
var funcRef = getRandomEffectFunctionNeme;
And set a reference to the function itself . Not only this avoids the issues setTimeout with strings has*. It also solves your closure issue since your code is structured in such a way the timeout has access to the function itself.
In your case, let's assume you have some functions that are filters, for example lowPass highPass and blur. In that case, instead of choosing a function name we would be choosing a function.
First, we store these functions in an array:
var filters = [lowPass,highPass,blur];
In JavaScript, functions are first-class objects, you can pass them around just like other objects.
Next, we'll get a random number
var chosen = Math.floor(Math.random()*3);//get a random number between 0 and 2
Finally, we'll choose the filter and invoke it
var filter = filters[chosen];
setTimeout(filter,1000);
( * just try debugging it, it basically invokes the compiler whenever ran and is painfully slow)
You just pass a function to setTimeout as a parameter, rather then a string, setTimeout(myTestFunc,1000) .
When calling Create it would have access to it anyway because they are in the same closure.
NOTE: This solution is only applicable if you can not pass the function name as a function reference, for example if you're integrating with code that is outside your control. Generally, when possible, you should pass a function reference since in JavaScript, all functions are objects.
Assuming that the timeout and the function are in the same closure your code is pretty close. The problem is that your eval call executes in the global context because it is in a timer. This means they are no longer in the same lexical scope.
You can however, grab a reference to the function by clever use of eval which you can later call in the setTimeout invocation.
var F=eval(funcName);// gain a reference to the function given the function's name
cTimer = setTimeout(F, 1000);
If you're using AIR or don't trust the functionName string you can do the following:
function Test(){
var functionContainer={
t:function(){
console.log("it's t");
}
};
this.callT=function(functionName){
var F=functionContainer[functionName];
console.log("F is:",F);
setTimeout(F,500);
}
}
(new Test()).call("t");
This is preferable since you are invoking setTimeout with a function's name and not a string. In general, using setTimeout with a string can have issues, it's hard to debug or maintain.

() right after a function means the function is going to get fired immediately? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What do empty parentheses () after a function declaration do in javascript?
I am looking at some Javascript code and trying to figure out what }(); right after return num+10 means. Does that mean the function will get executed immediately? Where can I get more information about this.
function addToTen(num) {
return function() {
return num+10;
}();
}
addToTen(5); // 15
Thanks,
Venn.
Yes, but only if it's a function expression, which is different from a function declaration. A function declaration is how your first function is defined:
function foo(){
}
If you add () after this, you get a Syntax Error. If the function is defined as a function expression, adding a set of parenthesis immediately executes it. Functions are expressions whenever they are not defined as above, e.g.:
(function(){}());
var x = function(){}();
return function(){}();
Your actual example is just... odd, and pointless. It's almost a classic closure example, something like:
function addTo(x){
return function(y){
return x + y;
}
}
var addToTen = addTo(10);
addToTen(5); // 15;
but your actual example is equivalent to just:
function addToTen(num){
return num + 10;
}
and all the extra stuff is completely unnecessary.
Yes, it means the function object is evaluated.
Just like with any other function, you have two ways of looking at it:
var myFunction = function(val) {
return val + 1;
}
To return the function object, or send it somewhere else, I just say myFunction
If I wish to execute it, I say myFunction()
In this closure or decorator, whatever, that you've described above, rather than return the function object itself, you're returning the value of executing that function immediately, hence the () afterwards.
Yes, it's executed immediately, but the usage doesn't make any sense in this example.
Often used for anonymous functions creating a closure.
see Why do you need to invoke an anonymous function on the same line?
One place where I use it a lot:
(function($) {
// secure way to ensure no conflict between $ (jQuery)
// and another js-framework can happen
$...
})(jQuery);

javascript class problem

Examine this code
var _class=function()
{
this.Test=100;
this.Callback=function(msg)
{
alert(msg+"\r\n"+this.Test);
}
}
function run(call)
{
call("Hello world");
}
var obj=new _class();
run(obj.Callback);
I got the result :
[Alert]
Hello world
undefined
but when i call
obj.Callback("Hello world")
i got expected
[Alert]
Hello world
100
why ?
thank for help
There's no intrinsic relationship between an object and the functions defined "inside" it. The only thing that determines the value of this (called the "receiving" object) in a function call is the way in which the function is called.
Call a function with object.func(), and this will be bound to object.
Call a function with "call()" or "apply()", and this is determined by the first parameter.
If a function is called without any implicit object context, however, as in your "callback" example, then this won't refer to anything your object — it will refer to window (or whatever the global context is).
The trick is that when you want to use a function as if it were a "method" on an object, such that the relationship remains intact even though the function reference has been yanked away from the object, you can pre-bind this in a couple of ways:
You can wrap the function in another function, so that you explicitly retain this in a closure.
You can use ".bind()" to (essentially) do the same thing.
The first way would look like this:
run(function() { obj.Callback(); });
The second way would look like this:
run(obj.Callback.bind(obj));
JavaScript is quite different from languages like C# or Java in this respect. In those languages, a function is sort-of stuck forever in a relationship with its class (or instances of its class). Not JavaScript; it really doesn't matter at all, in fact, where a function is defined. Your "_class" function would be equivalent if it were written like this:
function helloThere() {
alert(msg + "\r\n" + this.Test);
}
var _class = function() {
this.Test = 100;
this.Callback = helloThere;
};
edit — #jamietre correctly notes that had your "_class" function contained some var declarations or local functions, then there most certainly would be a difference (though not with respect to the way this behaves when "Callback" is invoked).
edit again — Thanks #Koolinc
this.Test is not defined. The scope of this in that context is the callback function.
This is a quick fix:
var _class=function()
{
var self = this;
this.Test=100;
this.Callback=function(msg)
{
console.log(msg+"\r\n"+self.Test);
}
}

Declaring functions in JavaScript [duplicate]

This question already has answers here:
var functionName = function() {} vs function functionName() {}
(41 answers)
Closed last year.
What's the difference between these two ways of declaring a function?
function someFunc() { ... }
var someFunc = function() { ... }
I'm not asking in the technical sense. I'm not asking which is better for readability, or which style is preferred.
I am on different opinion with most of the people here. Technically this syntax may mean the same for declaring functions both ways
(I stand incorrect on my last statement. I read up on a diff post why they are technically diff and I'll add in the end, why)
; but the way they play a role in evolving patterns is massive. I would highly recommend "Javascript: The Good Parts" by Doughlas Crockford.
But to prove my point in a subtle and a simple manner; here is a small example.
//Global function existing to serve everyone
function swearOutLoud(swearWord) {
alert("You "+ swearWord);
}
//global functions' territory ends here
//here is mr. spongebob. He is very passionate about his objects; but he's a bit rude.
var spongeBob = {
name : "squarePants",
swear : function(swearWord) {
name = "spongy";
alert("You "+ swearWord);
return this;
}
}
//finally spongebob learns good manners too. EVOLUTION!
spongeBob.apologize = function() {
alert("Hey " + this.name + ", I'm sorry man!");
return this;
}
//Ask spongebob to swear and then apologize in one go (CASCADING EFFECT!!)
alert(spongeBob.swear("twit").apologize());
if you look at the code above I declared a function with a name swearOutLoud. Which would take a swear word from any object or a call and will give you the output. It can do operations on any object using the "this" parameter that is passed to it and the arguments.
However second declaration is declared as an attribute of object called "spongeBob". This is important to note; as here I am moving towards an object driven behavior. While I am also maintaining "cascading effect" as I return "this" if i have nothing else to return.
Somthing similar is done in jquery; and this cascading pattern is important if you are trying to write a framework or something. You'll link it to Builder design pattern also.
But with functions declared as an attributes of an object I am able to achieve an object centric behavior which leads to a better programming paradigm. Unless designed well; individual functions declared outside with global access lead to a non-object oriented way of coding. I somehow prefer the latter.
To see cascading in effect, look at the last statement where you can ask spongebob to swear and apologize at once; even though apologize was added as an attribute later on.
I hope I make my point clear. The difference from a technical perspective may be small; but from design and code evolution perspective it's huge and makes a world of a difference.
But thats just me! Take it or leave it. :)
EDIT:
So both the calls are technically different; because a named declaration is tied to global namespace and is defined at parse time. So can be called even before the function is declared.
//success
swearOutLoud("Damn");
function swearOutLoud(swearWord) {
alert("You " + swearWord)
}
Above code will work properly. But code below will not.
swear("Damn!");
var swear = function(swearWord) {
console.log(swearWord);
}
One advantage of using function someFunc() { ... } is that the function name appears in Firebug debugger. Functions that are declared the other way (var someFunc = function() { ... }) come up as anonymous.
Actually, the difference is that the second declaration gives us the ability to declare functions like this making it possible to have a function as a property for an object :
var myObject=new Object();
myObject.someFunc=function() { ... };
Style wise the second example is more consistent with other common ways to declare functions and therefore it could be argued that it is more readable
this.someFunc = function() { ... }
...
someFunc: function() { ... },
However, as also mentioned it's anonymous and therefore the name does not appear when profiling.
Another way to declare the function is as follows which gets you the best of both worlds
var someFunc = function someFunc() { ... }
Another difference is that, on most browsers, the latter allows you to define different implementations depending on circumstances, while the former won't. Say you wanted cross-browser event subscription. If you tried to define a addEventListenerTo function thusly:
if (document.addEventListener) {
function addEventListenerTo(target, event, listener) {
....
}
} else if (document.attachEvent) {
function addEventListenerTo(target, event, listener) {
....
}
} else {
function addEventListenerTo(target, event, listener) {
....
}
}
on some browsers, all the functions end up being parsed, with the last one taking precedence. Result: the above just doesn't work. Assigning anonymous functions to variables, however, will work. You can also apply functional and basic aspect oriented programming techniques using anonymous functions assigned to variables.
var fib = memoize(function (n) {
if (n < 0) return 0;
if (n < 2) return 1;
return fib(n-1) + fib(n-2);
});
...
// patch the $ library function
if (...) {
$ = around($, fixArg, fixResult);
}
It is both true that the first form:
function test() { }
is a more recognized syntax and that the second form:
var test = function() { ... }
allows you to control the scope of the function (through the use of var; without it, it would be global anyway).
And you can even do both:
var test = function test() { ... test(); ... }
This allows you to define a recursive function in the second form.
For readability, I'd say the first is clearly better. A future maintenance programmer, even assuming they're familiar enough with javascript to know many of the finer points coming up in this thread, are going to assume the first format.
For example, if they should some day want to ctrl-f to search for the definition of your function to see what's happening in there, are they going to first search for someFunc = function() or function someFunc()?
Also, to get downright typographical about it (since we're talking readablity) readers are often scanning the text quickly, and would be more inclined to skip over a line that starts with "var" if they're looking for a function definition.
I know this is a non-technical answer, but it's harder for humans to read code than computers.
When you write
function Test() {
}
JavaScript is really creating a property to which it assigns the function object that once called will execute the code reported in the function definition. The property is attached to the object window, or to the object that contains the function definition.

Categories

Resources