Any way to get the currently executing function object in javascript? - javascript

Is there any way to refer to the function object that you're currently executing in? If it's not a method of any object or not called with .call() or .apply(), the this pointer is likely just window, not the function object.
I often use a design pattern like this for global variables that I want scoped to a particular function as this keeps them out of the top level namespace:
function generateRandom() {
if (!generateRandom.prevNums) {
generateRandom.prevNums = {}; // generateRandom.prevNums is a global variable
}
var random;
do {
random = Math.floor((Math.random() * (99999999 - 10000000 + 1)) + 10000000);
} while (generateRandom.prevNums[random])
generateRandom.prevNums[random] = true;
return(random.toString());
}
But, I'd rather not have to spell out the function name every time I want to use a variable scoped to that object. If the name of the function ever changes, there are then a lot of places to change the name.
Is there any way to get the currently executing function object?

Well, you could use arguments.callee()...
https://developer.mozilla.org/en/JavaScript/Reference/Functions_and_function_scope/arguments/callee
From MDN:
Description
callee is a property of the arguments object. It can be used to refer
to the currently executing function inside the function body of that
function. This is for example useful when you don't know the name of
this function, which is for example the case with anonymous functions.
Note: You should avoid using arguments.callee() and just give every
function (expression) a name.
BUT...
What you really want are Javascript Prototypes.
function RandomSomethingGenerator()
{
this.prevNums = {};
}
RandomSomethingGenerator.prototype.generate = function() {
var random;
do {
random = Math.floor((Math.random() * (99999999 - 10000000 + 1)) + 10000000);
} while (this.prevNums[random])
this.prevNums[random] = true;
return(random.toString());
};
Why do I say this?
1.) You're dirtying the global space with all those functions.
2.) Even if you like Jani's suggestion, and you want a "static" function like you have now, my suggestion would be the same, but with a twist: Create your global function, and wrap an instance of an object (built from a prototype) inside the closure and make the call to it (so, basically, make yourself a singleton).
As in this (adapted from Jani's answer):
var randomSomething = (function() {
var randomSomethingGenerator = new RandomSomethingGenerator();
return function() {
randomSomethingGenerator.generate();
};
})();

I don't think there's any way to do exactly what you ask, but you could use a closure for your function-local static variables instead.
You can easily achieve this using an IIFE:
var generateRandom = (function() {
//any function's static variables go here
var prevNums = {};
return function() {
//function code goes here
var random;
do {
random = Math....
}
prevNums[random] = true;
return random.toString();
};
})();

You want arguments.callee. From MDN - callee:
callee is a property of the arguments object. It can be used to refer to the currently executing function inside the function body of that function. This is for example useful when you don't know the name of this function, which is for example the case with anonymous functions.
For example:
> foo = function() { console.log(arguments.callee); };
> bar = function() { foo() };
> bar();
function () { console.log(arguments.callee) }
However, I think this is being deprecated. The above link says, "The 5th edition of ECMAScript forbids use of arguments.callee() in strict mode."

Related

What is the advantage of using call method instead of passing an object in the parameter

In the below code, which one is the right and how these two are different
Using call method
var obj = {
num: 10
};
var add = function(a) {
return this.num + a
}
console.log(add.call(obj,4))
Passing object in parameter
var obj = {
num: 10
};
var add = function(obj,a) {
return obj.num + a
}
console.log(add(obj,4))
Your second code block is just a regular function. The first one however is a bit more tricky. So the question is basically:
When to work with context in javascript?
In javascript, the term context basically means this. It is usually used when you call a method of an object, so that you can refer to the object. That's one of the core concepts of OOP, were we only define a function once inside the prototype, and every object of that class which inherits from it exposes this method, it won't work without context. So that's what this was invented for. However there are some cases, were context is useful without inheritance. E.g. Eventhandlers are usually contextless, as they are not part of any object:
window.addEventListener("load", function(evt){
const el = evt.target;
};
However as it is an Eventhandler of window, wouldn't it make sense that it is executed in the context of window? If you now say "YES", then you (will) probably love JS:
window.addEventListener("load", function(){
this.document.body.innerHTML = "Dynamic context can be cool!";
});
So in JS this is the way of refering to the object, the function refers to. Through Function.prototype.call we can make use of this everywhere. However that does not mean that we should use it everywhere. this should stay in the sense of context, as using it somewhere else will create confusion / uglify your code / make your code buggy.
var add = function(a) {
return this.num + a;
}
In your codesnippet i think its unclear what thisrefers to. So its rather a misuse of this. However it could get a meaning if you make it a method of obj, so its context becomes clear from the code:
const num = {
value:10,
add(a){ return this.value + a }
};
It gets even more beautiful if you use inheritance to make it reusable:
class CustomNumber {
constructor(n = 0){
this.value = n;
}
add(a){ return this.value + a; }
}
const num = new CustomNumber(10);

Is it possible to change scope of function after new Function()?

So I have this code:
function fn(a){
var f=(new Function("return a"));
return f();
}
fn(7)//ReferenceError: a is not defined
Same problems with local variables:
function fn(){
var a=7;
var f=new Function("return a");
return f();
}
fn(7)//ReferenceError: a is not defined
I want it to return a but the new function cant see a,
it can only see global a
var a=1;
function fn(a){
var f=(new Function("return a"));
return f();
}
fn(7)//1
With the normal initialization the function can see the argument.
function fn(a){
var f=function(){return a};
return f();
}
fn(7)//7
I need to call the basic constructor in my project and can't use global variables.
I know that i could solve this by giving arguments to the newly created function and call it with that like this:
function fn(a){
var f=(new Function('a',"return a"));
return f(a);
}
fn(7)//7
And also could use some parsing function and some stupidly long method to make incoming arguments reachable like this:
function parsargs(funct){
//some parsing methodes giving back argument name list from funct.toString()
return "['a','b']";//like this
}
function fn(a,b){
var arrgstr,retfunc;
arrgstr="";
for(var i in arguments)
{
if(i<arguments.length-1)
arrgstr+=arguments[i]+",";
else
arrgstr+=arguments[i];
}
//return arrgstr;
retfunc="var f=new Function("+parsargs()+",'return b*a');return f("+arrgstr+")";
return (new Function(retfunc))();
}
fn(7,4)//28
But there must be an easier way which reaches local variables and functions as well...
Any suggestions?
PS:
i am trying to replace eval() in the project
Here is a simplified version of my original problem:
fiddle
The answer is NO...
Your exact question isn't clear but, supposing you can use arguments.callee (i.e. non strict mode) and that you want to be able to have any arguments name in fn, you "may" do this:
function fn(a,b){
var strargs = arguments.callee.toString().match(/\(([^\)]*)\)/)[1];
return (new Function(strargs.split(","),"return a+b")).apply(null,arguments);
}
console.log(fn(7, 3)) // 10
But I have a strong feeling this is a XY question and that we could have given a more useful answer knowing the real original problem to solve.
You could call your new Function with a context that references the local variables that you need:
function f(a) {
var b = 30;
return new Function("return this.a + this.b").call({ a: a, b: b })
}
f(10) // 40
The reason why this isn't working as easy as you would like is that JavaScript doesn't blindly put variables in a scope. Instead, it parses the function body (as good as it can) and determines which variables the code will need. It will then look up the variables in the outer scopes, create references for them and attach those references to the new function. That's what keeps variables from the outer scope accessible inside of the function when it eventually will be executed.
You want to build a function from a string body. JavaScript can't tell which variables the body will use and hence, it won't make those variables available.
To make it work for function arguments, use apply()::
function fn(a){
var argref = arguments; // create reference to the arguments of fn() and hence to a or any other arguments
var func = new Function("return arguments[0]");
var wrapper = function() {
return func.apply(null, argref);
};
return wrapper;
}
Note that you still can't reference arguments by name since the code never specifies what the names of the arguments of func are - JavaScript can't magically read you mind and do what you want. If you want to access the arguments by name, you need to tell the interpreter the names.
This question has some code how to determine the names from a function reference: How to get function parameter names/values dynamically from javascript
I don't see a way to make local variables available without passing them to fn() as arguments. Even if you used them inside of fn(), they would be out of scope when func() is eventually executed.
A simple solution would be to pass an object to fn():
function fn(conf) {
var func = new Function('conf', "return conf.a");
var wrapper = function(conf) {
return func.apply(null, conf);
};
return wrapper;
}
fn({a:7});
new Function doesn't create a closure context, but eval does.
Here's a low-tech way to build a function with an arbitrary evaluated body and access to the calling scope:
function f(a) {
return eval("(function() { return a })")()
}
f(10) // 10

Calling a javascript function within a function

I have seen javascript something like this
var Gallery = function () {
var helloworld1 = function () {
alert('hey1');
}
var helloworld2 = function () {
alert('hey2');
}
var helloworld3 = function () {
alert('hey3');
}
}();
How would I call the helloworlds within this javascript file?
I've tried
helloworld1();
Gallery.helloworld1();
Gallery().helloworld1();
But they don't seem to work.
Also, are there any reasons why I should be writing my javascript in the above manner, rather than just using
function helloworld() {
alert('hey1');
}
Perhaps you want
var Gallery = {
helloworld1: function () {
alert('hey1');
},
helloworld2: function () {
alert('hey2');
},
helloworld3: function () {
alert('hey3');
}
};
Gallery.helloworld2();
or
var Gallery = function () {
this.helloworld1 = function () {
alert('hey1');
}
this.helloworld2 = function () {
alert('hey2');
}
this.helloworld3 = function () {
alert('hey3');
}
};
new Gallery().helloworld2();
Also, are there any reasons why I should be writing my javascript in the above manner?
It namespaces the functions. Everything to do with galleries is in the Gallery object.
Symbols declared in a function are only visible within that function (and inside other functions defined within it. That goes for symbols declared with var and function equally. Thus, in your first example, you cannot access those functions from outside the outer function.
Functions can be "exported" by having the outer container function return an object, with the functions as property values.
As to whether functions should be declared with function or var, it's a matter of personal style. I (personally) like function, but I know of many seriously talented JavaScript programmers who use var initializations.
About your 1st Question. What actually is happening that the variable Gallery is being assigned the value that your function is returning, which is basically undefined.
You are not able to do Gallery.helloworld() because .. Gallery is undefined.
The helloworld1() is not working as it would look for a helloworld1 function on the global object which is not defined again.
This is because you defined these functions inside the function scope.
You need to do this to achieve what you are trying to do.
var Gallery = function(){
return {
helloworld1:function(){alert('hey1')},
helloworld2:function(){alert('hey2')},
helloworld3:function(){alert('hey3')}
}
}();
This assigns Gallery to an object that has all the three functions as its properties. In this way then you can call. Gallery.helloworld1() which would print the alert.
This is a way of protecting an object from further modifications.
E.g you could do this
var Gallery = function(){
var realGallery = {no_of_pictures:1};
return {
getNumberOfPictures:function(){return realGallery.no_of_pictures;},
increasePictures:function(){realGallery.no_of_pictures += 1;},
decreasePictures:function(){realGallery.no_of_pictures -= 1;}
}
}();
This way no one can directly set no_of_pictures on realGallery object. They can only be incremented or decremented.
About your 2nd Question. It is generally not considered a good practice to use globals as anyone can tamper with them.
Lets say you defined function helloworld() {alert('hey1');}
Someone could easily redefine helloworld like this.
function helloworld(){alert('go away right now !!');}
So someone could easily completely break down your application with some small hack. That's why globals are considered a bad practice in javascript.
If you notice in the code that you cited, the parentheses after the Gallery function. Those are there to call the function immediately. So as soon as the code runs, that function is called. And that particular function is assigning the 3 hello world functions to their respective variables. But there is no access to those functions because o the reasons the first answer stated. So I'm not sure of the purpose of that code.
The key here is you have a self executing function, which doesn't return a value, therefore you can't access anything from within it, regardless of whether it was declared using var or this.
The goal of this coding style is to avoid polluting the global space with lots of variables and functions. Everything is encapsulated into the Gallery function. Using this style, you wouldn't try to access anything from the outside. It is like a bootstrap function where a set of procedures are executed and then it finishes, without the need to call anything inside again.
If you want to access from the outside, you need to first remove the self executing part, and secondly declare public properties or public pointers to the private properties:
var Gallery = function () {
var helloworld1 = function () {
alert('hey1');
}
var helloworld2 = function () {
alert('hey2');
}
var helloworld3 = function () {
alert('hey3');
}
this.helloworld1 = helloworld1;
this.helloworld2 = helloworld2;
this.helloworld3 = helloworld3;
};
var g = new Gallery();
g.helloworld1();
If you were to have the function return itself, then you can access the inside (providing the methods/properties are made public with this:
var Gallery = function () {
this.helloworld1 = function () {
alert('hey1');
}
return this;
}();
console.log(Gallery.helloworld2);

Does JavaScript have a variable for items declared in the function's scope? [duplicate]

This question already has answers here:
How can I access local scope dynamically in javascript?
(4 answers)
Closed 9 years ago.
Does JavaScript have a variable for items declared in the function's scope? I would like to access items declared inside a function using an associative array.
For example I can do the following with items at the global scope
var globalVar = "hi";
var myFunction = function () {
alert(window["globalVar"]);
};
But I would like to do a similar thing with variables declared inside a function
var myFunction = function () {
var funcVar = "hi";
alert(func["funcVar"]);
};
I realise doing such a thing isn't necessarily a good thing and I am doing the below instead, but I am still interested if JavaScript has such a variable.
var myFunction = function () {
var func = {funcVar : "hi" };
alert(func["funcVar"]);
};
This question has been asked and answered many times. No, in JavaScript there is no local object containing local variables as properties (in the way that for instance, in browser environments the window object contains global variables as properties).
Depending on what you are trying to accomplish, there are probably many alternative ways to attack it, including the one you are using now.
Duplicate of Javascript: Get access to local variable or variable in closure by its name, How can I access local scope dynamically in javascript?, Javascript local variable declare.
Perhaps you could assign properties to the function object itself, and reference those?
var myFunction = function() {
myFunction.funcVar = 'hi';
alert(myFunction['funcVar']);
};
It is not exactly the answer to your question, but it's the best way I can think of to access local variables as properties of an object. Note that in this method these variables will be visible outside the function in the same manner (that is, looking up the properties of the function).
If you really needed those properties to be hidden, you could hide them within a closure, like so:
var myFunction = function() {
(function hidden() {
hidden.funcVar = 'hi';
alert(hidden['funcVar']);
})();
};
Functions are just special objects that can be invoked. You can set properties of a function, and get them later.
var a = function () {
alert(a.testingVar);
};
a.testingVar = "asdf";
a();
DEMO: http://jsfiddle.net/gEM7W/
Although I don't see a reason/need to do this. You could always use a closure to keep local variables specific to a function. For example:
var a = (function () {
var obj = {
testingVar: "asdf"
};
return function () {
alert(obj.testingVar);
};
})();
a();
DEMO: http://jsfiddle.net/gEM7W/1/
You don't really have associative arrays. You have indexed arrays and you have objects.
In the future, there will be an iterator which will happily traverse both, without any side-effects. At that point, perhaps people will forget the difference.
However, the properties still wouldn't be order-based:
$arr = array(0, 1, "name"=>"Bob", 3);
In another language might get you an array where the keys are: 0, 1, "name", 3
In JS, you'd get 0, 1, 2, "name" (or "name", 0, 1, 2).
So stick with indexed arrays and objects with properties.
That said, you've got multiple options.
var myFunc = function () {
var private_data = {
name : "Bob",
age : 32
};
return {
getName : function () { return private_data.name; /* or private_data["name"] if that's really what your heart longs for */ },
get : function (key) { return private_data[key] || null; },
set : function (key, val) { private_data[key] = val; }
};
};
Now everything is private, and you can access them by property-name, using dot or bracket notation.
If they can be public, and the function is always going to be called the same thing (ie: not a constructor making an instance) then you can attach yourself to the actual function:
var myFunc = function () {
myFunc.name = "Bob";
myFunc["age"] = 32;
return {
get : function (key) { return (myFunc.hasOwnProperty(key)) ? myFunc[key] : null; }
};
};
Downside (or upside) is that myFunc is the public name. As such, these properties are publicly accessible.
Going the first route, you don't even need to declare a variable. You can just use the object you pass into a function.
var myFunc = function (dataObj) {
return {
getName : function () { return dataObj.name; },
setAge : function (val) { dataObj["age"] = val; }
};
};
var bob = myFunc({ name : "Bob" });
bob.setAge(32);
Now everything's private and I didn't even have to declare anything.
Closure keeps the object in play as long as there's a publicly accessible function that's returned, which still has access to that particular instance of the function call.
Once you figure out closures, this becomes a non-issue.

How to break closures in JavaScript

Is there any way to break a closure easily in JavaScript? The closest I have gotten is this:
var src = 3;
function foo () {
return function () {
return src; }
}
function bar (func) {
var src = 9;
return eval('('+func.toString()+')')(); // This line
}
alert(bar(foo()));
This prints '9', instead of '3', as a closure would dictate. However, this approach seems kind of ugly to me, are there any better ways?
Your code is not breaking the closure, you're just taking the code the makes up a function and evaluating it in a different context (where the identifier src has a different value). It has nothing at all to do with the closure that you've created over the original src.
It is impossible to inspect data that has been captured in a closure. In a sense, such data are even more "private" than private members in Java, C++, C# etc where you can always use reflection or pointer magic to access them anyway.
This could be useful if you are trying to create multiple similar methods in a loop. For example, if you're creating a click handler in a loop that relies on a loop variable to do something a little different in each handler. (I've removed the "eval" because it is unnecessary, and should generally never be used).
// Assign initial value
var src = 3;
// This is the regular js closure. Variables are saved by reference. So, changing the later will
// change the internal value.
var byref = function() {
return src;
}
// To "break" the closure or freeze the external value the external function is create and executed
// immidiatly. It is used like a constructor function which freezes the value of "src".
var byval = function(s) {
return function() { return s };
}(src);
src = 9;
alert("byref: " + byref()); // output: 9
alert("byval: " + byval()); // output: 3
As others said this doesn't seem to be the right thing to do. You should explain why you want this and what you want to achieve.
Anyway, one possible approach could be to access properties of an object inside your function. Example:
var src = 3;
function foo (context) {
context = context || window; // Fall back to the global namespace as default context
return function () {
return context.src;
}
}
function bar (func) {
var context = {src: 9};
return func(context);
}
alert(bar(foo));
If you want to access a variable in a wider scope, just don't reuse the variable name in a narrower scope.
That's how it is supposed to work. Work with it instead of trying to fight it.
Here is the code see if you can understand , closures defined within a loop .
var clicked = false;
for(var i=0;i<temp.length;i++){
(function(index){
if(clicked) return false;
$(temp[index]).on('click',function(){
if($(temp[index]).text()=="" && !$(".cell1").val()){
$(this).text(player1Val);
$(".cell1").val(true);
console.log("first player clicked ");
clicked = true;
$(this).off();
for(var j=0;j<temp.length;j++){
$(temp[j]).off('click');
}
return false;
}
else return false;
});
})(i);
}

Categories