I have a script setup like this (http://jsfiddle.net/YD66s/):
var countFull = new Array(0,1,2,3,4,5,6);
var countActive = new Array(0,1,2,3,4,5,6);
function pickRandom(a) {
if(arguments[1].length == 0) {
arguments[1] = arguments[0];
}
var m = Math.floor(Math.random()*arguments[1].length);
chosen = arguments[1].splice(m,1);
return chosen;
}
setInterval(function() {
pickRandom(countFull,countActive);
}, 1000);
When I run this I want the variable to be set for that function only. Instead it is affecting countFull towards the end because I make arguments[1] = arguments[0]. How in javascript can I just reference a variable but not consume it and ultimately arguments[1] becomes arguments[0].
Hope this makes sense. This is driving me nuts how different javascript variables are compared to other languages like PHP.
Javascript arrays are just pointers so when you do arguments[1] = arguments[0] you actually just set the pointer but the underlying arrays are the same. As a result, every time you modify arguments[1] you also modify arguments[0]. To do what you want, you need to copy the array. You could do it this way:
if (arguments[1].length == 0) {
for(var i = 0; i < arguments[0].length; i++) {
arguments[1][i] = arguments[0][i];
}
}
To copy an array, instead of referencing it, use copy = original.slice(0).
Related
This is a general question. But an answer in JavaScript would suit me the best.
I'm searching for a way to create variables after a pattern automatically.
For example, I want to create a while-loop in which a variable gets declared. In set loop, I want to create the variable car1. However, in the next loop pass I want to do the same thing BUT call the Variable car2 this time.
I'll try to write it in pseudocode:
//this should happen in the first loop
while(true){
var car1 = 1 + 2;
console.log(car1)
}
//this should happen in the second loop
while(true){
var car2 = 1 + 2;
console.log(car)
}
//In both cases "3" should be the output. But different Variables
Contrary to this example. I want to do all this in a single while loop. And on every while loop, a new variable should be created. So car1,car2,car3,car4.
Thanks in advance!
Maybe you can use an array and add an item every loop iteration or a hash map with a naming convention you set for the keys
You can try to use globalThis or window.
function nameFunction(name, f) {
return {
[name](...args) {
return f(...args)
}
}[name]
}
// use globalThis
for (let i = 1; i <= 3; i++) {
const funcName = `car${i}`;
const func =
nameFunction(funcName, () => console.log(`this is car ${i}`));
globalThis[funcName] = func;
}
car1(); car2(); car3();
// use window
for (let i = 4; i <= 6; i++) {
const funcName = `car${i}`;
const func =
nameFunction(funcName, () => console.log(`this is car ${i}`));
window[funcName] = func;
}
car4(); car5(); car6();
I hope this link will help you with this problem.
JS Dynamic Variable
Here they have discussed 2 ways of solving the problem. (One with "eval" and the other with "windows" object.
The process: In the game I'm making, there's a for loop that's supposed to save a value in an array. That value changes with each iteration. The problem: when the loop is done running, every element of the array is identical, all showing the most recent value.
I know this issue is common, and I've made so many different tweaks and attempts at solving it over the past 2 days.
0) I tried separating things into separate functions as much as possible.
1) I tried defining my loop counters with "let" so they would have a local scope.
2) I tried wrapping my assignment in a self-executing function so it would happen immediately, preserving the value of currentlyOn before the next loop iteration changes it. My counter is the variable c.
(function(c2, currentlyOn2) {
onAtSameTime[c2] = currentlyOn2;
return 0;
})(c, currentlyOn);
3) I tried attempt #2 with the added feature of returning a function, which still didn't save the value of currentlyOn. This option isn't a good one for me anyway, because the whole point is that I'm doing some computations ahead of time so my game will have a quick animation loop.
onAtSameTime[c] = (function(currentlyOn2) {
return function() {
return currentlyOn2;
};
})(currentlyOn);
I'm tired of beating my head against this wall. Can anyone explain what I'm doing wrong?
For more details, check out the jsfiddle I made. The problem area is at line 59, using a simple assignment:
onAtSameTime[c] = currentlyOn;
onAtSameTime[c] = currentlyOn; sets onAtSameTime[c] equal to the reference of currentlyOn, since currentlyOn is an array, not a primitive value. That reference gets updated with each iteration. You could work around that by creating a copy of the array before adding it to the onAtSameTime array. Something like onAtSameTime[c] = [].concat(currentlyOn); would do the trick.
See this fork of your JSFiddle: https://jsfiddle.net/L2by787y/
You could make a copy from currentlyOn for assigning to onAtSameTime[c]. This keeps the values, but does not keep the reference to the same array.
onAtSameTime[c] = currentlyOn.slice(); // use copy
"use strict";
function log(text) {
document.getElementById("logbox").innerHTML += JSON.stringify(text) + "<br>";
return 0;
}
function whichSwitchesAreOn() {
var currentlyOn = [],
flickedSet,
flickedOne,
turningOnCheck;
for (var c = 0; c < switchesToggled.length; c++) {
flickedSet = switchesToggled[c];
for (var d = 0; d < flickedSet.length; d++) {
flickedOne = flickedSet[d];
turningOnCheck = currentlyOn.indexOf(flickedOne);
if (turningOnCheck == -1) {
currentlyOn.push(flickedOne);
} else {
currentlyOn.splice(turningOnCheck, 1);
}
}
log("currentlyOn: " + currentlyOn);
onAtSameTime[c] = currentlyOn.slice(); // use copy
}
return 0;
}
var switchesToggled = [[0], [1, 2], [0], [2], []],
onAtSameTime = [];
whichSwitchesAreOn();
log(onAtSameTime);
<div id="logbox"></div>
You say you have tried let?
Did you have let currentlyOn = [] inside of the for loop?
for(var c = 0; c < switchesToggled.length; c++) {
let currentlyOn = [];
I'm constructing a javascript indicator for my client and they gave me below C++ code from their old system. I have never done C++ program before. Below is the part of the C++ code. What I want to know is in the line
if (it3 != d1Swing.end() && it3->x == h[i].x) --(it1 = it2 = it3); what is the meaning of --(it1 = it2 = it3)? What will it looks like in javascript?
vector<PTPoint::PTIndexPoint> dnSwing;
list<PTPoint::PTIndexPoint> hq, lq;
vector<PTPoint::PTIndexPoint>::iterator it1 = d1Swing.begin(), it2 = d1Swing.begin(), it3 = ++d1Swing.begin();
//
// more code here
//
for (int i = 0; i < period; ++i)
{
while (!hq.empty() && hq.back().y < h[i].y) hq.pop_back();
hq.push_back(h[i]);
while (!lq.empty() && lq.back().y > l[i].y) lq.pop_back();
lq.push_back(l[i]);
if (it3 != d1Swing.end() && it3->x == h[i].x) --(it1 = it2 = it3);
//
// more code here
//
}
//
// more code here
//
p->swap(dnSwing);
Thanks in advance.
tslin
It means that their previous programmer loved being "clever".
The value of an assignment is a reference to the object that was assigned to, and assignment associates to the right.
--(it1 = it2 = it3)
is
--(it1 = (it2 = it3))
and it's intended to assign the value of it3 to it2 and it1, then decrement it1.
(I have a hunch that this may be undefined, which is a thing that happens frequently when you're being clever in C++.)
it1 is apparently intended to be "one step behind" it2.
A more reasonable way to write that is
it2 = it3;
it1 = it2 - 1;
(In JavaScript, I suspect that you need to work with array indices rather than iterators to accomplish the same thing.)
I am trying to make two arrays. the unique array can get the elements (no repeats) from the text array, and the counter one can count the frequency of each elements. but something is wrong with the counter one.
var unique_array=new Array();
var counter_array=new Array();
var unique=true;
for (i=0;i<text_array.length;i++){
if (unique_array.length==0){
unique_array.push(text_array[0]);
counter_array.push(1);
}
else if(unique_array.length>0&&unique_array.length<=text_array.length){
for (j=0; j<unique_array.length;j++){
if (text_array[i]==unique_array[j]){
counter_array[j]=counter_array[j]+1;// something wrong with the
alert(counter_array[j]);
var unique=false;
}
}
if (unique==true){
unique_array.push(text_array[i]);
counter_array.push[1];
}
unique=true;
}
You could also simplify the code down using a hashmap and some ES5 higher-order functions:
var text_array = ["a1","a1","a2","a3","a2","a4","a1","a5"];
var counts = {};
text_array.forEach(function(el) {
counts[el] = counts.hasOwnProperty(el) ? counts[el]+1 : 1;
});
var unique_array = Object.keys(counts);
var counter_array=unique_array.map(function(key) { return counts[key]; })
You can do this much more simply using an object. Let the values be the keys of an object, then just increment the count of each property as you go. At the end, you can get an array of the unique keys and their values:
var text_array = ['foo','bar','foo','fum','fum','foo'];
var i = text_array.length;
var obj = {};
while (i--) {
if (obj.hasOwnProperty(text_array[i])) {
obj[text_array[i]]++;
} else {
obj[text_array[i]] = 1;
}
}
console.log('Unique values: ' + Object.keys(obj)); // Unique values: foo,fum,bar
console.log('Value counts: ' + Object.keys(obj).map(function(v){return obj[v]})); // Value counts: 3,2,1
Note that the sorting of counts in the output is purely coincidental.
As Jasvir posted, you can make it pretty concise:
var obj = {};
text_array.forEach(function(v) {
obj.hasOwnProperty(v)? ++obj[v] : obj[v] = 1;
});
But the first example is a bit easier to digest.
I think the approach is what's making it difficult. A hash table / associative array would be much easier to work with.
With a hash table (an object {} in JS), you can store each word in a key and increment the value of the key when you encounter the word again. Then, at the end, just go through the hash table and gather up all the keys which have small values. Those are your unique words.
function get_unique_words(text_array) {
var hash_table, i, unique_words, keys;
hash_table = {};
for(i = 0; i < text_array.length; i++) {
if(hash_table[text_array[i]] === undefined) {
hash_table[text_array[i]] = 1;
} else {
hash_table[text_array[i]]++;
}
}
// go through the hash table and get all the unique words
unique_words = [];
keys = Object.keys(hash_table);
for(i = 0; i < keys.length; i++) {
if(hash_table[keys[i]] === 1) {
unique_words.push(keys[i]);
}
}
return unique_words.sort();
}
console.log(get_unique_words(
['blah', 'blah', 'blah', 'goose', 'duck',
'mountain', 'rock', 'paper', 'rock', 'scissors']
));
Some issues and suggestions :
Don't use var twice for the same variable.
Browsers deal with it ok, but for clarity you should only be declaring your variables once.
Always localize your loop counters - forgetting a var before your i and j will cause them to become global variables.
This is relevant when you have a page with lots of code - all global variables will show up in the debugger's watch list at all times, making it harder to debug your code.)
Use the array literal notation [] instead of the function form Array.
The function form is longer and it's easier to forget the new. It's also easier to read (IMO).
Use more whitespace (it won't bite), such as before and after an equals sign:
var x = 1;
// vs.
var x=1;
It makes the code easier to read and most people don't overdo it.
Indent your code when it's inside a block (e.g. function, if, else, while, for, etc.).
This makes it easier to read the control flow of the code and will help prevent bugs.
Use three equals signs (===) unless you are using loose equality on purpose.
This will help someone looking at your code later (probably yourself) understand better what the test is supposed to be testing.
Is there any way I can uniquely identify a function without giving it an expando property? I've been just using "toString()" to identify the function, but when two functions are identical, they conflict.
The following sample code reproduces the problem. In my actual code, the key for the associative array "myfunctions" is built from other parameters as well. I don't want to generate a meaningless key since the developers using this code need to be able to rebuild this key at any time without holding a reference to some random key.
var myfunctions = {};
(function(){
var num = 1;
function somefunc() {
alert(num);
}
myfunctions[somefunc.toString()] = somefunc;
})();
(function(){
var num = 2;
function somefunc() {
alert(num);
}
myfunctions[somefunc.toString()] = somefunc;
})();
for (var f in myfunctions) {
myfunctions[f]();
}
When this code is run, only one alert fires, and it always has the message "2".
The answer is no, there isn't any unique string value you can draw from a function with which you can associate that specific instance.
Why do you want to avoid using an expando?
I suspect that whatever you put in a property name (not a hash key, a property name) will be converted to string anyway.
This does not work either
(function(){
var num = 1;
function somefunc() {
alert(num);
}
somefunc.blah = 1;
myfunctions[somefunc] = somefunc;
})();
(function(){
var num = 2;
function somefunc() {
alert(num);
}
somefunc.bloh = 1;
myfunctions[somefunc] = somefunc;
})();
I just did some reading, and it seems like a property name can only be a string.