One of the key features of const in JavaScript is that the const variable cannot be redeclared.
However, in this code that is grabbed from this link:
signalServer.on('discover', (request) => {
const clientID = request.socket.id // clients are uniquely identified by socket.id
allIDs.add(clientID) // keep track of all connected peers
request.discover(Array.from(allIDs)) // respond with id and list of other peers
})
Every time a new client connects to the server via a socket, a new const clientID = request.socket.id is created.
So the clientID variable is created more that one time even though it is a const.
How is that possible?
A variable name can only exist once in a scope. (Redeclaring one with var doesn't cause an error, doing so with let and const does).
Each call to a function creates a new scope.
There's still only one instance of that variable in that scope.
It's only being declared once in each scope that you have it, if clientID was in the outer scope, let's say along with signalServer then it would work the way you think it did
this constant only exists in the block of the callback function. after the function is executed, the constant is unloaded from memory.
const are block scoped const - JavaScript | MDN.
In the snippet, every time the callback function is called after discover event is triggered, a new execution context is created for the callback function.
Scope for const clientID is limited within the nearest curly braces, where it can be assigned only once at the time of declaration.
as far as I know variables in functions are always temporary if they are declared in the function scope. So even though it's a const it's still temporary since it's declared inside a function. You however would not be able to declare a different variable with the same identifier. so saying const x and later on saying let x isn't possible. If you had identified the const x outside of the function scope you wouldn't be able to set a variable with the same identifier in the function scope.
Related
I don't understand why a var variable can be reassigned within a function, but the change also applies outside of the function. Why/How?
var c = 1;
function Fn() {
c = 2;
}
Fn();
c; // 2
Why isn't the value 2 limited to the scope of the function?
When I write c = 2 within a function, does the javascript engine automatically hoist a new var c outside of the function and assigns it the value undefined, which is then changed to 2 once Fn() is called?
It applies outside the function because, inside the function, you are changing the variable.
You are not creating a new variable that exists only inside the function.
Why isn't the value 2 limited to the scope of the function?
You didn't use var, let, const or any other method to create a variable in the scope of the function.
You are accessing the variable you already created in the wider scope.
When I write c = 2 within a function, does the javascript engine automatically hoist a new var c outside of the function and assigns it the value undefined, which is then changed to 2 once Fn() is called?
No. There isn't a new variable. There is only the c you already created outside the function.
This is a common complaint about javascript. Since you used "Var" it has a global scope, so even though you're within a new function when you use c=2 since it's already defined globally it's changed globally. Using "Let" helps define things local to the function and "const" defines globals as constants so they cannot be changed. This issue is particularly fun when you have two global variables with the same name in different JavaScript files and then reference both files to be used on a page. Globals should be used with caution.
When you start run this program, engine will store your variable which declared with "var" keyword in global object(window) then move on to get in the function, Engine will create Special Scope for function is called "Function Execution Context" (FEC) every declaration within the function will be available in this scope(FEC), so when Engine execute body of your function will find re-assignment for variable is called "c", it will looking for it in current scope, if didn't find it, will move on parent scope, in this case, Global Scope is its destination, will find the searched variable and then re-assign it with new value.
Read this wonderful article -> execution-context-how-javascript-works-behind-the-scenes
0
I have a question, what contains the function express()? , because i cannot understand how you call a function if you store express() in a variable like: const app = express();
and then you call , for example, the function listen() like if was an object:
app.listen()
can you guys help me to understand?
thanks in advance
Objects can have methods. Methods are really just functions. Sometimes those methods return something, and other times they don't. Sometimes you care about the result, and sometimes you don't.
const myObj = {
add: (a, b) => a+b;
echo: (msg) => console.log(msg);
}
const result = myObj.add(1,2);
myObj.echo(result);
Functions in Javascript are objects. You can assign them to variables. You can execute them by calling them. You can assign properties to them. You can read properties from them.
So, this is assigning a function to a variable (assigns the module.exports from the 'express' module to a variable named express):
const express = require('express');
This is executing the function by calling it:
const app = express();
This is accessing the .static property on the express function (which can also be a function):
app.use(express.static('/public'));
As another example, all regular functions have some built in properties:
function greet(greeting) {
console.log(greeting);
}
// outputs 1 because the function has one declared argument
console.log(greet.length);
But, you can also add your own properties if you want since functions are a sub-class of an object.
A function nested inside another cannot be called directly from outside of the outside function.
However, an inner function can be made accessible if a global reference is made to it.
In my snipped example, outerFunction contains two innerFunctions followed by two variable declarations that assign those functions to each of two variables (named outerFunction.innerFunction1 and outerFunction.innerFunction2). Had these been declared with let or const inside the outer function, they would be accessible only from within the function. However, declaring a variable by name only, gives it global scope.
So, if outerFunction is invoked, it places the inner functions into the global scope. They can now be referenced by the names they were given outerFunction.innerFunction1 and outerFunction.innerFunction2. Giving them names containing a dot is useful as a reminder of where the functions come from, but they could be given any name and called directly (as in my third example in the snippet).
function outerFunction(){
function innerFunction1(){
console.log( 'hello from first innerFunction' );
} // end innerFunction2;
function innerFunction2(){
console.log('hello from second innerFunction');
} // end innerFunction2;
function innerFunction3(){
console.log('hello from the third function');
} // end innerFunction3;
outerFunction.innerFunction1 = innerFunction1;
outerFunction.innerFunction2 = innerFunction2;
anyName = innerFunction3;
} // end outer function;
outerFunction(); // essential to declare and initialise global variables about to be accessed;
outerFunction.innerFunction1();
outerFunction.innerFunction2();
anyName();
If you can look inside outer function of the example you gave, you will find a declaration to the dot notation variable name you're using to call it. There is nothing magical about the dot notation here, it is just a variable name.
I have the current code;
socket.on('KeyPress', function(data){
var ply = PLAYER_LIST[socket.id];
/* ... */
});
WebStorm is informing me that socket.id may not be initialized, and then when this event is triggered it does cause the error
TypeError: Cannot read property 'id' of undefined
The whole code is inside of
io.sockets.on('connection', function(socket){ /*...*/ });
Here is two of the on method I'm using;
In the first block you can see I'm doing the same thing yet it works..
Also on that note how secure is it to use socket.id to auth a user? Is it possible to force-set your own id?
You are a victim of a bad practice of defining variables with var within a loop and then getting bit by the influence of "variable hoisting" where a variable defined with var anywhere in the function is automatically declared at the start of the function and then initialized where your assignment was, meaning it's undefined everywhere in your function before that.
The problem is this line of code:
var socket = SOCKET_LIST[i];
That is redefining a local variable named socket that hides the one you actually want. Variables defined with var are function scoped. That means they are defined at the top of the function (this is called variable hoisting) and thus hides the other parent scoped socket variable.
Think of your function as starting like this:
socket.on('KeyPress', function(data) {
var socket; // this is hoisted from deeper inside the function
// and creates a new undefined socket variable
var ply = PLAYER_LIST[socket.id];
// other code here
});
This is essentially how Javascript sees your code. You can do a search on "Javascript variable hoisting" and see LOTS of articles written on the topic if you want more info.
The smallest change you can make it to change the name of this local variable to something else to it doesn't interfere with the parent scoped variable, but really this code structure is not ideal in the first place.
var localSocket = SOCKET_LIST[i];
var ply = PLAYER_LIST[p];
localSocket.emit(...)
In general it's a bad practice to define a variable with var inside a for loop. It leads to the "assumption" that it is scoped only to that loop, but in reality, it's scoped to the whole function and can mess with things outside of the loop.
In ES6, you can use let or const instead of var to declare a variable that is actually scoped to only the block of the loop.
Of other note, you should NEVER be iterating arrays with for/in. That iterates all array properties (including other enumerable object properties), not just array elements. ES6 adds for/of for iterating arrays this way. In ES5, you can use the more traditional for loop or .forEach().
I am doing a small work in JavaScript and I want to avoid problems, so I am asking beforehand.
Can I use two different variables and name them the same in different functions, given that one of these functions calls the other?
So, when I define the variable in the second function, will it interpret as two different variables, or will it rewrite the value of the original variable from the first function? (Or, will it throw an error due to the fact that a variable with that name already exists?)
Here is an example:
function first()
{
var a = somevalue;
second();
}
function second()
{
var a = differentvalue;
}
Thanks!
Variables declared inside a function are local to that function, and doesn't conflict with variables with the same name anywhere else.
You can even have a global variable with the same name, and the code inside the function will only see the local variable.
Example:
var a; // global variable
function first() {
var a; // local variable in first
second();
}
function second() {
var a; // local variable in second
}
(Global variables should of course be used as little as possible, but it's good to know that you can have a local variable that is unaffected by any global variables that may exist.)
A local variable inside a function is not only local to the function, it's actually local to that execution of the function. If you call the function again, a new variable is created, and if the function calls itself (recursion), each level will have it's own variable.
Yes you can, as long as you don't forget the var keyword : the scope of a variable is either the function in which it is declared or the global scope. There is no way from outside the functions to gain access to the variables they declare.
I have this function that populates the currsong variable with data.
The problem is that the variable currsong is only available inside the function and I need to access it globally.
// get a single audio url
echonest.artist(artist).audio( function(audioCollection) {
var currsong = audioCollection.data.audio[0].url;
return currsong;
});
Thank you!
To declare a global variable, you can always remove var:
currsong = audioCollection.data.audio[0].url;
I'm not sure if a global variable is a good solution for whatever you're trying to do, though. People suggest to avoid them for reason.
edit
An example.
Note, the variable will be undefined before function is executed first time. In your code, you only pass it into audio, you don't actually invoke it.
edit2
As Tgr notes, you can also declare global variable explicitly: window.currsong = .... There's no functional difference, but it improves code quality.
Scope is an interesting bird in javascript. So is closure.
Observation 1: you are returning a value from an inline function; that return value is meaningless.
Observation 2: by using the "var" keyword, you are specifying a local scope. Removing var will make the variable global. However, even if you do that it is possible that you will attempt to access that variable before the function gets triggered (i.e. it will be undefined).
Since you're just starting to wrap your head around the concept of closure and javascript scope, I'd recommend reading up on it and then rethinking your application design (since I would be willing to bet that you will learn something which prompts another approach).
In the mean time, try defining the variable outside of the inline function and giving it a temporary value. After that remove "var" from inside of the function.
// get a single audio url
var currsong = "temporary value";
echonest.artist(artist).audio( function(audioCollection) {
currsong = audioCollection.data.audio[0].url;
return currsong;
});
I've rewritten your code to make it a little more clear for myself and others. Please let me know if I've transliterated something incorrectly.
Basically, it looks like you're trying to get curSong as follows:
echonest.artist(artist).audio(
function(audioCollection){
var curSong = audioCollection.data.audio[0].url;
return curSong;
}
);
Right now, what you're doing is passing a function (the anonymous function defined by function(audioCollection)) to the audio function of whatever artist(artist) returns. As such, the curSong value is returned to audio(), and then only when audio() actually runs the function that its handed. I would look at audio() and try to see if there is a way to get curSong out of it. Otherwise, I'd do as slifty describes above and declare curSong in a larger scope, so that it can be accessed even outside of audio().
EDIT: For example, a sample audio function could be as follows:
function audio(inputFunction){
var audioCollection = getAudioCollection();
var song = inputFunction(audioCollection);
return song;
}
The variable curSong is in an anonymous function being passed to audio(). As such, it doesn't exist until that anonymous function is executed, as in the above code. Now, when you run your code (from the first snippet), the anonymous inner function will return curSong to audio(), and audio() will return curSong to you.