The code goes like this (The syntax may seem odd but as far as I know, there is nothing wrong with it. Or is there?)
var add=function addNums(a, b) {
return a+b;
}
alert("add: "+ add(2,3)); // produces 5
alert("addNums: "+addNums(2,3)); // should also produce 5
addNums() is declared as a function. So, when I pass the parameters to it, it should also return the result.
Then, why am I not getting the second alert box?
You are seeing a named function expression (NFE).
An anonymous function expression is where you assign a function without a name to a variable1:
var add = function () {
console.log("I have no own name.");
}
A named function expression is where you assign a named function to a variable (surprise!):
var add = function addNums() {
console.log("My name is addNums, but only I will know.");
}
The function's name is only available within the function itself. This enables you to use recursion without necessarily knowing the "outside name" of the function - even without having to set one in the first place (think callback functions).
The name you choose shadows an existing name, so if another addNums is defined elsewhere it will not be overridden. This means you can use any name you like without fear for scoping problems or breaking anything.
In the past you would have used arguments.callee to refer to a function inside itself without knowing its name. But support for that is being removed from JavaScript2, so NFEs are the correct way to do this nowadays.
Here is a lot of stuff to read on the topic: http://kangax.github.io/nfe/
1 Assigning it to a variable is not necessary, it just serves as an example to distinguish it from a plain function declaration. It could be any other context where JS expects an expression (a function argument, for example).
2 You will receive an error if you have strict mode in effect and try to use arguments.callee.
The problem
You are using a named function expression - and a function expression's name is not available outside of that function's scope:
// Function statement
function statement() {
console.log("statement is a type of " + typeof statement);
}
statement();
console.log("statement is a type of " + typeof statement);
results in:
statement is a type of function
statement is a type of function
whereas:
// Function expression with a name
var expression = function namedExpression() {
console.log("namedExpression is a type of " + typeof namedExpression);
};
expression();
// namedExpression(); // uncommenting this will cause an exception
console.log("expression is a type of " + typeof expression);
console.log("namedExpression is a type of " + typeof namedExpression);
will produce:
namedExpression is a type of function
expression is a type of function
namedExpression is a type of undefined
The solution
Depending on what you are trying to do, you want do do one of the following:
Change your function declaration to use a statement and then alias your function:
function addNums(a, b) {
return a + b;
}
var add = addNums;
Alias both names to your expression:
var add = addNums = function addNums(a, b) {
return a + b;
};
Why does JavaScript do things this way?
Named function expressions are useful because they let you reference a function inside itself and they give you a name to look at in a debugger. However, when you use a function as a value you don't generally want parts of it leaking into the enclosing scope. Consider:
(function setup() {
var config = retrieveInPageConfig();
if (config.someSetting) {
performSomeOtherSetup();
}
kickOffApplication();
})();
This is a perfectly licit use of a function expression - in such a case you would not expect the name setup to leak into the enclosing scope. Assigning a named function expression to a variable is just a special case of this, that just happens to look like a function statement declaration.
addNums is only available in the scope of the newly-defined function.
Quite obviously, when a function expression has a name (technically —
Identifier), it is called a named function expression. What you’ve
seen in the very first example — var bar = function foo(){}; — was
exactly that — a named function expression with foo being a function
name. An important detail to remember is that this name is only
available in the scope of a newly-defined function; specs mandate that
an identifier should not be available to an enclosing scope.
Read more detail form this article.
You should either declare as named function:
function addNums(){
}
or assign function to the variable:
var add= function(){// your code }
The reason why addNum() doesn't return anything is because it's not added to the global scope with the way you declare it.
Demo
function addNums(a, b) {
return a+b;
}
var add = addNums;
alert("add: "+ add(2,3));
alert("addNums: "+addNums(2,3));
I have added your code in my test web app and works fine for me. Here is the code. Would you please share the more details of your code/app?
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="JavascriptTest.aspx.cs" Inherits="GetGridViewColumnValue.JavascriptTest" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script type="text/javascript">
var add = function addNums(a, b) {
return a + b;
}
alert("add: " + add(2, 3)); // produces 5
alert("addNums: " + addNums(2, 3));
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
Cheers!!!
Consider the following code:
var f = function g() {
// function
};
The g will be access only in the function itself, and its needed when you want to use the function
by itself, for writing recursive functions. For example, you want the factorial function:
var f = function factorial(x) {
if (x <= 1) return 1;
// here we want to use the function itself
return x * factorial(x - 1);
};
console.log(f(5));
However, its really needed as you can access the function itself by arguments.callee:
// note that the function has not any name
var f = function (x) {
if (x <= 1) return 1;
// here we want to use the function itself
return x * arguments.callee(x - 1);
};
console.log(f(5));
I've slightly modified your code:
var add = function addNums(a, b){
return a+b;
}
console.log(add);
console.log(typeof(add));
console.log("add: "+ add(2,3)); // produces 5
console.log("addNums: "+addNums(2,3));
And then proceeded to run it inside of node.js to get this output:
[Function: addNums]
function
add: 5
/home/mel/l.js:44
console.log("addNums: "+addNums(2,3));
^
ReferenceError: addNums is not defined (... backtrace)
Normally, a variable assigned an inline anonymous method would print out [Function] when called with console.log(var); Here console.log(add); results in the name of the function also being printed.
So it's not like your addNums declaration is invalid or not used, it's simply scoped to be bound to the variable add.
addNums is not a function in the global namespace..
It's an function defined only within the assignment operator..
if you want to have access to it try the follow:
function addNums(a, b)
{
return a+b;
}
var add = addNums;
var add = function <---- the function name is add and it's value is a function..
Related
I want to know how the function has been initialized, with the expression or declaried as fuction. _ Amazon interview question
expression : var a = function (){ }
declaration: function a (){ }
You could just do a.toString() and parse out the name. Or do the same with regular expressions
a.toString().test(/^\s*function\s*\(/);
function a(){ }; // gives false
var a = function (){ }; // gives true
Of course as Grundy pointed out this fails with named functions. Something like
var a = function b() {};
or
function b() {};
var a = b;
And ES6 has .name (see the Browser table at the bottom for the current state of affairs) - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Function/name
I don't think it's possible to do so. The only difference between:
var func = function(){ };
and:
function func() { };
Is that the first one gets assigned on runtime. The way I see it, is that both function statements return a reference to their respective function objects. In that sense they are both the same. The only thing you could argue is that one is not named and the other one is, but you could have assigned a named function to a variable too.
However, there seems to be a difference on how they get assigned. The second one seems to get assigned to a variable that its named after, right at the start of the execution context. The first one has to wait for the explicit assignment within the execution context.
So you'd be testing for when they get assigned. You might think that's is possible to do so within the global object like:
//some protected vars that can't work without same-origin
var protected = ['caches', 'localStorage', 'sessionStorage', 'frameElement'];
var definedAtInit = [];
for(prop in window){
if(!isSandboxed(prop) && typeof window[prop] === 'function'){
definedAtInit.push(prop);
}
};
function isSandboxed(prop){
return protected.indexOf(prop) !== -1;
}
function isItDefinedAtInit(funcName){
return definedAtInit.indexOf(funcName) !== -1;
}
var func = function() {
console.log('test');
}
var results = { isItDefinedAtInit : isItDefinedAtInit('isItDefinedAtInit'),
func : isItDefinedAtInit('func')
};
document.getElementById('results').innerHTML = JSON.stringify(results, '/t');
<pre id="results"></pre>
However, you could still do something like:
var isItDefinedAtInit = function() { };
//After this, isItDefinedAtInit('isItDefinedAtInit') would be wrong.
And you still have the problems with other execution contexts, I don't think functions declared within a function execution context get attached to any object.
I think these kind of checks are a bad idea to be honest.
There is only way, we can determine function has defined with function declarations not as expression.
as Grundy mentioned name property of the respective function gives require information, if it has been defined with expression name property holds undefined value, else it holds function name.
Here is the code :
var isDefinedAsFunction = function(fn){
return fn.name !== undefined
}
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
<script>
!function add_them(a,b) { return a+b;} (9,4)
console.log(add_them());
</script>
Question:
it shows: ReferenceError: add_them is not defined, what is the problem? and how to make it show the right result: 13?
You seem to want a simple function declaration:
function add_them(a,b) { return a+b;}
console.log(add_them(9,4));
If you wanted to use an immediately invoked function expression, it might look like this:
console.log(function add_them(a,b) { return a+b; } (9,4));
// \ expression / ^^^^^
// invocation
however the identifier (add_them) is not reusable outside (after) of the function expression.
Also notice that when your IEFE is supposed to yield some result, the (little) advantage of !function(){}() over (function () {})()? is neglected since the result gets negated.
You're confusing the browser (well, it's technically correct according to the spec).
Try another trick to make it treat the function as an expression:
(function add_them(a,b) { return a+b;})(9,4) // 13
Or simply:
console.log((function add_them(a,b) { return a+b;})(9,4)) // logs 13
If you're just trying to fixate the parameters you can .bind the function to values (which is what it seems to me you're trying to do):
var add_them = (function(a,b) { return a+b;}).bind(null, 9,4)
console.log(add_them());// logs 13
The problem is that immediately invoked function expressions are function expressions.
In JavaScript functions may be either declarations or expressions. For instance, consider:
(function (a, b) { return a + b; }) // This is an expression
function (a, b) { return a + b; } // This is a declaration
How to distinguish a function expression from a function declaration? If the function is used in place where an expression is expected it automatically becomes an expression. Function expressions can be invoked immediately.
On the other hand a function declaration is also easy to spot because declarations in JavaScript are hoisted. Hence the function can be invoked before it appears in the program. For example, consider:
console.log(add(2, 3));
function add(a, b) {
return a + b;
}
Now the problem with your code is that you're immediately invoking a function expression. However because it's an expression and not a declaration you can't use it like a normal function. You need to declare a function before you can use it.
Do this instead:
add_them(9, 4);
console.log(add_them());
function add_them(a, b) {
return a + b;
}
If you want to fix the parameters of the function then you may use bind as follows:
var add_9_4 = add_them.bind(null, 9, 4);
console.log(add_9_4());
function add_them(a, b) {
return a + b;
}
Hope that helps.
Following are two ways to define BW.Timer. Can someone tell me what the difference is? I am not certain the first is even valid, but if it is valid, what is different about using the myfunc=(function(){}()) syntax?
BW.Timer = (function () {
return {
Add: function (o) {
alert(o);
},
Remove: function (o) {
alert(o);
}
};
} ());
And...
BW.Timer = function () {
return {
Add: function (o) {
alert(o);
},
Remove: function (o) {
alert(o);
}
};
};
The first is the return-value of the immediately-invoked function. The second is a function. It essentially comes down to what the difference is between these:
var f = (function() { return 0; })();
var f = function() { return 0; };
Since the first function is called immediately, the value of 0 is given to the variable f. The first f is not a function. However, the second f we must call in order to get the value:
f(); // 0
It follows that in your example, the first BW.Timer is the object literal itself and the second is a function returning an object literal. You must call the function in order to get to the object:
BW.Timer().Add(x);
Why use the first then?
You might ask yourself why one would use a syntax like a = (function() { return {}; })() instead of a = {}, but there's a good reason. An IIFE (Immeditately-Invoked Function Expression), unlike a regular function allows the emulation of static variables (variables that maintain their value through a single instance). For example:
var module = (function() {
var x = 0;
return { get: function() { return x },
set: function(n) { x = n }
};
})();
The above a text-book example of the Module Pattern. Since the function is called right away, the variable x is instantiated and the return value (the object) is given to module. There's no way we can get to x other than by using the get and set methods provided for us. Therefore, x is static, meaning its variable won't be overridden each time you use module.
module.set(5);
module.get(); // 5
On the other hand, let's see an example where module is declared as a function instead:
// assume module was made as a function
module().set(5);
module().get(); // 0
When we call module() the x variable is overridden each time. So we're effectively using different instances of module and x each time we call module.
The difference is rather large.
In the first case, BW.Timer is executed when it is first encountered, and that is the static version assigned to BW.Timer. In that instance, BW.Timer.Add(1) may be used. Each call to BW.Timer will be the same object.
In the second case, BW.Timer is not executed when first encountered, and instead is a function referece which must be invoked BW.Timer(). For Add to be used, this must be the case BW.Timer().Add(1). Also, you can issue var timer = new BM.Timer();. Each instance of BW.Timer() will be unique here.
In the first example BW.Timer references an object that the self-executing function returns, while in the second example it references a function object, in other words it's a function that can be executed BW.Timer().
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."