Does Javascript Use Dynamic Name Resolution? - javascript

This is my go to test for whether a language has dynamic name resolution.
function foo() {
function bar() {
print a
}
var a = 10
bar()
}
If the language uses dynamic name resolution, the code should print 10. Otherwise, it should throw an undefined error.
Javascript prints 10. But Javascript uses variable hoisting, which moves var a to the top foo and invalidates my test.
Edit:
If we could delete variables in JS, the following would be an excellent test:
var a = 5
function foo() {
var a = 10
function bar() {
print a
}
delete a
bar()
}
foo()
If JS statically resolves names, bar's a references foo's a. Since foo's a gets deleted (if it were possible), bar would print undefined.
If JS dynamically resolves names, bar's a will be looked up dynamically when bar() is called. Since foo's a is already deleted at this point, the lookup would find the global a, and bar would print 5.

Does Javascript Use Dynamic Name Resolution?
Yes. Consider the following example:
eval("var foo = 'foo';");
console.log(foo);
// > "foo"
The variable foo isn't bound to the lexical environment until runtime (due to the eval() statement), but the fact that no error is thrown (and the code works) demonstrates that the name is resolved dynamically.
But Javascript uses variable hoisting, which moves var a to the top foo and invalidates my test.
Note: maybe you're just saying that hoisting is getting in the way of the test you're trying to perform? If so, please ignore the rest of this answer...
This behavior is actually explained by hoisting, rather than invalidated by it. I.e.,
As you pointed out, due to hoisting, the variable a gets created (but not assigned to, yet) at the very top of the foo() function.
Next, you have a function declaration. As it happens, function declarations get hoisted to the top of their scope, too.
Next you assign the value 10 to a. Note that this happens before you actually invoke bar().
Finally, you actually invoke bar(), at which point a already has been assigned the value 10, resulting in 0 being printed out.
Combining that all together, your foo() function behaves the same as if it had been written as follows:
function foo() {
// hoisted
var a;
// also hoisted
function bar() {
// due to hoisting, `a` is lexically in scope here
console.log(a);
}
// the actual assignment
a = 10
// the invocation
bar()
}
I happened to provide a fairly thorough explanation of the difference between declarations and assignments/initialization in an answer just last night. It explains much of the behavior seen here as well: Declaring vs Initializing a variable?

Related

It is considered bad practice to assign a value to an implicitly declared local variable of a function?

Question: It is considered bad practice to assign a value to an implicitly declared local variable of a function? if so, what is the perfered method of assigning a implicitly declared local variable of a function
function foo(baz) {
baz = 3; //this is implicitly declared by the function's argument baz
}
foo()
I wouldn't call it a bad practice (as in harmful), just not a good one. A beneficial effect is to reduce code length by 4 characters as it replaces a variable declaration within the function. That's only for the first variable, after that there is no benefit and if other variables are declared, there is zero benefit.
However, code readability suffers and the function signature is needlessly obfuscated, e.g.
function foo(bar) {
/* some code */
}
leaves the user wondering what should be passed to bar, whereas:
function foo() {
var bar;
/* some code */
}
makes it clear that foo doesn't take any arguments.
Formal parameters are processed before declarations, but I can't see any benefit or side effects from that.
I think it's a bit useless. Because it doesn't matter what value you pass, you just overwrite it with whatever you want. So, not a bad practice, just a useless function. No offense please.
That reminds me:
function random_number() {
return 7;
}

Unusual javascript behavior

I have encountered a weird behavior in javascript. Consider this code:
var foo;
function bar(){
function foo(){};
foo = 10;
return;
}
foo = 1;
bar();
console.log(foo);
This will output 1. But if I delete the foo function declaration in the third line, it will output 10. Why isn't it output 10 when the function declaration is there? And what is the reason for if I change that function definition to this:
foo = function(){};
it will output 10 again? I know about the hoisting of function declarations, but it doesn't seem to be answer to this.
That's not weird - you have a variable called foo, which you're setting to 1 normally. Inside the bar function, the foo function
if present, shadows this variable
if not present, foo references this original variable.
As such, if you define that foo function, foo=10 will take effect on that, otherwise it will take effect on the original foo.
As for the second part of the question (why does it change back if you use var foo=...), that's because in that case the duplicate variable declaration is merged into one, so you end up with the same as if you didn't write var.
This is a scoping problem. The first foo defined with a var is a "global" variable. When you have the foo function which is also a "variable" inside of the bar function, the foo assignment to 10 will be done to the local scope thus the global foo that you actually print out will not be changed. However, when there is no local foo the assignment inside of bar will change the global variable thus printing 10

A better understanding of javascript precompile

var foo=1;
function bar(){
foo=10;
return;
function foo(){}
}
bar();
alert(foo);
I am currently learning on how javascript is actually running in the machine and this is a piece of code I see in the example. I got no idea why the final alert is 1 instead of 10. So I am wondering could any one help me explain how the javascript virtual machine is actually execute these code. Thanks!
This is due to function declaration hoisting:
var foo=1;
function bar(){
function foo(){} // This gets moved up here by the engine
foo=10; // You've reassigned the local `foo` function to 10,
// leaving the global `foo` untouched
return;
}
bar();
alert(foo); // Since the foo has never changed in this scope, it's still 1
I got no idea why the final alert is 1 instead of 10.
Because the foo in this line in bar:
foo = 10;
...is the variable-like thing* declared by the function declaration later on in that function:
function foo(){}
...not the foo that's outside bar. That is:
var foo=1;
function bar(){
foo=10; // <== This `foo`
return;
function foo(){} // <== Is the `foo` declared here
}
bar();
alert(foo);
...not to the foo declared in the containing scope (var foo).
There are two reasons that's happening:
Function declarations are processed immediately on entry to the containing scope (the call to bar, in this case), prior to any step-by-step code in the function. This is sometimes called "hoisting" the declarations (because they happen as though they were at the very top). And since the function declaration isn't step-by-step code, the return has no effect on whether it gets processed; it gets processed before the return ever happens.
Function declarations also create what might as well be variables with the names of the functions. So the foo in the function declaration effectively becomes a variable with that name (more below) — and as you've seen in that code, you can assign new values to those "variables."
When you run that code, here's the order of things that the JavaScript engine does:
Creates a variable called foo and gives it the initial value undefined.
Creates the function bar, adding bar as an in-scope symbol (effectively a variable) in the current scope and making it a reference to the bar function.
Starts step-by-step code for that scope.
Assigns the value 1 to foo.
Calls the bar functon.
Creates the foo function relevant to that call to bar, adding foo as an in-scope symbol (effectively a variable) during the call and making it a reference to the function.
Starts the step-by-step code for that scope.
Assigns the value 10 to the local foo (which used to refer to the function).
Returns out of the function.
Calls alert with the foo in that scope, which still has the value 1.
You can read up on all the gory details in §10.4.3 of the spec and the sections it links to.
* "variable-like thing" In JavaScript, each execution context (the global context and any contexts created by calling functions, etc.) has an object that it uses to hold various names used in that context and their values; it's called a "binding object." The binding object for a context (I'm skipping some unrelated details here) has properties for each variable, function declaration, and a few other things like the arguments pseudo-array, the name of the function itself (referring back to the function), and such. The name of the properties are the names of the variables, declared functions, etc. That's why assigning to foo inside bar overwrites the reference to the foo function declared in bar, instead of assigning to the variable in the outer scope. foo is effectively a local variable in bar, even though it's not declared with var, because of the function declaration.
This has to do with a concept called hoisting. function foo is essentially just an alternative syntax for var foo = function .., so inside bar the name foo does not refer to the outer foo variable but to a locally defined foo. This foo is first a function, but later gets overwritten by 10.
Now, through hoisting the name foo is "reserved" and scoped at parse time, before the code executes. Essentially, it executes like this:
function bar(){
var foo = function () {};
foo = 10;
return;
}
Hence it does not overwrite the outer variable at all.

Javascript Scope/Closure: Why can I access internal vars here?

I am currently working on a relatively simple project and discovered something:
var test = (function() {
var internal = 5;
return {
init: function() {
$(document).on('click', function() {
alert(internal);
});
}
};
}());
test.init();
I thought closure and javascript scope (as I understood it) meant that a function can only access its own variables, and those 1 level above it. So Why does this work? When I click on the document I get an alert of "5", I expected to get undefined.
Here is a JSFiddle showing what I'm doing:
http://jsfiddle.net/mcraig_brs/m644L/1/
I thought closure and javascript scope (as I understood it) meant that a function can only access its own variables, and those 1 level above it.
Nope, it's all levels above it. In fact, that's how global variables work in JavaScript; they're just an example of closures in action.
So Why does this work?
When the JavaScript engine needs to resolve a symbol, it looks first (loosely) in the execution context that the symbol appears in (in this case, the one created by the call to the anonymous function you're passing into on). If it doesn't find a matching variable there, it looks at the execution context that surrounds that one (in this case, the one created by calling init). If it doesn't find it there, it looks at the next one out (the one created by calling your outermost anonymous function). And if not there, the next level out, until it reaches the global execution context.
More about closures (on my blog): Closures are not complicated
Note that I kept saying "...created by the call to..." above. This is a critical point: There can be (almost always are) multiple execution contexts created for a given scope as a program runs. Consider:
function foo(name) {
return function() {
alert(name);
};
}
(This is only two levels again, but it applies to as many levels as you like.)
foo, when called, creates and returns a function that, when called, shows us the name that was passed into foo when that function was created:
var f1 = foo("one");
var f2 = foo("two");
f1(); // "one"
f2(); // "two"
Calling foo creates an execution context. The function foo creates has an enduring reference to the part of that context that contains variables for that call (the spec calls it the "variable binding object"). That binding object still exists after foo returns, which is why when we call the function foo creates, it still has access to the relevant name variable.
It's important to remember that it isn't that closures get a copy of the value of the variable. They get an enduring reference to that variable. Which is why this works:
function foo(a) {
return function() {
alert(++a);
};
}
var f = foo(0);
f(); // 1
f(); // 2
f(); // 3
Javascript is statically scoped. when you are writing a function, you will have access to all the variables available to you inside the function as they are available from where you are accessing it.
var a = 10;
function foo() {
// now i have access in a
var b = 20;
// i have access to both a and b
function bar() {
// still have access to both a and b
var c = 30;
// any more nested function will have access to a,b and c
}
}

Two functions with the same name in JavaScript - how can this work?

As far as I know, function foo() { aaa(); } is just var foo = function(){ aaa() } in JavaScript. So adding function foo() { bbb(); } should either overwrite the foo variable, or ignore the second definition - that's not the point. The point is that there should be one variable foo.
So, in this example the me variable should not be correctly resolved from inside the methods and it is not in Explorer 8 :-). I came to this example by trying to wrap them into another closure where (var) me would be, but I was surprised that it's not necessary:
var foo = {
bar1 : function me() {
var index = 1;
alert(me);
},
bar2 : function me() {
var index = 2;
alert(me);
}
};
foo.bar1(); // Shows the first one
foo.bar2(); // Shows the second one
Demo: http://jsfiddle.net/W5dqy/5/
AFAIK function foo() { aaa(); } is just var foo = function(){ aaa() } in JavaScript.
Not quite; they're similar, but also quite different. JavaScript has two different but related things: Function declarations (your first example there), and function expressions (your second, which you then assign to a variable). They happen at different times in the parsing cycle and have different effects.
This is a function declaration:
function foo() {
// ...
}
Function declarations are processed upon entry into the enclosing scope, before any step-by-step code is executed.
This is a function expression (specifically, an anonymous one):
var foo = function() {
// ...
};
Function expressions are processed as part of the step-by-step code, at the point where they appear (just like any other expression).
Your quoted code is using a named function expression, which look like this:
var x = function foo() {
// ...
};
(In your case it's within an object literal, so it's on the right-hand side of an : instead of an =, but it's still a named function expression.)
That's perfectly valid, ignoring implementation bugs (more in a moment). It creates a function with the name foo, doesn't put foo in the enclosing scope, and then assigns that function to the x variable (all of this happening when the expression is encountered in the step-by-step code). When I say it doesn't put foo in the enclosing scope, I mean exactly that:
var x = function foo() {
alert(typeof foo); // alerts "function" (in compliant implementations)
};
alert(typeof foo); // alerts "undefined" (in compliant implementations)
Note how that's different from the way function declarations work (where the function's name is added to the enclosing scope).
Named function expressions work on compliant implementations. Historically, there were bugs in implementations (early Safari, IE8 and earlier). Modern implementations get them right, including IE9 and up. (More here: Double take and here: Named function expressions demystified.)
So, in this example the me variable shoudl not be corectly resolved from inside the methods
Actually, it should be. A function's true name (the symbol between function and the opening parenthesis) is always in-scope within the function (whether the function is from a declaration or a named function expression).
NOTE: The below was written in 2011. With the advances in JavaScript since, I no longer feel the need to do things like the below unless I know I'm going to be dealing with IE8 (which is very rare these days).
Because of implementation bugs, I used to avoid named function expressions. You can do that in your example by just removing the me names, but I prefer named functions, and so for what it's worth, here's how I used to write your object:
var foo = (function(){
var publicSymbols = {};
publicSymbols.bar1 = bar1_me;
function bar1_me() {
var index = 1;
alert(bar1_me);
}
publicSymbols.bar2 = bar2_me;
function bar2_me() {
var index = 2;
alert(bar2_me);
}
return publicSymbols;
})();
(Except I'd probably use a shorter name than publicSymbols.)
Here's how that gets processed:
An anonymous enclosing function is created when the var foo = ... line is encountered in the step-by-step code, and then it is called (because I have the () at the very end).
Upon entry into the execution context created by that anonymous function, the bar1_me and bar2_me function declarations are processed and those symbols are added to the scope inside that anonymous function (technically, to the variable object for the execution context).
The publicSymbols symbol is added to the scope inside the anonymous function. (More: Poor misunderstood var)
Step-by-step code begins by assigning {} to publicSymbols.
Step-by-step code continues with publicSymbols.bar1 = bar1_me; and publicSymbols.bar2 = bar2_me;, and finally return publicSymbols;
The anonymous function's result is assigned to foo.
These days, though, unless I'm writing code I know needs to support IE8 (sadly, as I write this in November 2015 it still has significant global market share, but happily that share is plummetting), I don't worry about it. All modern JavaScript engines understand them just fine.
You can also write that like this:
var foo = (function(){
return {
bar1: bar1_me,
bar2: bar2_me
};
function bar1_me() {
var index = 1;
alert(bar1_me);
}
function bar2_me() {
var index = 2;
alert(bar2_me);
}
})();
...since those are function declarations, and thus are hoisted. I don't usually do it like that, as I find it easier to do maintenance on large structures if I do the declaration and the assignment to the property next to each other (or, if not writing for IE8, on the same line).
Both me lookups, are only visible/available inside the function expression.
Infact those two are named function expressions, and the ECMAscript specification tells us, that the name of an expression is not exposed to the such called Variable object.
Well I tried to put that only in a few words, but while trying to find the right words, this ends up in pretty deep chain of ECMAscript behavior. So, function expression are not stored in a Variable / Activation Object. (Would lead to the question, who those guys are...).
Short: Every time a function is called, a new Context is created. There is some "blackmagic" kind of guy that is called, Activation object which stores some stuff. For instance, the
arguments of the function
the [[Scope]]
any variables created by var
For instance:
function foo(test, bar) {
var hello = "world";
function visible() {
}
(function ghost() {
}());
}
The Activation Object for foo would look like:
arguments: test, bar
variables: hello (string), visible (function)
[[Scope]]: (possible parent function-context), Global Object
ghost is not stored in the AO! it would just be accesssible under that name within the function itself. While visible() is a function declaration (or function statement) it is stored in the AO. This is because, a function declaration is evaluated when parsing and function expression is evaluated at runtime.
What happens here is that function() has many different meanings and uses.
When I say
bar1 : function me() {
}
then that's 100% equivalent to
bar1 : function() {
}
i.e. the name doesn't matter when you use function to assign the variable bar1. Inside, me is assigned but as soon as the function definition is left (when you assign bar2), me is created again as a local variable for the function definition that is stored in bar2.

Categories

Resources