Data pushed to array does not remain in the array - javascript

having a strange issue with JS/jQuery. When I push data from a while loop into an array, the data becomes local to the loop.
ignoring the fact my code barely works, if I move console.log(bxStore); into my document ready {} or anywhere below the while loop, it reads undefined.
var bxRegEx = new RegExp(/[b][x]\d*[y]\d*[w]\d*[h]\d*/) //identifier
expression
function bxCycle(){ //cycle html for indbx identifiers
var cycle = 0
var bxIdGet = document.getElementsByTagName('div')[cycle].outerHTML
var bxStore = new Array()
while (bxRegEx.test(bxIdGet)){
bxStore.push(bxRegEx.exec(bxIdGet))
cycle++
bxIdGet = document.getElementsByTagName('div')[cycle].outerHTML
console.log(bxStore)
}
}
$(document).ready(function(){
bxCycle()
})
https://codepen.io/anon/pen/wrRVKw?editors=1112
edit: doesn't appear to be a variable scope issue guys, my example does show it within the function, but when declaring it outside I get the same issue.

I've looked at your codepen. The correct code goes like this:
function bxCycle(){ //cycle html for indbx identifiers
var bxRegEx = /bx\d*y\d*w\d*h\d*/i //identifier expression
var bxStore = new Array();
for (i in document.getElementsByTagName('div')) {
if (bxRegEx.test(i)){
bxStore.push(bxRegEx.exec(i))
}
}
return bxStore
}
$(document).ready(function(){
console.log(bxCycle())
})

I don't have enough reputation to comment yet, so I have to write this in a full blown answer even though it might not fully solve your problem!
Because you define bxStore in the function, it's only usable within that function (it's "scope" is inside the function). So, if you move console.log(bxStore) into the document.ready function it can't see bxStore.
One way to solve your immediate problem is to define bxStore as a global variable (up with bgRegEx) as stravanato says, so that the document.ready function can see it. An even better way would be to have your bxcycle function
return bxStore
... then you could console log your result on document ready like
$(document).ready(function(){
console.log(bxCycle())
})

bxStore scope is inside the function so outside it is not visible.
If console.log is inside function it should echo something, if it's outside it should not.
You should put var bxStore = new Array(); outside the function.

You have to create a closure to expose the local variable of a function, because you declare bxStore inside a function, it will be dumped after function get executed. Yes just do a simple return
return bxStore
Or you can create a global variable.

Related

socket undefined inside of socket.on

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().

Why does my JavaScript code work when I copy a variable in a for loop

This JavaScript code for a Google Chrome Extension.
It works, but I wonder about one thing. It's in the for loop that iterates an associative array and utilizes its values in a Chrome function.
This works just fine:
var links =
{
apps: 'chrome://apps/',
bookmarks: 'chrome://bookmarks/',
history: 'chrome://history',
...
};
for (var link in links)
{
(function()
{
var href = links[link];
document.querySelector('#' + link).addEventListener('click', function() { chrome.tabs.create({ url: href }); });
})();
}
But with some changes it suddenly doesn't (changes are highlighted)
var href = links[link]; Look -----v
[...].addEventListener('click', function() { chrome.tabs.create({ url: links[link] }); });
Also I have to use the (function() { })(); pattern (I don't know the name), otherwise it also doesn't work.
Question
Why does this only work when using both the pattern and the variable copying? Please explain to me how JavaScript processes variables in a way that these contraptions are required.
There is no special scope in a for loop, so the variable is overwritten on each iteration when you do
for (var link in links) {
var href = links[link];
element.addEventListener('click', function() {
chrome.tabs.create({ url: href });
});
}
Note that the click happens later, when the for loop has completed, and because there is no new scope created inside the for loop, the variable changes on each iteration, and by the time you click the element, the href variable inside the event handler callback is the last value it was set to.
What's really happening is that any function declaration will create a new scope, so the variable isn't being overwritten on each iteration, and an Immediately Invoked Function Expression is such a function declaration, and it keeps the value of the variable constant because it creates a new scope
for (var link in links) {
(function() { // new scope, variables inside this isn't changed on next iteration
var href = links[link];
element.addEventListener('click', function() {
chrome.tabs.create({ url: href });
});
})();
}
The scope of a variable declared with var is its current execution
context, which is either the enclosing function or, for variables
declared outside any function, global.
When you create a reference to a function, like you do when adding that event-listener, the js interpreter preserves any variable references it finds inside that function, preventing those references from being garbage-collected.
In the first snippet, the preserved reference is a reference to a string, called href. Since this string is declared inside the self-executing anonymous function (the one you declare just within the for-loop), a new reference is created and preserved for each run of that function. Although each reference is named 'href', each reference is actually a unique variable, unique to that run of the anonymous function.
Now in the second snippet, there are two references inside your event listener function: 'link' and 'links,' but those variables are declared in the outer-scope, (from the code provided, it appears to be global, but I'm betting there's some function(){ declared above, off-screen)... because this variable is declared only once, in the same scope as the for loop, the anonymous function inside the for loop is actually always referring to the same object as the other copies. Since the for-loop changes the value referred to by 'link' every time it loops, and every binding you created is looking at the same instance of 'link' and 'links', every function you bound will always wind up referring to the last link in the list (unless you could click so fast that you hadn't completed the for-looping when you clicked, then it would point to whichever link the for loop was currently working on.)
(Edit: This behavior is actually pretty useful, btw - you can use it to emulate "public/private properties" seen in other languages, and to insulate properties from being changed by external code, like this:
var MyCounter = Counter();
MyCounter.Increment();
MyCounter.Increment();
MyCounter.Increment();
console.log(MyCounter.GetCount());
function Counter() {
// count is a locally-scoped variable, inaccessible to the outside world
var count = 0;
// The object below is what's going to be assigned to MyCounter
// the functions hold references to count, so it won't be garbage-collected
// count will also be unique to each run of Counter()
return {
Increment : function() {
count++;
},
GetCount : function() {
return count;
}
}
};
end edit)
The pattern you're referring to is called a "closure", and it's the source of endless JavaScript confusion for lots of folks.
When you create a new function inside a function, a reference to the execution state of the current function is captured and saved for later execution of the created function. The problem with doing so in a loop is that only one closure is created for any given containing function, so by the time you get to executing any of the created functions, the state saved in the closure is pointing to the last item in the loop.
Mozilla has a great explanation of the whole concept here, including a section specifically on your issue.
To add to the answer of adeneo, this article explains the closures and especially the scenario where the scope of the outer function's variable values changes.

Reading a variable value inside a named function in javascript

This may be very simple but i lost my way in finding the answer,
I have a named function inside a Backbone view. I'm trying to write unit test for this named function and i could see a variable is being declared in function scope. The state of this variable changes based on certain scenarios.
I have instantiated the view object inside my test suite and when i do a console.log(viewObject.namedFunction) i see the entire function being logged properly. Now how do i access the variable inside the namedFunction, i was expecting something like viewObject.namedFunction.variableName but it will not work and when i did that, it was not working as expected.
If the variable is tied to viewObject scope then it would have been easy to access it. But in this scenario it is not so can some one please help me in getting a hold on the variable inside named function in view object from test suite.
I think I understand your confusion, because when you define a variable using var in the window scope, it becomes a property on the window object... It would seem to follow that when you define a variable in a child scope, it should become a member of the local context, right? Nope. Globals are special ;-)
In fact, if that were the case, there would be no privacy!
If you want sign to be public, be explicit.
obj = {
namedFunction : function myself() {
console.log(myself);
myself.sign = 23;
}
};
obj.namedFunction.sign;
The only problem with this approach is that you can now assign a new value to sign from anywhere. The classic and preferred approach to this problem is to create a getter function for your private variable.
var obj = {
namedFunction : function myself() {
var sign = 3;
myself.getSign = function(){return sign;};
}
};
obj.namedFunction.getSign();
This isn't by any means the only approach, but I hope it was helpful.
One way to do this is like such:
namedFunction = (function(){
var theActualFunction = function(){
//Do something
//Access variable like: theActualFunction.MyVariable
};
theActualFunction.MyVariable = "value";
return theActualFunction;
}());

nodejs async function parameters durability in rapid calls

sorry the topic might be confusing coz i don't know how to say that.
consider a situation that i have a async function with one parameter. an array.
i used this parameter inside function. I'm afraid that calling function multiple times could rewrite the array i sent to function previously. Could it be happened?
assume this code:
//this is an IPC function which will be called by another process.
responder.on('message', function(request) {
resp = msgpack.unpack(request);
//resp is my array.
myvar = resp[1];
.
.
.
}
I'm afraid resp[] will be overwrite before the first call finished and this cause problem in first call code execution.
Consider the following example:
function doStuff() {
var temp = 0;
function modifyTemp(temp) {
temp = 5;
}
modifyTemp(temp);
//the value of temp is still 0
function modifyTemp2() {
temp = 10;
}
modifyTemp2();
//temp now equals 10
}
doStuff();
Notice that temp is within the closure scope of "doStuff()". So any reference to temp within this scope will use this reference, unless there is one that takes precedence, as in the example of modifyTemp(temp) declaration. In this case, a temp copy of the temp variable is created and stored to "temp" which is modifed within the scope of only this funciton, and the temp defined within the closure is left untouched. So the answer to your question is, it depends on what level of scope you have declared your resp variabled. The way your could looks to be written, I would suggest that what you are concnered about happening is in fact a concern.
The following modifications (provided in commented/uncommented lines) would potentially provide jurastically different behaviors, depending on how the rest of your program function, and how much async stuff you have going on. Notice that the uncommented implementation redefines the variable, so that we don't need to worry about consecutive runs or other functions interfering with it's value.
responder.on('message', function(request) {
//resp = msgpack.unpack(request);
var resp = msgpack.unpack(request);
//resp is my array.
myvar = resp[1];
.
.
.
}

jquery making local variable in function global

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.

Categories