When a function is invoked, a new lexical environment is created for that invocation. That lexical environment contains an environment record, which in turn holds the local named bindings which exist in that environment. So, for instance:
(function () {
var x = 123;
// other code
}());
In the above function invocation, there will exist a binding with the name "x" and the value 123, in the function's lexical environment.
Now, if we wanted to change the value of that binding, we could:
set the identifier x as the left-hand side of one of the assignment operators:
x = 456;
// the value of the "x" binding has changed to 456
set the identifier x as the operand of a prefix/suffix increment/decrement operator:
x++;
// the value of the "x" binding has changed to 124
My question: Are those the only two methods to change the value of the "x" binding?
Well, I don't think we should talk about 'bindings' here. The link #Incognito gave in comments to the question describes binding of variables and functions - but not their values.
As 'x' in your example has a primitive value assigned, I don't think there's a way to alter it - if not in an assignment (direct or syntax-sugar one).
For example, this...
var x = 42;
x.y = 24;
... won't actually result in changing x (it gets converted into an object, assigned a new property, but then this object will be just thrown away).
And this...
function x() { ... }
... will also fail to assign a new value to x.
UPDATE: My point is that 'var x = 42' statement in JS (but not in Erlang) won't result in binding of 42 (number literal) to variable x.
Related
I have a quick question regarding some code I do not understand:
var anonymousGreet = function(){
console.log('Hi');
}
function log(a){
console.log(a);
}
log(anonymousGreet);
In the code above when I call the function log and pass in the function expression anonymousGreet as a parameter to log. Does that mean the variable "a" in log is pointing to the variable anonymous greet which is then pointing to the function object. Or does a point directly to the function object pointed to by anonymousGreet? I am a little confused if a first points to the variable anonymous greet or does it directly point to the function object pointed to by anonymousGreet. Sorry if this is confusing but any help would be appreciated! Thanks you!
If you come from a C++ background then a simple rationalization is
In Javascript everything is passed by value, references are never used
All passed values are however pointers to objects
For example when you write:
a = b + c;
you should imagine (in C++) something along the lines of
Object *a, *b, *c;
a = new Number(b->numericValue() + c->numericValue());
(note that however Javascript differently from C++ provides a garbage collector so no explicit delete is ever needed).
This is of course just a simple description of what is the observable behavior (and it was may be the implementation of very first Javascript engines). Today what really happens behind the scenes is much more sophisticated and includes run-time generation of machine code (JIT).
This is the reason for which for example:
function foo(x) {
x[0] = 1;
}
var a = [0];
foo(a); // Will change the content of a[0]
but
function bar(x) {
x = 9;
}
var b = 0;
bar(b); // Will *NOT* change the content of b
Yes, if you check a===anonymousGreet, the result is true. All primitive values are passed by value, but objects are passed by reference in Javascript.
var anonymousGreet = function(){
console.log('Hi');
}
function log(a){
console.log(a === anonymousGreet); //true
console.log(a);
}
log(anonymousGreet);
As a matter of terminology, and to avoid confusion, I would avoid the use of the word "pointer". It's too easy to get confused when using the word "pointer". Sometimes "A pointing to B" can mean that A is a kind of alias for B. Or that B can be modified through A. Or A can point to B which points to C; what does that mean?
IMO it is clearer to use the terminology that in JavaScript a variable holds a value. That's it. It holds a value. It does not point to anything, it does not refer to anything, it holds a value.
However, two variables may hold the same value, such as an empty array []:
var a = [];
var b = a;
Both a and b hold the same value, a particular empty array. We can see that they hold the same value by checking a === b. Since they hold the same value, that value can be manipulated through either one; a.push(1) and b.push(1) do exactly the same thing, because they are both manipulating the value held in common by each. Re-assigning to a merely changes the value that a holds; it does not and cannot affect b, and vice versa. b is not a "pointer" to a, or an alias to a; it is a variable which happens to hold the same value as a.
In other words, a = b does not make a "point" to b. Nor does it copy the value of b and assign it to a. It gives a the value of b, so that a and b now hold the identical value.
The function parameter passing mechanism can be thought of as a particular type of assignment. It makes the formal parameter in the function definition assume, or hold, the value of a parameter specified in the call. When I define a function
function foo(x) { console.log(x); }
and then call it
var y = 42;
foo(y);
the variable/parameter x is assigned the value of the parameter passed in the function call. In other words, x comes to hold the value of y. x does not "point" to y, and it is not a copy of y. It holds the same value as y, which in this case is 42.
Let's take your specific example:
var anonymousGreet = function(){
console.log('Hi');
}
function log(a){
console.log(a);
}
log(anonymousGreet);
In this case, anonymousGreet is a variable which, by virtue of the assignment, holds as its value a particular anonymous function. When you call log(anonymousGreet), the parameter a to the log function is set to hold the value of the parameter in the call, so it now holds the value of anonymousGreet. It does not "point" to the variable anonymousGreet, and any changes to it cannot affect the value of anonymousGreet, nor of course the function which that value represents.
Does that mean the variable a in log is pointing to the variable anonymousGreet which is then pointing to the function object?
No, it means that the variable/parameter a in log holds the value held by anonymousGreet, which is the anonymous function.
Or does a point directly to the function object pointed to by anonymousGreet?
Yes, but not "point to the thing pointed to by", but rather, "holds the value of anonymousGreet, which holds as its value the anonymous function.
Can anyone explain the hoisting behavior in the below scenarios?
alert(x);
var x = 10;
Result: alert-undefined
In the below case, x is not defined using 'var' keyword - hence attaches to the global scope.
alert(x);
x = 10; // not given a var
Result: error
In case if we replace x with window.x, we get alert as undefined!
alert(window.x); // calling the variable with window namespace
x = 10; // not given a var
Result: alert-undefined
Can you explain why it is different in calling a variable (which is attached to global scope) with the variable name (x) and with window namespace (window.x)?
The term "hoisting" is often misunderstood to mean that certain statements are moved to the top of their execution context, which is not what happens and why the term should be avoided.
What actually happens is that all declarations are processed first, so any variable declared with var (and any function created by a function declaration) exists before any code is executed. Then code execution begins.
So the variable x is created and assigned the value undefined before any code is executed (per ECMA-262), then later, during execution, it may be assigned some value.
So in the case of:
alert(x);
var x = 10;
x exists when alert is called, but has yet to be assigned a value other than undefined.
In:
alert(x);
x = 10;
x is not declared, so it does not exist when alert is called, hence the error. After the alert (if the code kept running), the assignment to x would create a property of the global (window in a browser) object named x and assign it a value of 10.
In:
alert(window.x);
x = 10;
It is a quirk of ECMAScript that global variables are also available as properties of the global object. The expression window.x attempts to read the x property of the window object. Since no such property exists, the return is undefined. Then the next statement creates x as a global variable and hence window.x now exists with a value of 10.
var x hoists the variable in the entire scope it's valid in, so the name x is available and valid anywhere within the scope. Its initial value is undefined, it only receives its value after the alert.
In case of a plain x, the variable is not hoisted because there's no var, so the bubbling up to window and its creation there only happens on the line x = 10, which is after the alert, which means the variable is entirely undefined and invalid at the time you try to alert it.
Any non-existing property of any object returns undefined, so testing window.x at a time when that property isn't set returns undefined as expected. That's how you do membership testing in Javascript: check whether a specific property equals undefined.
In the first case, var x gets hoisted, so x does exist when you call it (even though the value is undefined)
In the second case, when you say y = 10, you're essentially saying window.y = 10, so there's no hoisting at all, that's why it can't find the variable at all and gives you an error.
alert(x);
var x = 10;
will treated as
var x;
alert(x);
x = 10;
So at the time of alert x has the value undefined by default;
alert(x);
x = 10;
will be treated as
alert(x);
x = 10; // If this line runs in use strict mode then this line will throw error otherwise in non strict mode x will be added to global object ie. window
So will throw error because of x is undefined at the time of alert
alert(window.x);
x = 10;
will be treated as
alert(window.x);
x = 10;
alert will alert undefined because window is an object and it is having no property named as x at the time of alert so undefined
Later the line x = 10; will add the x to global object if in non strict mode, and will throw error if in strict mode
Is this a variable definition or declaration? And why?
var x;
..and is the memory reserved for x after this statement?
EDIT:
In C extern int x; is a declaration, int x = 5; is a definition. What's the analog in JS? Wikipedia says a declaration allocates memory and the definition assigns a value to this allocated memory.
SECOND EDIT:
I think the explanation of #Deryck sounds great, but there's some output that disagrees with his explanation:
> var x;
undefined
> x
undefined // now it looks like x is defined to the value undefined
> y
ReferenceError: y is not defined
If the ReferenceError output would say y is not declared it would make sense. But often I read that JS has two non-values: null and undefined. So var x would be a definition with the value undefined.
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
PS - your analogy between C variable dec/def and JS was spot on. What you read on Wikipedia was correct.
Declaring a variable is like telling the (javascript) compiler that this token x is something I want to use later. It does point to a location in memory, but it does not yet contain a value. ie. it is undefined
var x;
defining it means to give it a value which you can either do it like:
x = 10; // defining a variable that was declared previously
or like this:
var y = 20; // declaring and defining a variable altogether.
http://msdn.microsoft.com/en-us/library/67defydd(v=vs.94).aspx
http://www.w3schools.com/js/js_variables.asp
I will give you a long answer for better explanation.
When the javascript engine is not able to find a particular variable in memory, it will throw an error. To be more specific, when the javascript engine (Execution Context) is not able to "reference" a variable in memory, it will throw a ReferenceError. This is not exactly the same as a Declaration Error, at least in javascript.
There is a deference between a not defined error and the value undefined.
So doing
var a = undefined;
and
var a;
will both log the same result i.e. undefined. This is because, when you simply do a var a; the javascript engine allocates memory for the variable and automatically sets it's value to undefined, which is different from saying that a doesn't exist at all - in which case it will throw a ReferenceError.
Hoisting
console.log(a); // undefined
var a = 'something';
will log undefined because, the javascript engine knows there's a variable declared somewhere in the code - which means to say that the javascript engine actually does something before it executes the code - one of the thing it does is hoists variables. To put it simply, the above code is the same as
var a; // hoisted (declared and defined the value `undefined`)
console.log(a); // undefined
a = 'something' // update the defined value to `something`
So, yes, declaration and definition happen together in javascript (automatically - if you don't do it yourself) and the default defined value is undefined.
ES6
Just an additional note
const a;
will throw a SyntaxError where a initializer (definition) is necessary. const is the only time when you need to declare and define manually.
> var x;
undefined
> x
undefined // now it looks like x is defined to the value undefined
> y
ReferenceError: y is not defined
Although it is usually said that Javascript is an interpreted language, but there is also a compilation step that happens very fast just before the interpreter runs. The job of this compilation step is to create scope chains, where variables are declared(no read/write operation here, just simple name-keeping) in their respective scopes. These variables will point to some memory location but value in it will be undefined until some execution is carried out by the interpreter.
> Compiler run:
When compiler sees var x;, it will simply book-keep this variable in its respective scope.
The next x; and y; are simply ignored in the compilation step as they are execution statements.
> Interpreter run:
When interpreter sees var x;, it will skip this as there is no read/write operation here.
Now when interpreter sees x;(execution statement), "x" will already be declared in the scope, and it will hold value "undefined", which is what you get on the console.
But when interpreter sees y; similarly, there has been no previous declaration or name-keeping for it in the compilation step, and thus we get the ReferenceError as expected.
Hope someone finds this comment useful.
var x, y, z;
var x;
var h = 4;
i = 4;
all the above are global variables if placed at the top, (outside any functions)
Lets say that the javascript has a function start
function start() {
x = 5*5;
}
the global variable x is now equal to 25
Where as if the var x; was not placed outside of any functions, that variable x would just be local to that function.
You declare JavaScript variables with the var keyword:
var carname;
After the declaration, the variable is empty (it has no value).
To assign a value to the variable, use the equal sign
var carname="Volvo";
In computer programs, variables are often declared without a value. The value can be something that has to be calculated, or something that will be provided later, like user input. Variable declared without a value will have the value undefined.
The variable carname will have the value undefined after the execution of the following statement:
var carname;
var hoisting
In JavaScript, a variable can be declared after being used.
bla = 2
var bla;
// ...
// is implicitly understood as:
var bla;
bla = 2;
For that reason, it is recommended to always declare variable at the top of functions. Otherwise, it may lead to confusing cases
When declaring a variable without assigning a value to it, there still needs to be some memory available for it, otherwise you cannot make a reference to the variable later in the program. I don't think it's a noticeable amount of memory being used and won't make a difference.
var x;
This is a variable declaration. In Js if you don't assign any value to variable in declaration. It will get undefined by default.
var x; // declaring x
console.log(x); // output: undefined
But if you have not even declared the variable in you try to access it. It says that the variable is not defined.
console.log(y); // Output: ReferenceError: y is not defined
If you need access to objects between JS files, it's good practice to expose one object to the global namespace and declare fields and methods on that object.
File 1:
var myObject;
myObject.myField = "Field!";
File 2:
myObject.prototype.myFunction = function () {
return this.myField;
};
I have taken from a really good discussion on : Equivalent of C extern declaration in JavaScript
https://github.com/ganqqwerty/123-Essential-JavaScript-Interview-Questions
Various trivia regarding the difference between undefined and null completely aside, the short answer is: there is no equivalence in Javascript. There are no bare "forward declarations". Javascript variable declarations are definitions. Variables that have been defined but not explicitly initialized will contain the value 'undefined'. There is no "external linkage".
If you refer to an identifier that is not in any accessible scope (perhaps because it doesn't exist the first place), you will get your "ReferenceError: y is not defined". This has nothing to do with variable value or storage.
In simple terms,
undefined means value to the variable is not defined.
not defined means the variable itself is not defined.
var x; //value is not defined. So,
x //undefined
//y variable is not declared or defined. So,
y // y is not defined
I have been watching a video series by Douglas Crockford. I am a little confused on the relationship of assigning variables as a parameter of assigning variables as a global variable, let me demonstrate.
var bob = 22; //global scope
function funky(parameter){
parameter = null; //sets the var passed in to null
bob = 44; //sets the bob
}
var hello = [];
funky(hello); // hello still has the value of an empty array even after the function is invoked.
bob; // value is 44
So 'var bob' is assigned 44 when funky() is invoked. This bob holds the new value outside the scope of the function.
var hello is passed as a parameter, while inside funky, it has the value null, outside when hello is invoked in global space, it holds the value of an empty array.
Is this just something I have to memorize? If a defined variable in global scope is passed as a parameter, it will only hold it's new assigned value within the scope of the function? Am I missing something at a broader scope with either how a parameter is passed and assigned in a function?
Here is a repl.it of the code with console.log outputs while inside and outside the function/global scope.
http://repl.it/NgN
Because this line
parameter = null;
Only sets the value of the function's parameter, not the value of the variable that was passed in. However, bob inside the function is interpretted as a reference to the global variable, so it does modify the external value.
Note, however, that objects are references, so if you wrote it like this:
function funky(parameter){
parameter.hello = null;
}
Then calling funky does directly modify the object that the parameter references.
var x = { hello: [] };
funky(x); // x => { hello: null }
Is this just something I have to memorize?
Yes, understanding how parameters are passed is pretty important.
If a defined variable in global scope is passed as a parameter, it will only hold it's new assigned value within the scope of the function?
Parameters only hold their values within the scope of the function. Global variables are, well, global, so if they are modified inside the function, they keep that value outside the function.
Also, be aware of hiding—if a parameter has the same name as a global variable, the parameter hides the variable within the scope of that function.
ok, so the following example will confuse you even more.
var a = {'a': 'A'};
function foo(param){param.a = 'B';}
foo(a);
// now print a
{'a': 'B'}
Here's an important concept:
Primitives are passed by value, Objects are passed by "copy of a reference".
As for more information, you can check this answer:
Does Javascript pass by reference?
Regarding this:
var hello is passed as a parameter, while inside funky, it has the value null, outside when hello is invoked in global space, it holds the value of an empty array.
Do not think of parameter as an alias for hello. They are distinct variables. They are free to point to different things. Assigning a value -- null in this case -- to parameter has no effect on hello. After that line, the global variable hello still points to an empty array. Only parameter points to null.
Furthermore, funky(hello) passes the value of hello to the funky function. Consider the following:
var arr = [];
function addElements(arr) {
arr.push(5);
arr.push(77);
}
The global arr is still empty after addElements executes. The arr inside the function is distinct from the arr in the global scope. (I should note that the contents of each arr may point to the same objects, but that's a separate issue.)
(Note also that some languages do allow the sort of aliasing you seem to expect, but that's not how parameters are passed in JavaScript.)
JavaScript assumes that if you assign a value to a variable it is in the global scope—unless that variable is declared with a var. Like for example, this:
var bob = 22; //global scope
function funky(parameter){
parameter = null; //sets the var passed in to null
var bob = 44; //sets the bob
}
var hello = [];
funky(hello); // hello still has the value of an empty array even after the function is invoked.
bob; // value is 22
Since the function's bob variable is declared with a var, it is owned by the local scope of the function and has no impact on the bob declared outside the function's scope.
Regarding how objects differ from primitives when passed into functions, check out Jonathan Snook's article http://snook.ca/archives/javascript/javascript_pass and the helpful comment from #p.s.w.g.
why is it that when I do this:
x = 5
(function bla(varX){
varX = 7; console.log(x); //7
})(x);
console.log(x); //5
the x doesn't change, since it's in a closure if I understand correctly,
but here:
x = {a:5}
(function bla(varX){
varX.a = 7; console.log(varX.a);
})(x)
console.log(x.a); //7
Why does x.a gets overwritten and x doesn't?
You can do the same thing with any other function:
var o = {};
function f(x) {
x.val = "foo";
}
f(o);
console.log(o.val);
The object is floating around somewhere on the heap, and both x are merely references to that object. You only need a reference to it to alter an object, no matter how you got that reference.
On the other hand, the statement x = ...; simply overwrites the local variable to refer to something else. This is also why JS does not have "pass by reference" by the traditional (and more useful) definition.
In both functions you have a global x (on line one) and a local x (function bla(x){).
In the first example, you are just changing the values of a series of variables. Changing the value of the local x doesn't touch the global x.
In your second example, you are passing a reference to the object you create to the function, not a copy of it. In the function you modify that object by assigning a new value to one of it's properties. The value of both the global and local x remains the same (a reference to the object).