dynamic scope and `this` in Kyle Simpson's YDKJS - javascript

In his (great) series of books “You don't know JS", Kyle Simpson states that dynamic scope and this mecanism are "near cousin", he also says that :
"the this mechanism is kind of like dynamic scope."
(YDKJS, Scope and Closure, Appendix A)
What is preventing him from saying that this is plain and simple dynamic scoping ?
Also, in the book "this & Object Prototypes", also part of the series YDKJS, as far as I can say, Kyle is not mentioning once dynamic scope while discussing how thisis working, so I am a bit surprised why he decided to not go further in the analogy... Does anyone have an idea why ?
Thanks

The reason I claim this is just "kind of like" a dynamic scope and not actually a dynamic scope is based on these two observations:
The aesthetic of accessing the "scope context" explicitly with an object reference (this.foo = 1) is distinct from implicitly accessing it via lexical variable reference (foo = 1). At best, this makes the two systems of "scope" parallel, not the same. But there's more different than what it seems on the surface!
But more importantly, dynamic scopes are traditionally defined as scope chains that are based on the call-stack. That is, a dynamic scope is one where the decision of what "scope contexts" to consult, in order, is exactly the current stack of function calls. But this isn't based on the call-stack, per se, but rather just the manner in which the most recent call in the stack was made, only.
Consider this scenario: foo() calls bar(), bar() calls baz(), and in baz() a reference is made to an x variable that is not defined in baz().
In lexical scope, the lookup would be baz(), then whatever the outer scope of baz() is, and so on. bar() and foo() wouldn't be consulted at all, unless they happened to be the lexically surrounding scopes of baz().
In dynamic scope, the call stack foo() -> bar() -> baz() is the scope chain, so baz() is consulted, then bar(), then foo(), regardless of where those 3 functions exist lexically in the code base.
Now, consider the same scenario, but this.x is the reference made inside baz(). The call stack foo() -> bar() -> baz() is not particularly relevant in resolving this.x. Rather, the only thing that matters is how baz() was invoked. If the call site is baz(), the "default binding" rule applies. If it's this.baz(), the "implicit binding" rule applies. If it's baz.call(..), the "explicit binding" rule applies. And if it's new baz(), the "new binding" rule applies. That's it.
Actually, it's not the only thing, it's just the first decision that's made. Once it's determined what object (aka scope context object) this points to, now the only thing that matters is the prototype chain of that object, as that's the "scopes" that will be consulted, in order of the prototype chain linkage.
Summary:
In lexical scope, where a function is defined is the only thing that determines what contexts are used, and in what order, to resolve a variable reference.
in dynamic scope, where a function is called from is the only thing that determines what contexts are used, and in what order, to resolve a variable reference.
in this-based context, neither where a function is defined nor where it's called from are relevant. Therefore, this is neither lexical scoping nor dynamic scoping.
The only thing that matters here is how the current function in the call stack (top of the stack) was called. Well, that's the only thing that matters to determine which scope chain to start the lookup on. But once that object is decided, it's now that object's prototype chain that entirely defines the scope resolution.

Because the this "variable" is the only variable that has dynamic scope, all other ("real") variables have lexical scope in JavaScript. In contrast, in "plain and simple dynamic scoping", all variables have dynamic scope and you can't get away from it (which is really ugly). So when we want to have multiple values in our dynamic scope, we store them in an object, and access them as properties of the this object, which is quite different from dynamic scope and also involves object inheritance.

Related

Different scoping in Javascript - Lexical vs Dynamic

I was going through the scoping concept and I found out that it is possible to implement both lexical and dynamic scope. Can any one help me to understand what is the major difference between Lexical and Dynamic scope in accordance of JavaScript?
Also how can we implement it in JavaScript?
In lexical scoping, the variable can be called only from within the block of the code which it is defined. The scope of that variable is defined when the program is compiled. The variable can be accessed by its children's execution contexts. But it doesn't work backward to its parents, meaning that the variable likes cannot be accessed by its parents.
In dynamic scope, the variable declared can be called from outside the code block. In this, the compiler will search for the variable reference in the local function first, then it searches in the function that called the local function, then it searches in the function that called that function, and so on, up the call stack. "Dynamic" refers to change, in that the call stack can be different every time a given function is called, and so the function might hit different variables depending on where it is called from.
http://wiki.c2.com/?DynamicScoping

Is a Java lambdas equivalent to a JavaScript closures?

I started learning about functional programming and I'm a bit confusing about it.
My question is: is Java lambdas equivalent to JavaScript closures? If not, what is the difference between them?
They are "slightly different" and also "roughly equivalent".
tldr; a Java lambda that access an outer-scoped variable1 is also a closure; and a JavaScript "closure" that does not access an outer-scope variable is not strictly a closure (and can be more precisely called an anonymous function2).
In JavaScript, a closure generally implies "being able to re-assign variables in the outer scope" - however, having access to or "closing over / binding" a variable is sufficient for an anonymous function to be a closure3.
Java lambda's requires that all variables from the outer scope accessed in a lambda are effectively final which means they cannot be re-assigned.
1The rule is that a [Java] lambda expression can only access local variables from an enclosing scope that are effectively final. An effectively final variable is never modified—it either is or could be declared as final - http://www.informit.com/articles/article.aspx?p=2303960
However, since a Java lambda can capture a read-only variable binding to mutable objects, it is possible for a Java lambda to indirectly modify state in the outer context and can thus emulate the ability to "re-assign" values.
2In computer science, a closure is a function that has an environment of its own. Inside this environment, there is at least one bound variable [and] anonymous functions are sometimes wrongly called closures. This is probably because most languages [eg. JavaScript] that have anonymous functions also have closures and it's common for programmers to learn about both at the same time. - https://simple.wikipedia.org/wiki/Closure_(computer_science)
Java also has different semantics on this inside a lambda vs a JS anon-function / closure; also see JavaScript "arrow functions" which have different rules than traditional anonymous functions on how this behaves.
3 Trivial argument:
Haskell has closures.
Haskell does not allow variables to be re-assigned.
Therefore, re-assignment (or mutability) is not a requirement of closures.
No, they are not equivalent. One has to do with syntax and the other with memory.
Lambdas are a short-hand syntax for declaring anonymous code structures.
Closures are when a nested function (named or not) holds a reference to a variable from a function in an outer scope. That, in and of itself isn't really an issue. But, when the nested function persists longer than the outer scoped variable, the variable won't be garbage collected when the outer scope terminates. That's when closures become either very powerful or very annoying. It all depends on if you are intentionally using them or not. Closures can allow for shared access to private data.

Why hoist variables when there is TDZ

The ES6 standard comes up with Temporal Dead Zones, making a variable reference not possible in any way until the lexical binding is evaluated. So what does variable creation at the time of lexical environment initialisation mean to
The programmer ?
The Compiler ?
The declaration of a variable using var declaration might mean something to the programmer previously, but now with TDZ in place does javascript start behaving like java for this purpose? Is there any reason other than the way javascript interpreter works that we have hoisting (as a result TDZ) in the first place?
What happens when a lexical binding is encountered later in the code due to order of execution even when the code appears before it lexically?
let abc = f();
let b;
f(){ return b;}
When does traditionally programming languages like java create variables? When the variable declaration is encountered? or when the lexical scope is initialised?
I have a feeling that the creation of TDZ had to do with it being a very menial step from var, whereas if they were to go with the seemingly more logical approach of not even having the identifier exist, the engine would have had to undergo even more intensive changes. As for the second part of your question in reference to when other languages "create" variables, there are many other important factors to consider that you seem to have left out, such as is the language interpreted vs compiled, as well as there are multiple different steps to "creating" a variable. It acts differently in many different cases, and there is no single answer. In fact, that is one of the big reasons why there are many different languages.
As for your coding question, it would depend on when you're calling your f function, since function declarations are hoisted in javascript. If you are calling it before b is declared, then you are in a TDZ and b cannot be referenced. It will behave very similarly as if you were simply putting the return b wherever this function is called.
Honestly, it seems as if there is some underlying misunderstanding of javascript, and computer languages in general. Javascript is not "behaving" more like java, in fact the new let keyword has very nuanced behavior, such as being able to be block scoped, compared to type/variable declarations in java. I would suggest not trying to think of the changes in ES6 in terms of other languages; javascript is not like a lot of other languages, it will be very difficult to understand the concepts and how you should be programming with javascript if you do.
EDIT:
As for why there is variable and function declaration hoisting, that is easily googlable.
So what does variable creation at the time of lexical environment
initialisation mean to the programmer?
Not much. A programmer only intends to use declared and initialised variables.
That the variable is available in the whole scope (from the beginning) only means that mistakes will be caught easier, as the usage of the variable prior to initialisation fails (with an exception) instead of silently being resolved to an outer-scope (global?) variable. It also means that the identifier, regardless where in the scope it is used, always refers to the local variable - which is just what we'd expect from a scope.
So what does variable creation at the time of lexical environment
initialisation mean to the Compiler?
That a lexical environment doesn't change its structure during execution. Static resolution of identifiers in a known scope makes compiling possible, and execution faster.
Just as a counterexample, consider this thing:
var x = "global";
var code = "var x = 'local';";
(function() {
"use sloppy";
function test() {
console.log(x); // what do you think does `x` refer to?
} // It's hard to understand as a developer,
// now imagine being a compiler that tries to optimise `test`.
test();
eval(code);
test();
}());
What happens when a lexical binding is encountered later in the code
due to order of execution even when the code appears before it lexically?
b is used by the call to f() before it's initialised. Accessing it throws a TDZ exception.
You can try it online.

Why is an execution context not created here?

Writing the following will result in the evaluation of the Function constructor function, resulting in the presence of a property on the global object pointing to a function-object instance Foo.
function Foo() {}
Execution contexts are created when functions are invoked, hence has an execution context other than the global one been created even without invocation of Foo?
My thinking is as follows:
Everything is an object in JavaScript (with minor exceptions related to primitives). Objects are created by functions. Foo is an object. A function has been invoked.
Answering my own question, based on the long comment list above.
No execution context is created because execution contexts are only meaningful for user-defined code. For the internal operation of a JavaScript engine, such as the precise mechanism for the creation of the function-object Foo in the code in the question, are left to engine implementers.

What is the difference between a closure and an anonymous function in JS

What is the difference between a closure and an anonymous function in JavaScript
The closure mechanism applies to all JavaScript functions, whether anonymous or not.
I think confusion between the two concepts comes from use of the term "closure" where an author has said something like "the following code creates a closure" and then given an example that happens to use an anonymous function. In such instances typically the closure mechanism is what is important to make the particular piece of code work as intended, while use of an anonymous function rather than a named function just happens to be a convenient way to code it. People reading such examples and seeing "closure" for the first time then misinterpret the term and go on to use it incorrectly in their own Stack Overflow or blog posts and so the confusion spreads.
A closure is an expression relying on a namespace reference in which variables are resolved (a context). An anonymous function is one way to form a closure in Javascript - a named function is another.
There is some discussion about the ability to form closures with non-function blocks, but the current standards specify no such.
http://jibbering.com/faq/notes/closures/ is a pretty good description.
A closure is a function that has captured its environment (the variables that it has access to)
It can be created both from an anonymous and as from named function.
And an anonymous function differs from a named function mainly that it's declaration does not get hoisted to top of the scope.

Categories