This question already has answers here:
function arguments
(5 answers)
Closed 9 years ago.
Consider:
var success = function(data){
data = process_data(data);
console.log(data);
};
vs.
var success = function(data){
var data = process_data(data);
console.log(data);
};
What are the pros/cons of each?
There is no difference for your ECMAscript interpreter.
Both, formal paramters aswell as local variables are stored in the such called Activation Object (ES3) respectively lexical Environment Record (ES5+).
Those are, special data containers on implementation level which store data belonging to a context, like a function.
While there won't be any differences at runtime, most linting tools will complain about the second piece of code. JSHint gives this error:
'data' is already defined.
If you don't need the original data parameter it's safe to redeclare the variable, but usually it isn't necessary.
On entering function code, the identifiers in the formal parameter list are effectively treated as variable declarations, therefore including them in a var statement inside the function body has no effect.
However, there was an ancient version of Safari that threw an error in cases like:
function (foo) {
foo = foo || {};
...
}
where no value was passed. However, that was a long time ago and certainly not a reason to include var statements for formal parameters.
If you have:
function foo(bar) {
var bar = otherFunc(bar);
...
}
Although this is technically correct, I consider it poor form because you're implying that there are two distinct "bar" variables. That seems like it could cause more confusion later down the line than the version where you don't use "var".
If you want to declare a variable inside then probabley you should declare it with some other name(not similar to the argument).
This way you will be able to reuse the original argument.
If you don't want to use the original argument then you can directly use it. But remember declaring a new variable inside will restrict the scope of the variable.
Related
I run into a bit of confusion regarding scoping with respect to where a callback is defined.
function test(){
var b = 3
var fun = function(){
var printingFunction = function(){
console.log(b)
}
printingFunction()
}
return fun
}
test()() //prints 3, as expected because of closures
However, the following doesnt work
function test(){
var b = 3
var fun = function(cb){
cb()
}
return fun
}
test()(function(){console.log(b)}) //b is not defined
I would expect that since the function is passed as an argument and has not been defined before, its definition takes place inside 'fun' and therefore it would have access to b. Instead, it looks a lot like the function is first defined in the scope where its passed and THEN passed as an argument. Any ideas/pointers?
EDIT: Some extra pointers.
someFunction("a")
We couldn't possibly claim that "a" is a definition. What happens here implicitly is that "a" is assigned to a variable named by the argument name so var argumentNameInDefintion = "a". This happens in the body of someFunction.
Similarly we cant claim {} is a definition in : someFunction({}). So why would:
someFunction(function(){})
decide that function(){} is a definition is beyond me. Had it been
var a = function(){}
someFunction(a)
everything would make perfect sense. Maybe its just how the language works.
Scoping in JavaScript is lexical. If you look at your examples, you can see that where printingFunction is defined, lexically (e.g., in the source text) b is declared in a containing scope. But in your second example, it isn't. That's why b can't be resolved in your second example but can in your first.
The way it works is that when a function is created, it has a reference to a conceptual object containing the variables and such in the scope in which it's created (which has a fancy name: "Lexical Environment object"); and that object has a reference to the one that contains it. When looking up a variable reference, the JavaScript engine looks at the current lexical environment object and, if it finds the variable, uses it; otherwise, it looks to the previous one in the chain, and so on up to the global one.
More details can be found:
In this SO question's answers
In this post on my anemic little blog
The issue stems from me not understanding that function(){} on its own is a definition and so is "a" and {}. Since these are definitions then the definition scope of the function passed is appropriately placed where it is and the world makes sense again.
In first case, it is forming a closure and has access to the variable "b" but in second case it does not form a closure at all. If you put a debugger just before the cb() inside the function, you will notice that there is no closure formed and the reason of that being the callback function is suplied to the function as an argument and it becomes local to that function which does not have any knowledge of the variable b.
Think of it as two different functions, one in which it has a local variable "b" and in other no local variable but we are trying to access it which throws the reference error.
This question already has answers here:
Is JavaScript a pass-by-reference or pass-by-value language?
(33 answers)
Closed 6 years ago.
First of all, I'm sorry for asking this which was seemingly asked before, but...
In the questions I found, people talk about scope (and I'm familiar with the concept) or about some "callback" or "asynchronous" things that I don't really understand. The reason why I ask this is because all my global variables so far, were normally affected by the great number of functions.
The code I have is way too big for me to paste it here, but I'll give you an example.
var ContainsSomeNumber = 50;
var AnObjectWithSomeValues ...
var TheFunctionInQuestion = function(nameRepresentingTheObject, nameRepresentingNumberVar){
if(nameRepresentingTheObject.lestSayName ==== "SomeString"){
nameRepresentingNumberVar+=5;
}
}
Now the thing is, it understands both variables and gets the correct result when I pass them into the function, however, the ContainsSomeNumber variable remains unaffected by the function on a global scale. If I place an alert or log to show me how much it is inside the function, it shows 55, as it should. But once I try to access the modified global variable in another place with the modified value after the function has been run successfully (chrome and firefox show no foul play), it returns the same unmodified value of 50.
Is the problem because I didn't use hardcode versions of variables to pass in the function, or what? Because like I said, it sees and modifies it the right way, but only inside the function. Shouldn't scope see the variable as a global one as I didn't write "var" in front of the one I used in the function? I mean, I didn't declare it as a new variable, plus it took it's global value normally. Why doesn't the global variable stay modified by the function?
Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.
So if you want to a function modify an variable outside there scope, you should pass an object and change some attribute inside the object.
var obj = {
ContainsSomeNumber: 50;
}
var AnObjectWithSomeValues ...
var TheFunctionInQuestion = function(nameRepresentingTheObject, obj){
if(nameRepresentingTheObject.lestSayName === "SomeString"){
obj.ContainsSomeNumber+=5;
}
}
Or you can return the value:
var ContainsSomeNumber = 50;
var AnObjectWithSomeValues ...
var TheFunctionInQuestion = function(nameRepresentingTheObject, nameRepresentingNumberVar){
if(nameRepresentingTheObject.lestSayName === "SomeString"){
nameRepresentingNumberVar+5;
}
return nameRepresentingNumberVar
}
This code always works, even in different browsers:
function fooCheck() {
alert(internalFoo()); // We are using internalFoo() here...
return internalFoo(); // And here, even though it has not been defined...
function internalFoo() { return true; } //...until here!
}
fooCheck();
I could not find a single reference to why it should work, though.
I first saw this in John Resig's presentation note, but it was only mentioned. There's no explanation there or anywhere for that matter.
Could someone please enlighten me?
The function declaration is magic and causes its identifier to be bound before anything in its code-block* is executed.
This differs from an assignment with a function expression, which is evaluated in normal top-down order.
If you changed the example to say:
var internalFoo = function() { return true; };
it would stop working.
The function declaration is syntactically quite separate from the function expression, even though they look almost identical and can be ambiguous in some cases.
This is documented in the ECMAScript standard, section 10.1.3. Unfortunately ECMA-262 is not a very readable document even by standards-standards!
*: the containing function, block, module or script.
It is called HOISTING - Invoking (calling) a function before it has been defined.
Two different types of function that I want to write about are:
Expression Functions & Declaration Functions
Expression Functions:
Function expressions can be stored in a variable so they do not need function names. They will also be named as an anonymous function (a function without a name).
To invoke (call) these functions they always need a variable name. This kind of function won't work if it is called before it has been defined which means Hoisting is not happening here. We must always define the expression function first and then invoke it.
let lastName = function (family) {
console.log("My last name is " + family);
};
let x = lastName("Lopez");
This is how you can write it in ECMAScript 6:
lastName = (family) => console.log("My last name is " + family);
x = lastName("Lopez");
Declaration Functions:
Functions declared with the following syntax are not executed immediately. They are "saved for later use" and will be executed later, when they are invoked (called upon). This type of function works if you call it BEFORE or AFTER where is has been defined. If you call a declaration function before it has been defined Hoisting works properly.
function Name(name) {
console.log("My cat's name is " + name);
}
Name("Chloe");
Hoisting example:
Name("Chloe");
function Name(name) {
console.log("My cat's name is " + name);
}
The browser reads your HTML from beginning to end and can execute it as it is read and parsed into executable chunks (variable declarations, function definitions, etc.) But at any point can only use what's been defined in the script before that point.
This is different from other programming contexts that process (compile) all your source code, perhaps link it together with any libraries you need to resolve references, and construct an executable module, at which point execution begins.
Your code can refer to named objects (variables, other functions, etc.) that are defined further along, but you can't execute referring code until all the pieces are available.
As you become familiar with JavaScript, you will become intimately aware of your need to write things in the proper sequence.
Revision: To confirm the accepted answer (above), use Firebug to step though the script section of a web page. You'll see it skip from function to function, visiting only the first line, before it actually executes any code.
Some languages have the requirement that identifiers have to be defined before use. A reason for this is that the compiler uses a single pass on the sourcecode.
But if there are multiple passes (or some checks are postponed) you can perfectly live without that requirement.
In this case, the code is probably first read (and interpreted) and then the links are set.
I have only used JavaScript a little. I am not sure if this will help, but it looks very similar to what you are talking about and may give some insight:
http://www.dustindiaz.com/javascript-function-declaration-ambiguity/
The body of the function "internalFoo" needs to go somewhere at parsing time, so when the code is read (a.k.a parsing) by the JS interpreter, the data structure for the function is created and the name is assigned.
Only later, then the code is run, JavaScript actually tries to find out if "internalFoo" exists and what it is and whether it can be called, etc.
For the same reason the following will always put foo in the global namespace:
if (test condition) {
var foo;
}
I've done a lot of searching and some playing around, and I'm pretty sure the answer to this question is no, but I'm hoping a JavaScript expert might have a trick up his sleeve that can do this.
A JavaScript function can be referenced by multiple properties, even on completely different objects, so there's no such thing as the object or property that holds the function. But any time you actually call a function, you must have done so via a single object (at the very least, the window object for global function calls) and property on that object.
(A function can also be called via a function-local variable, but we can consider the function-local variable to be a property of the activation object of the scope, so that case is not an exception to this rule.)
My question is, is there a way to get that property name that was used to call the function, from inside the function body? I don't want to pass in the property name as an argument, or closure around a variable in an enclosing scope, or store the name as a separate property on the object that holds the function reference and have the function access that name property on the this object.
Here's an example of what I want to do:
var callName1 = function() { var callName = /* some magic */; alert(callName); };
var obj1 = {'callName2':callName1, 'callName3':callName1 };
var obj2 = {'callName4':callName1, 'callName5':callName1 };
callName1(); // should alert 'callName1'
obj1.callName2(); // should alert 'callName2'
obj1.callName3(); // should alert 'callName3'
obj2.callName4(); // should alert 'callName4'
obj2.callName5(); // should alert 'callName5'
From my searching, it looks like the closest you can get to the above is arguments.callee.name, but that won't work, because that only returns the name that was fixed to the function object when it was defined, and only if it was defined as a named function (which the function in my example is not).
I also considered that maybe you could iterate over all properties of the this object and test for equality with arguments.callee to find the property whose value is a reference to the function itself, but that won't work either (in the general case), because there could be multiple references to the function in the object's own (or inherited) property set, as in my example. (Also, that seems like it would be kind of an inefficient solution.)
Can this be done?
Short answer:
No, you cannot get "the property name" used to call your function.
There may be no name at all, or multiple names across different scopes, so "the property name" is pretty ill defined.
arguments.callee is deprecated and should not be used.
There exists no solution that does not use arguments or closure.
Long answer:
As thefourtheye commented, you should rethink what you are trying to do and ask that instead in a new question. But there are some common misconceptions, so I will try to explain why you cannot get the "simple property name".
The reason is because it is not simple.
Before we go ahead, let us clarify something. Activation Objects are not objects at all.
The ECMAScript 5.1 specification calls them Environment Records (10.2.1), but a more common term is Scope chain.
In a browser the global scope is (often) the window object, but all other scopes are not objects.
There may be an object that you use to call a function, and when you call a function you must be in some scope.
With few exceptions, scopes are not objects, and objects are not scopes.
Then, there are many names.
When you call a function, you need to reference it, such as through an object property. This reference may have a name.
Scope chain has declarations, which always have a name.
A Function (the real function, not reference) may also have a function name - your arguments.callee.name - which is fixed at declaration.
Not only are they different names, they are not (always) the "the property name" you are seeking.
var obj = { prop : function f(){} }, func = obj.prop;
// "obj" and "func" are declarations.
// Function name is "f" - use this name instead of arguments.callee
// Property name is "prop"
func(); // Reference name is "func"
obj.prop(); // Reference names are "obj" and "prop"
// But they are the same function!
// P.S. "this" in f is undefined (strict mode) or window (non-strict)
So, a function reference may comes from a binding (e.g. function declaration), an Object (arguments.callee), or a variable.
They are all References (8.7). And reference does have a name (so to speak).
The catch is, a function reference does not always come from an object or the scope chain, and its name is not always defined.
For example a common closure technique:
(function(i){ /* what is my name? */ })(i)
Even if the reference does have a name, a function call (11.2.3) does not pass the reference or its name to the function in any way.
Which keeps the JavaScript engine sane. Consider this example:
eval("(new Function('return function a(){}'))()")() // Calls function 'a'.
The final function call refers the eval function, which refers the result of a new global scope (in strict mode, anyway), which refers a function call statement, which refers a group, which refers an anonymous Function object, and which contains code that expresses and returns a function called 'a'.
If you want to get the "property name" from within a, which one should it get? "eval"? "Function"? "anonymous"? "a"? All of them?
Before you answer, consider complications such as function access across iframes, which has different globals as well as cross origin restriction, or interaction with native functions (Function.prototype.bind for example), and you will see how it quickly becomes hell.
This is also why arguments.caller, __caller__, and other similar techniques are now all deprecated.
The "property name" of a function is even more ill defined than the caller, almost unrealistic.
At least caller is always an execution context (not necessary a function).
So, not knowing what your real problem is, the best bet of getting the "property name" is using closure.
there is no reflection, but you can use function behavior to make adding your own fairly painless, and without resorting to try/catch, arguments.callee, Function.caller, or other strongly frowned-upon behavior, just wasteful looping:
// returning a function from inside a function always creates a new, unique function we can self-identify later:
function callName() {
return function callMe(){
for(var it in this) if(this[it]===callMe) return alert(it);
}
};
//the one ugly about this is the extra "()" at the end:
var obj1 = {'callName2':callName(), 'callName3':callName() };
var obj2 = {'callName4':callName(), 'callName5':callName() };
//test out the tattle-tale function:
obj1.callName2(); // alerts 'callName2'
obj2.callName5(); // alerts 'callName5'
if you REALLY want to make it look like an assignment and avoid the execution parens each time in the object literal, you can do this hacky routine to create an invoking alias:
function callName() {
return function callMe(){
for(var it in this) if(this[it]===callMe) return alert(it);
}
};
//make an alias to execute a function each time it's used :
Object.defineProperty(window, 'callNamer', {get: function(){ return callName() }});
//use the alias to assign a tattle-tale function (look ma, no parens!):
var obj1 = {'callName2': callNamer, 'callName3': callNamer };
var obj2 = {'callName4': callNamer, 'callName5': callNamer };
//try it out:
obj1.callName2(); // alerts 'callName2'
obj2.callName5(); // alerts 'callName5'
all that aside, you can probably accomplish what you need to do without all the looping required by this approach.
Advantages:
works on globals or object properties
requires no repetitive key/name passing
uses no proprietary or deprecated features
does not use arguments or closure
surrounding code executes faster (optimized) than
a try/catch version
is not confused by repeated uses
can handle new and deleted (renamed) properties
Caveats:
doesn't work on private vars, which have no property name
partially loops owner object each access
slower computation than a memorized property or code-time repetition
won't survive call/bind/apply
wont survive a setTimeout without bind() or a wrapper function
cannot easily be cloned
honestly, i think all the ways of accomplishing this task are "less than ideal", to be polite, and i would recommend you just bite the coding bullet and pass extra key names, or automate that by using a method to add properties to a blank object instead of coding it all in an object literal.
Yes.
Sort Of.
It depends on the browser. (Chrome=OK, Firefox=Nope)
You can use a factory to create the function, and a call stack parsing hack that will probably get me arrested.
This solution works in my version of Chrome on Windows 7, but the approach could be adapted to other browsers (if they support stack and show the property name in the call stack like Chrome does). I would not recommend doing this in production code as it is a pretty brittle hack; instead improve the architecture of your program so that you do not need to rely on knowing the name of the calling property. You didn't post details about your problem domain so this is just a fun little thought experiment; to wit:
JSFiddle demo: http://jsfiddle.net/tv9m36fr/
Runnable snippet: (scroll down and click Run code snippet)
function getCallerName(ex) {
// parse the call stack to find name of caller; assumes called from object property
// todo: replace with regex (left as exercise for the reader)
// this works in chrome on win7. other browsers may format differently(?) but not tested.
// easy enough to extend this concept to be browser-specific if rules are known.
// this is only for educational purposes; I would not do this in production code.
var stack = ex.stack.toString();
var idx = stack.indexOf('\n');
var lines = ex.stack.substring(idx + 1);
var objectSentinel = 'Object.';
idx = lines.indexOf(objectSentinel);
var line = lines.substring(idx + objectSentinel.length);
idx = line.indexOf(' ');
var callerName = line.substring(0, idx);
return callerName;
}
var Factory = {
getFunction: function () {
return function () {
var callName = "";
try {
throw up; // you don't *have* to throw to get stack trace, but it's more fun!
} catch (ex) {
callName = getCallerName(ex);
}
alert(callName);
};
}
}
var obj1 = {
'callName2': Factory.getFunction(),
'callName3': Factory.getFunction()
};
var obj2 = {
'callName4': Factory.getFunction(),
'callName5': Factory.getFunction()
};
obj1.callName2(); // should alert 'callName2'
obj1.callName3(); // should alert 'callName3'
obj2.callName4(); // should alert 'callName4'
obj2.callName5(); // should alert 'callName5'
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How can I access local scope dynamically in javascript?
Hi all.
We all know that you can access a property of a javascript object by it's name using the [] syntax.. e.g. ob['nameOfProperty'].
Can you do the same for a local variable? Another answer here suggested the answer is to use window['nameOfVar']. However, this only worked for the poster as he was defining variables at window-level scope.
I assume that this must be possible in general, as Firefox's Firebug (which I believe is written in javascript) can show local and closure variables. Is there some hidden language feature I'm not aware of?
Specifically, here's what I want to do:
var i = 4;
console.log(window['i']); // this works..
function Func(){
var j = 99;
// try to output the value of j from its name as a string
console.log(window['j']); // unsurprisingly, this doesn't work
}
Func();
I'm not aware of anything built into JavaScript to reference local variables like that (though there probably should be considering all variables are internally referenced by strings).
I'd suggest keeping all your variables in an object if you really need to access by string:
var variables = {
"j": 1
};
alert(variables["j"]);
Update: It kind of bugs me that there's no way to do this like you want. Internally the variable is a mutable binding in the declarative environment records. Properties are bound to the object they're a property of through the object's environment records, but there's actually a way to access them using brackets. Unfortunately, there's no way to access the declarative environment records the same way.
Accessing the variable with window or any other global accessor won't work because the variable is not globally accessible. But you can use can use eval to evaluate any expression:
<script>
function test(){
var j = 1;
alert(eval("j"));
}
test();
</script>
What about:
<script>
function Func(){
var fn = arguments.callee;
fn.j = 99;
console.log(fn['j']);
}
Func();
console.log(window['j']); //not global
console.log(Func['j']); //but not private
</script>
No, this isn't possible in general. JavaScript resolves identifiers inside a function using the scope chain; there's no single object that contains all the variables in scope, and the objects in the scope chain are inaccessible from JavaScript running in the page.
No, because the variable is only accessible from within the execution contexts that contain the variable's scope.
Put another way, the only way you can access j is if you are accessing it from something in the scope of test -- via an inner function, or whatever. This is because j, in a sense, doesn't exist to objects with a wider scope, like the global object. If it were otherwise, then variable names would have to globally unique.