This may be a silly question, but why are function arguments in JavaScript not preceded by the var keyword?
Why:
function fooAnything(anything) {
return 'foo' + anyThing;
}
And not:
function fooAnything(var anything) {
return 'foo' + anyThing;
}
I have a feeling the answer is because that's what the Spec says but still...
Most dynamicaly-typed programming languages don't have explicit vars in the argument list. The purpose of the var keyword is to differentiate between "I am setting an existing variable" and "I am creating a new variable" as in
var x = 17; //new variable
x = 18; //old variable
(Only few languages, like Python, go away with the var completely but there are some issues with, for example, closures and accidental typos so var is still widespread)
But in an argument list you cannot assign to existing variables so the previous ambiguity does not need to be resolved. Therefore, a var declaration in the arguments list would be nothing more then redundant boilerplate. (and redundant boilerplate is bad - see COBOL in exibit A)
You are probably getting your idea from C or Java but in their case type declarations double up as variable declarations and the cruft in the argument lists is for the types and not for the declarations.
We can even get away with a "typeless, varless" argument list in some typed languages too. In Haskell, for example, types can be inferred so you don't need to write them down on the argument list. Because of this the argument list consists of just the variable names and as in Javascript's case we don't need to put the extraneous "let" (Haskell's equivalent to "var") in there:
f a b = --arguments are still variables,
-- but we don't need "let" or type definitions
let n = a + b in --extra variables still need to be declared with "let"
n + 17
It would be a redundant use of the var keyword. Items that appear in the parentheses that follow a function name declaration are explicitly parameters for the function.
The var keyword declares the scope of the variable. A function argument also introduces the scope for that argument. Hence there's no need for it, since it serves the same function.
I think the question comes up because we're used to seeing function bla (int i) in many languages. The same, syntactically, as the int i; somewhere in the function body to declare a variable. The two ints are however not doing the same; the first defines the type, the second defines type and the scope. If you don't have to declare the type, the scope-declaration still needs to happen (which is why we have var in the second case) but there is no information needed in front of arguments.
Related
I have this problem on freeCodeCamp as I'm learning JavaScript.
I'm trying to understand this block of code.
function multiply(arr, n) {
if (n <= 0) {
return 1;
} else {
return multiply(arr, n-1)*arr[n-1];
}
}console.log(multiply([2,2,4],3));
As a whole, I understand what this code above does. But not this line below.
multiply(arr, n-1)*arr[n-1];
There's already a about post this specific problem here, but I have read all of the comments and I did not understand.
What I don't understand specifically is (arr, n-1). Exactly what does that do? The rest of the line I can understand after a long time thinking, it's just that little piece that I can't make sense of.
What I don't understand specifically is "(arr, n-1)". Exactly what does that do?
This is the argument list for the function call of the multiply() function. You cannot understand this in isolation because it belongs to the function call.
In other words, the syntactic element is not (arr, n-1), it is multiply(arr, n-1).
A parameter is kind of like a "hole" that you leave in a function definition. Parameters allow you to make functions re-usable in different contexts.
For example, a function like this:
function doubleTheValueSix() {
return 2 * 6;
}
is not very useful because it can be used for only one very specific thing. However, we can make it more useful by parameterizing it:
function doubleAnyArbitraryValue(n) {
return 2 * n;
}
is much more useful. Here, n is called the parameter and (n) is called the parameter List. In this case, there is only one parameter in the parameter list, but there can be arbitrary many, including – as we have seen above – zero.
An argument is what you pass to a function call to "fill in" the "hole" left by the parameter in the function definition.
So, in this code here:
doubleAnyArbitraryValue(42)
The literal 42 is the argument which gets bound to the parameter n inside the function body of doubleAnyArbitraryValue. In other words, everywhere n appears in the function body, it gets replaced with 42.
So, in this case, 42 is the argument and (42) is the argument list.
What this means in your particular code snippet is the following:
Look up the name multiply in the local scope. It could be a function defined in the local scope (or in an enclosing scope), a const, a let, or a var defined in the local scope (or in an enclosing scope).
Call the object you found in step #1, passing the result of evaluating the expressions in the argument list as arguments:
Evaluate the expression arr (which essentially means: look up the name arr in the local scope; it could be a const, a let, or a var defined in the local scope (or in an enclosing scope)).
Evaluate the expression n-1:
Look up the name n in the local scope; it could be a const, a let, or a var defined in the local scope (or in an enclosing scope).
Apply the Binary Arithmetic Subtraction Operator - to the result of step 2.1.1 and the Numeric Literal 1.
You can find the details about how function calls work in subsection 13.3.6 Function Calls of the ECMAScript Language Specification. (Note, the version I linked to is the Living Document which always shows the current state of the next release, but that doesn't matter in this case – how function calls work fundamentally hasn't changed since ECMAScript was still called LiveScript in 1995 and even before that when it was still called Mocha.)
MDN documentation states:
let bindings are created at the top of the (block) scope containing
the declaration, commonly referred to as "hoisting". Unlike variables
declared with var, which will start with the value undefined, let
variables are not initialized until their definition is evaluated.
Accessing the variable before the initialization results in a
ReferenceError. The variable is in a "temporal dead zone" from the
start of the block until the initialization is processed.
Is the "let binding" referrred to (the hoisting of let and const) just the keyword let, or is it just the creation of storage space (which doesn't have to do with the keyword)?
Previously I thought the variable keyword and variable name together comprised a declaration, but in a question I asked recently, the answerer said they are actually an initialization.
I'm sorry for using two different terms when writing that MDN paragraph. For all purposes in that article, "variable" and "binding" should be understood as the same thing. But let's go into details.
A variable declaration creates the variable (as an abstract entity). It tells the compiler that it should introduce a new variable, and also can tell it about a name, a type to be held, an initial value, a scope etc. (depending on the language). In JS, there are different kinds of declarations that do different things, for example
var has a name, an optional initialiser and scoping rules specific to var
function has a (sometimes optional) name, the value is always given and known to be a function
const has a name, a required initialiser, should be immutable, and has lexical scoping
…
A binding is the association of a variable name with the variable entity, for example "x refers to the variable declared with class x". Such bindings depend on the scope, i.e. in every different scope there are different bindings and so the identifier x might refer to different things in different scopes.
Given the scoping rules of JavaScript, a variable declaration also causes bindings for itself to be created in the respective scopes.
So the binding is what makes the name available to be used. That's what I referred to as "the let binding is created at the top of the scope". It has nothing to do with the variable existing, having memory allocated for it, or being initialised.
A declaration just says that something exists. In JavaScript you can declare variables, functions and (more recently) classes.
In some languages (e.g. C, C++) it's possible to declare something without defining it. For example:
// this declares a function exists with a given signature, but doesn't define its implementation
void someFunction();
someFunction(); // here we call the function, since we know it exists
// here we define the function, which we have to do at some point
void someFunction() { /* ... */ }
This pattern is less common in modern languages, where the declaration and the definition tends to be combined, but it's useful to understand the distinction seeing as your question seems largely about terminology.
Variables can be declared, however they don't have definitions.
let b; // we declare that there's a variable 'b'
Instead you can assign a variable:
b = 5; // assignment
let c = 6; // declaration and assignment in one statement
The concept of binding in computer science has many forms. For example, when you type foo in your code, binding is the act of working out which variable/function/type/... should be used. In JavaScript this is pretty straightforward, but in some languages it can get pretty hairy (due to things like overload resolution and so forth).
However I don't believe that's what MDN means when they talk about let bindings. I believe it's a shorthand for "let declaration and assignment", as we saw above.
Regardless, I wouldn't worry too much about that term. The most important bit to understand from the paragraph you've quoted is that let and const are tighter versions of var, introduced in recent versions of the language to address pitfalls and surprises that came from the way var works.
Previously I thought the variable keyword and variable name together comprised a declaration
You're right.
var a;
var b = 1;
let c;
let c = 2;
const d = 3;
These are all declarations of variables (even though const technical variables can't vary, or more precisely, they cannot be reassigned).
It's just that var is a bit sloppy and surprising.
You could declare a var more than once within the same scope:
var a = 1;
var a = 2;
This won't work with let:
let a = 1;
let a = 2; // SyntaxError: Identifier 'a' has already been declared
Scoping on var can be surprising too:
for (var i = 0; i < 10; i++)
{
var inner = 1;
}
console.log(inner); // prints 1 even though you might think this would be an error
Or worse:
for (var i = 0; i < 10; i++)
{
for (var i = 0; i < 10; i++)
{
console.log('hello');
}
}
At a glance you might think this would print hello 100 times (10*10), but actually it is only printed 10 times because both loops use the same variable. This is a type of programmer error that the language should really prevent. If that code used let i instead, it would produce a syntax error.
As for hoisting you can think of it as though all the var declarations were moved to the top of the containing function.
function foo()
{
doThing();
var i = 0;
doSomethingElse();
for (var j = 0; j < 10; j++)
{
var k = 10;
}
}
Even though that's how you might write the code, it behaves as though you had written:
function foo()
{
var i; // all declarations hoisted to top of containing function scope
var j;
var k;
doThing();
i = 0;
doSomethingElse();
for (j = 0; j < 10; j++)
{
k = 10;
}
}
This is why you can write:
i = 10;
var i;
The var is moved up in the code, so it behaves as:
var i;
i = 10;
You can think of let as not being moved. Therefore it is an error to reference it before it is declared.
The main thing to understand here is that the js engine actually visits a let statement inntwo different situations (as well as every other statement, but it particularily matters here). It is visited once during parsing, when it generates an AST and also analyzes the scopes and the variables. It also creates a list of variables for each scope. Now when the code gets executed, the engine visits the statement a second time (or more often if its inside a loop / function / whatever) and now finally initializes the variable and assigns a value to it. So "hoisting" is basically just caused because of the parsing / executing stages, the engine knows that a variable exists before it reaches the declaration statement during execution as it has already parsed it before.
Is the "let binding" referrred to (the hoisting of let and const) just the keyword let, or is it just the creation of storage space (which doesn't have to do with the keyword)?
The keyword actually causes an entry in the scope record, which will then get turned into a storage space during execution. On the other hand the statement itself causes an initialization during execution. So its actually hard to say when a declaration happens, thats a question of words. Its common to say
That variable was declared at line 10
Its declared in that block
so wether "declaration" refers to the statement or the scope assignment is up to you :)
the answerer said they are actually an initialization.
Actually the answerer prefered to call it "initialization" and not "declaration" to not confuse readers, but well in reality its confusing as human languages are not as clearly defined as machine ones.
It may seem very trivial issue but very confusing and recurring for me. In some manuals for javascript or tutorials these terms are used alternately.
In others I found the explanation that we declare variables when we create them with var const let and we define variables, when we append some value/object to the declared variable as below:
var name; //declaring
name = 'Adam' //defining
var age = 'dead' //declaring + defining
Are there any approved and correct rules of using these two terms?
I'd say that "variable definition" is not a standard JavaScript term.
Functions (of all kinds) and object properties can get defined, but variables always get declared. This terminology might hint at the declarative nature of variables - a declaration always applies to the complete current scope, it's not an action that gets executed and does something.
var name is a declaration. var age = 'dead' is a declaration with an initialiser. name = 'Adam' is just an assignment. I'd guess that "defining" a variable refers to it no longer being undefined, so both an assignment statement or the initialiser of the declaration might do that. I'd rather speak of the initialisation of the variable, though.
var x is a declaration because you are not defining what value it holds but you are declaring its existence and the need for memory allocation.
var x = 1 is both declaration and definition but are separated with x being declared in the beginning while its definition comes at the line specified (variable assignments happen inline).
I see that you already understand the concept of hoisting but for those that don't, Javascript takes every variable and function declaration and brings it to the top (of its corresponding scope) then trickles down assigning them in order.
You seem to know most of this already though. Here's a great resource if you want some advanced, in-depth exploration. Yet I have a feeling you've been there before.
Javascript Garden
This question already has answers here:
Is using 'var' to declare variables optional? [duplicate]
(14 answers)
Closed 8 years ago.
Given the snippet code from Javascript the good parts (page 24):
var name;
for (name in another_stooge) {
if (typeof another_stooge[name] !== 'function') {
document.writeln(name + ": " + another_stooge[name]);
}
}
Why there is definition of variable name before use in for in loop, since it will work without it?
There are two different things to pay attention to here.
var
Without var, the variable would be a global unless it was already declared in a wider scope. (In strict mode, it would be an error rather than a global).
Before the loop
You could have for (var name… but that makes it harder to spot the var statement.
Douglas Crockford (the author of The Good Parts, so highly relevant here) advocates declaring all local variables at the top of the function so you have one place to look to find your scope.
var name = 1;
name = 1;
These two are different things. For the first line, name is a variable deaclared under the current function scope, while the second is equivalent to window.name = 1 (if name hasn't been decalred in current scope.) You should never declare temporary variables in the global scope unless you have a really good reason behind it.
It is recommended, that all variables of a function are defined in same place, so if you had multiple variables, that one in the loop would be defined among them:
var a, b, name; //etc
for (name in another_stooge) {
if (typeof another_stooge[name] !== 'function') {
document.writeln(name + ": " + another_stooge[name]);
}
}
This goes with the section of: "best practices".
Yes but in that case name will be a global variable and will behave differently. So if you are after the good parts use var for every variable you use (global variables are not good).
But you can shorten the code like this...
for (var name in another_stooge) {
That will make name a scope variable...
EDIT: Assuming you are asking why not
for (var name in another_stooge)
A matter of style.
Unlike many other languages, JavaScript is function scoped, not blocked scoped.
As a result, many programmers will manually "lift" their var declarations to the top of the function to make it readily apparent what is going on.
Or -- considering the use of document.write in that code, it could be that the original coder didn't realize there was another way.
Considering this code :
var o = {};
o.f = function(){};
new o.f;
Chrome prints o.f {} into the console. Do you know how this o.f part is called? More importantly, is there any way to get this result without using the console? I'd like to extract the name of a method from the function itself, that is to say, without any additional information.
I already know how to get the name in this case :
function f(){}
f+'' // "function f(){}"
But it does not behave the same way in the situation described above.
The following content is mostly copied from comments.
I wanted to know if there is a "technical" word to talk about this o.f pattern, let's say for example "namespace", "identifier", or "function path". Then, I was wondering if there was a way to retrieve this information from a loaded script in a webpage. The following question may help you in understanding my goal, the paragraph which is right after the first code block is quite close to my idea : Does Chrome retain each object's constructor?.
Maybe I should have mentioned that my original goal was to generate a documentation at runtime :/ Something like a reflection API would have been helpful in this case. More precisely, I was looking for a way to include the name of a method into the decompilated form of the function. Look :
function Class(){}
Class.prototype.method = function(){};
Class.prototype.method + '' gives function(){}. I'd like to inject the method's name to get this result : function method(){}.
The problem is that I don't have any information about which function I'm currently serializing since the operation occurs when the user clicks a link. I know I could easily store the name somewhere, binding the data to the anchor element for example, that's obvious to me, I was just curious to know if there was a way to retrieve this data the same way as Chrome.
Well, this seems a simple enough question, as far as the naming of all these constructs goes:
o.f = function(){};
is a common statement, consisting of even more common expressions. o.f is simply one of 2 ways to access an objects' properties, commonly referred to as the dot-notation. Though I believe in JS the dot (.) isn't really seen as an operator, I'll be referring to it as the member-of operator henceforth.
Next we have the well-known assignment-operator, which assigns the right-hand operand to the left (member of the object o, called f).
The right-hand expression (needs to be evaluated to a singular value) is a function definition that, instead of a statement on its own, is used as an expression. Given that fact, we refer to this usage of functions as function expressions.
In this particular case, the function has no name, it's an anonymous function. Internally, most -if not all engines- will give it a name, but that's not something JS should know or indeed care about. As far as JS is concerned, this function has no name, and is only accessible through o.f. If you call this function like so: o.f(), its context will be that of the object o, effectively making this function behave as a method.
So basically your statement reads like this: "Assign, and create if required, to the member of o called f, an anonymous function." The function itself has no name.
Consider this:
var o = {f: function(){console.log('I am a function');}};
var foobar = o.f;
foobar();//logs I am a function
So saying the name of the function o.f is f doesn't always apply. Other variables or properties can reference the same function. That's because functions are first class objects, they can be returned, passed to and assigned to, from and by anything.
The answer, then, is to use either one of these 2 approaches:
You can change the function expression by adding a name, to turn it into a named function expression:
f.o = function newName(){};
The newName name is, apart from older versions of IE, not available outside of the functions' scope. This is required by the ECMA specifications see the details here. Anyway, now we can check for that:
var func = function func(){console.log(func);};
//same name:
func();//logs function func(){}
var foobar = func;
foobar();//logs function func(){}
func = 123;//<-- no longer function
foobar();//still function func(){}//func is still accessible
var hidden = (function()
{
return function named()
{
console.log(named);//access name
};
}());
hidden();//logs function named(){}
console.log(named);//undefined -> not visible outside the function itself
The name of the function is restricted to its own scope.
Use a regex, which is slightly hacky, and doesn't pick up on two variables/properties referencing the same function object:
o = {f: function(){console.log('I am a function');}};
for (var pName in o)
{//probably add o.hasOwnProperty(pName) check to be safe
if (o[pName] instanceof Function)
{
console.log(o.f.toString().replace(
/^function\s*\(/,
'function o.'+pName+'(')
);
}
}
This stringifies the function (giving function (){/*body*/}) and replaces function ( with function <propertyName>(. If the function already had a name of its own, that name is not replaced.
In general, this is not common practice in Javascript or in programming in general.
However, functions do have an attribute name - see Function.name.
but in your code o.f is a nameless function.
var o = {};
o.f = function(){}; //function (){} creates a nameless function.
you can define a name before the ()
var o = {};
o.f = function f(){}; //function f(){} creates a function with the name f
then
o.f.name == 'f'
NOTE: this functionality is NOT supported in IE, and is not a specification of EMCA
This is exposed as the name property of the function, and these day it is part of the standard (search for SetFunctionName in the spec). See also MDN, Chrome Platform Status, browser support. If you are asking specifically about the feature of auto-guessing the name from the variable name for anonymous functions, MDN calls that the inferred function name.
Back when the question was asked, the definitive discussion of this topic was kangax's article Named function expressions demystified (now a bit outdated).