I have recently been trying to learn javascript and have a couple of questions.
When you create a function expression:
var greet = function(){
console.log('Hi');
}
Is that creating a function object and having the variable "greet" point to that function object in memory?
My second question if you have a function like this:
function log(a){
console.log(a);
}
Then you make a call to that function:
log(greet); //greet is the function expression declared above.
So I know that when a function object is created there are two properties that are given to the object. The name (if provided, otherwise anonymous) and a code property which stores the code contained inside the parentheses of the function. Now I am a little confused on where the parameter "a" in the log function gets attached to in a function object. Is "a" just another property of the function object log and it simply just points to the memory address of anything that is passed into the log function? Where in this case it was a function expression called greet. Any input would be appreciated. Thank you!
When a function is called as in:
log(greet)
then the identifier log is resolved in the current execution context and, if not found, is searched along the scope chain, ending at the global execution context. If not found, an error is thrown.
In this case, log has been defined using a function declaration so it exists in the global scope so is found. Its value is checked to make sure it's callable (again, if not, an error is thrown) if it is, it's called.
In the call, the identifier greet is resolved and its value passed to the function. If greet can't be resolved (i.e. it doesn't exist on the scope chain), an error is thrown. In this case, it resolves to a reference to the function assigned to greet.
When log is executed, a new execution context is created. The function declaration for log defines a formal parameter a (in its formal parameter list), so a is created as a local variable for log. The values in the call are passed to identifiers in the formal parameter list in order, so the value of greet is assigned to a. Note that initialisation and creation of a new execution context occurs every time a function is called.
The same process is followed when calling:
console.log(a);
so that within console.log, the reference to greet is passed as the first parameter, so it now references the greet function.
The behaviour of console.log is entirely implementation dependent so the internals are unknown, but for functions most tend to just call the function's toString method.
It's a handy feature of ECMAScript that an arguments object is created of the arguments passed to functions, so the values passed are always available as numeric properties of the arguments object if there is no parameter for them to be assigned to. So console.log doesn't have to define any formal parameters, it can just loop over its arguments object and process the passed values in turn.
Related
When function foo is invoked, the [[Call]] method is called and an execution context is created. IIUC, as part of the creation of the execution context, an environment record for str is created and added to the lexical environment within the execution context.
So I "know" how JavaScript logically keeps track of str.
When control moves to the line with the anonymous function expression, a function object is created, and then executed. Does the specification define a position in the execution context to store a reference to such a function object, or, does it not, because the function object is part of an expression and a reference to it is simply thrown away, unless it is assigned to something with a name?
In this instance, there is presumably a logical period when the anonymous function object exists, but has not yet been invoked as part of the IIFE, so a reference to the function object might be expected to exist for this short period, or is the IIFE indivisible?
function foo() {
const str = 'foo';
(function() { })();
}
foo()
Does the specification define a position in the execution context to store a reference to such a function object
No.
the function object is part of an expression and a reference to it is simply thrown away, unless it is assigned to something with a name?
Precisely that.
there is presumably a logical period when the anonymous function object exists, but has not yet been invoked as part of the IIFE, so a reference to the function object might be expected to exist for this short period, or is the IIFE indivisible?
Well, the reference to the function exists inside the expression interpreter of course, somewhere in RAM the engine keeps a pointer to the object. But no, this has nothing to do with the scope that the expression is evaluated in, it does not create a variable binding for it.
From a JS perspective, the expression is indivisible, you cannot inspect its state anyhow without changing the expression.
I have heard different opinions about the usage of var at a situation like this:
function(maybeUndefined) {
if(typeof maybeUndefined === 'undefined')
var maybeUndefined = 'bob';
}
Is it necessary to notate var, or not, because maybeUndefined is an argument of function?
You do not need the var in this case, as mayBeUndefined is already allocated within the scope of the function (hint: listing argument variables in a function definition causes those variables to be declared locally). That var is therefore completely optional, though completely pointless (and a drain on readability).
Example:
function func ( arg1, arg2 ) {
var local1, local2;
function nested1 () {}
function nested2 () {}
// other code
}
Here we have a function declaration. When this declaration is parsed into a function object, a lexical environment (= scope) is created for that function with the following bindings:
arg1
arg2
local1
local2
nested1
nested2
this
arguments
(Notice how there also are two special, built-in bindings: this and arguments. These are always created for all function objects.)
These names are defined as local bindings. (This process is specified in "Declaration binding instantiation". Warning: this algorithm is not meant to be read by humans :-)) Therefore, when a name is defined as a parameter, it is not necessary to declare it as a local variable. This mechanism is independent of whether a value (argument) is passed for that parameter when the function is invoked.
So, even if you invoke the function like so:
func(123);
the name arg2 will still be defined (as a binding in the function's environment), although its value will initially be undefined for that particular invocation.
Btw, if you use the strict language (recommended!), function environments are static which means that the above bindings are garanteed to be the only bindings in the function's environment. The default language, on the other hand, provides certain mechanisms to, dynamically, add/remove bindings from the function's environment. Example:
(function () {
// the name "temp" does not exist as a binding in the function's environment
eval('var temp');
// now it does
delete temp;
// and it's gone again
}());
You should not use var again, it is bad for readability, and the variable will already be scoped locally as a result of being an argument.
Also, you should note that it is not a part of this. this will only be scoped to the function object if the new keyword has been used, and as you do not have a named function, that seems unlikely in this case. Without new, this refers to window (or is undefined if use strict; is used), of which your variable is definitely not a part of as a result of the argument having a local scope.
Interfacing
Including a function argument is effectively the same as scoping a variable (in other words, it's effectively the same thing as defining a function-level reference using the var keyword). The main reason for providing function arguments (in JavaScript) is for your own interfacing preference.
The arguments object
Arguments may still be passed to functions without parameters, and will still be accessible in the 'hidden' arguments object -- which is sort of a "pseudo-array" (if you will), in that it is functionally an array, but is not equipped with the same APIs JavaScript equips the Array (pseudo-type) with:
// The following functions do the same thing, but one is "more readable"
function foo() {
return arguments;
}
function bar(baz, qux) {
return arguments;
}
Evaluation (interface) vs Execution (implement)
When both functions are evaluated (on file 'load'), the arguments object is undefined in every function definition; the object doesn't become "defined" until the function body executes the code therein; to visualize that using pseudo-code, it'd look something like this:
// Function bodies (as objects)
foo : {
arguments : new Array // [undefined]
__proto__ : Empty() // the super-object that allows this object to inherit "functionality"
}
bar : {
arguments : new Array(baz, qux) // [undefined, undefined]
__proto__ : Empty()
}
Function invocation
So when you invoke a function, it "implements" or "executes" its body (its "object"). When it does that, if the objects that have been pushed into the arguments object are defined, then the function can reference them. If not, a reference error will be thrown, logging that the variables are undefined in that scope.
In short:
It isn't necessary to interface function-scope-level variables (aka "private members") using var because the language already attaches the arguments object to all function body objects.
More reading:
JavaScript Memoization: "Function-caching" multiple arguments for better performance:
http://decodize.com/javascript/javascript-memoization-caching-results-for-better-performance/
Consider the following snippet of JavaScript:
function outer() {
var x = 10;
function inner() {
var y = 20;
}
}
Obviously, the variable y is not available in the context of outer. Following through the process in the ES5 spec tells us that this is what happens when we enter the outer execution context:
We enter a new execution context (10.4)
Since it's a function, we follow the steps outlined in Entering Function Code (10.4.3)
Let code be the value of F’s [[Code]] internal property.
The [[Code]] internal property of a function is described in Creating Function Objects (13.2). It refers to the FunctionBody as specified by the grammar (the entire contents of the function):
function Identifier ( FormalParameterListopt ) { FunctionBody }
At this point we enter the Declaration Binding Instantiation (10.5) section and do the following:
Create bindings for any arguments in the formal parameter list of the function
For each function declaration in code:
Create a binding in the current scope between function identifier and a Function object (created as specified in Function Definition (13))
There is nothing to say "remove the function we've just processed from code"
Create a binding for the arguments object
For each variable declaration in code:
Create a binding in the current scope for the variable identifier
My question is why, at this point, are bindings not created for variable declarations from inner functions? It seems like code should still contain the entire source text of the outer function (which would include the source text of the inner function). I'm looking for something in the spec which explains the behaviour.
Updated, to be a bit clearer: I am asking about what happens when we enter the context of the outer function. The inner function is never called, and I don't care about what happens when we return from the outer function. I am purely interested in the process, as defined by the spec, of creating bindings for variable declarations when entering a new execution context.
You have a error in your thinking.
Javascript has function-scope. Thus you have a new execution context for each function, thats true. However, after you return from a function this function context expires. That is the reason why you can't access the variables from the inner function after it has returned. You still are in the execution-context of the outer-function but you can't access the execution-context of the inner function anymore.
Citing the spec:
Every return exits an execution context. A thrown exception may also exit one or more execution contexts.
EDIT: To clarify this further: The body of a function declaration is NOT being processed (see 10.5.5.d), only the function identifier and the arguments are passed to the variable environment.
It's right there in the definition of the term code (§10.1):
Function code is source text that is parsed as part of a FunctionBody. The function code of a particular FunctionBody does not include any source text that is parsed as part of a nested FunctionBody.
What is the calling context of an invoked method or function within another function?
In browsers, the default calling context is the window object. In various situations, how do I avoid this?
If a function is invoked -- for example, by theFunction(); -- within a containing function, is the invoked function's calling context the containing function?
In these two examples
(function ()
{
something.initialize();
}());
and
(function ()
{
something.initialize.call(this);
}());
..., is the calling context the same?
They are not the same. In the following I assume you were talking about this when you mentioned context.
In the first example, inside initialize, this will refer to something. In the second one, it will refer to the global object, which is window in browsers.
What this refers to is determined by how the function was called. There are five cases:
func(), calling a function "standalone": this refers to the global object.
new func(), calling a function as constructor method: this will refer to an empty object which inherits from func.prototype.
obj.func(), calling a function as property of an object: this will refer to the object obj.
func.apply(foo), func.call(foo), invoking a function with apply or call: this refers to the object passed as first argument.
ECMAScript 5 also introduced .bind() [MDN] which enables you to bind this to a certain object, without immediately calling the function.
Now you understand why in your second example, inside initialize, this will refer to window:
The outer function is called "standalone" (first case), so this inside of it will refer to window. Next you are passing this to call, which sets this inside initialize to window (fourth case).
Further reading:
MDN - this, explains all I write above with some examples.
No, they are not the same. The first parameter to the call method sets the value of this inside that function; example 1's this should theoretically contain a reference to something; example 2's this corresponds to the this of your self executing function.
The environment available to a function when it is invoked is based on several things.
the this binding which is different for the initialize method in your example
the actual parameter bindings which are not and a binding for a special arguments object
a binding for the function name, if any
the environment chain at the time the function was created. This is the "close" part of the term "closure". A javascript function "closes over" all the variables that are in-scope when the function object comes into existence.
In your example, only 1 is affected by the choice to use call which has the effect of passing this instead of something as the this value in the method body.
The relevant part of the spec starts at section 10.4.3
The following steps are performed when control enters the execution context for function code contained in function object F, a caller provided thisArg, and a caller provided argumentsList: ...
Functions don't create context, unless it's a constructor (a function called with new).
In your second example the context is undefined (which gets transformed into the global object , window). In ES5 strict mode it won't be transformed into anything.
I recommend John Resig's interactive JavaScript tutorial on the topic of context.
Based on some code in a lecture by Doug Crockford, I've created this.
var isAlphaUser = (function() {
alert("Forming Alpha User List");
let AlphaUsers = {
1234: true,
5678: true
};
return function(id){
alert("Checking Alpha Users:",id);
return AlphaUsers[id];};
}());
alert("starting");
alert(isAlphaUser(1234));
alert(isAlphaUser(5678));
alert(isAlphaUser(3456));
which gives me this:
Forming Alpha User List
starting
Checking Alpha Users: 1234
true
Checking Alpha Users: 5678
true
Checking Alpha Users: 3456
undefined
Which is quite cool, as it does the expensive setup once only, and every further call is a cheap check.
However, I can't decipher the code that does this. Specifically, I can't understand why I need the "()" at the end of the function declaration.
Can somebody explain how this syntax is working?
() calls a function. function() { } defines a function. Appending () right after immediately calls it1, and the result (also an anonymous function) is assigned to isAlphaUser.
The function() { ... }() pattern is frequently used to isolate variables to an inner scope, so those variables don't become part of the global scope.
In this case, this is what happens:
An anonymous function is run, defining a variable AlphaUsers inside that scope.
That function returns another function that takes 1 parameter. This function is a closure to which the AlphaUsers variable becomes bound (in other words, available). This function checks if the parameter passed in is contained in AlphaUsers (actually, it returns the item at that index, which is just a boolean).
The return value is assigned to a variable isAlphaUser.
Since isAlphaUser is now a function, it can be called to see if the parameter is contained in the AlphaUsers variable, but no direct access to AlphaUsers is available in the global scope (it become a sort of private variable).
1 — Note: As cwolves mentioned in the comments, beware that while () appended directly after the } works in this case, it is only because in this case the function definition is a function expression. If function is the first word on the line, the line becomes a function declaration, and that is all that line can do, the function is not anonymous (it will require a name, otherwise it's a syntax error) and cannot be called immediately inline. See Function Declarations vs. Function Expressions for more info.
The () at the end of the code is separate from the closure issue. By wrapping your function in parens and adding the () at the end you are creating an anonymous function that is run immediately with whatever arguments you pass into ().
Specifically, I can't understand why I need the "()" at the end of the
function declaration.
It creates self-invoking function, in other words, the function is executed as soon as it is parsed.
It is basically same thing when you call a function by suffixing it with () like:
myfunc(); // call this func
The top-level anonymous function returns the function that the isAlphasUser varaible refers to.
You need to call the top-level function, to get the inner-function reference.
Think of it like this, the outer anonymous function is a function factory, i.e., it returns a function.
In order to use any function (even one that returns a function) you must call it.