Access a variable based on other variable value in Javascript [duplicate] - javascript

This question already has answers here:
Accessing an object property with a dynamically-computed name
(19 answers)
Closed 4 months ago.
This post was edited and submitted for review 4 months ago and failed to reopen the post:
Original close reason(s) were not resolved
I have a bunch of variables having boolean values. I wish to have another variable that stores the name of the boolean variable changed last. So, next time when a new boolean variable value is changed, I want to toggle the previous boolean variable.
Any idea/suggestion to achieve the above would be highly appreciated.
Eg. it would be something like this incorrect code-
isDemo1=false; isDemo2=false; isDemo3=true; isDemo4=false; isDemo5=false;
lastChangedBooleanVariable = this.isDemo3;
handleBooleanVaiables(currentChangedBooleanVariable: string)
{
// somehow toggle this.isDemo3 variable value
this.lastChangedBooleanVariable = currentChangedBooleanVariable;
// let's say currentChangedBooleanVariable = isDemo4
// somehow toggle this.isDemo4 value
}

Everytime that you need to do some weird code, rethink your approach, it will probably wrong.
You can instead use Arrays:
isDemo = [false, false, true, false, false];
lastChangedBooleanVariable = 3;
handleBooleanVaiables(currentChangedBooleanVariable: int) {
this.lastChangedBooleanVariable = currentChangedBooleanVariable;
isDemo[currentChangedBooleanVariable - 1] = !isDemo[currentChangedBooleanVariable - 1]
}

Sounds very much like what you're trying to do is functionally equivalent to:
let demo = 3;
Then set the value of this variable to any value from 1 to 5.
Instead of if (isDemo2), test if (demo == 2).
The "last changed variable" is always simply the current value demo holds, and that's probably obsolete information with this approach.

ES6 has a feature on Arrays called fill which can be pretty handy here. Essentially, you just set all the values to false before you activate a new version.
let demos = new Array(5).fill(false);
function activateDemo(demo) {
demos = new Array(5).fill(false);
demos[demo] = true;
}
activateDemo(4);
let demos = new Array(5).fill(false);
function activateDemo(demo) {
const humanIndex = demo > 0 ? demo - 1 : 0; // to make it into human counting form, if you want.
demos = new Array(5).fill(false);
demos[humanIndex] = true;
}
activateDemo(4);
console.log("4", demos);
activateDemo(3);
console.log("3", demos);

var keys = {
"isDemo1":false, "isDemo2":false, "isDemo3":false, "isDemo4":false, "isDemo5":false;
};
var lastChangedBooleanVariable: string = "isDemo3";
const nameOf = (f) => (f).toString().replace(/[ |\(\)=>]/g,'');
function getName(varName:string){
return varName.substring(
varName.indexOf(".") + 1,
varName.lastIndexOf(";")
);
}
function handleBooleanVaiables(currentChangedBooleanVariable: string)
{
console.log(keys[lastChangedBooleanVariable]);
keys[lastChangedBooleanVariable] = !keys[lastChangedBooleanVariable];
keys[currentChangedBooleanVariable] = ! keys[currentChangedBooleanVariable];
lastChangedBooleanVariable = currentChangedBooleanVariable;
// let's say currentChangedBooleanVariable = isDemo4
// somehow toggle this.isDemo4 value
}
function printValues(){
console.log(keys);
}
var varName = getName(nameOf(()=>keys.isDemo1));
handleBooleanVaiables(varName);
printValues();
varName = getName(nameOf(()=>keys.isDemo4));
handleBooleanVaiables(varName);
printValues();
here's fiddle: https://jsfiddle.net/hjv540tk/

Related

How to check empty in variable in Google Apps Script [duplicate]

This question already has answers here:
How do I check for an empty/undefined/null string in JavaScript?
(52 answers)
Google Spreadheets Scripts: check if cell is empty
(3 answers)
Closed 1 year ago.
I have a variable that can be either empty, number or text. I like to find only empty one. But the following codes using .length returned null for 0 number, though it returned 1 for "0" string . .toString.length even didn't work. Any suggestion? Thank you!
function test() {
// criteria can be either empty, number or text. How can I check whether the critieria is empty?
// In the example below, critiera_2.length returned null, not 1.
criteria_1 = "";
Logger.log(criteria_1.length);
criteria_2 = 0;
Logger.log(criteria_2.length);
criteria_3 = "0";
Logger.log(criteria_3.length);
criteria_4 = "X";
Logger.log(criteria_4.length);
criteria_1 = "";
Logger.log(criteria_1.toString.length);
criteria_2 = 0;
Logger.log(criteria_2.toString.length);
criteria_3 = "0";
Logger.log(criteria_3.toString.length);
criteria_4 = "X";
Logger.log(criteria_4.toString.length);
}
criteria_1 = "";
console.log(criteria_1.toString() == ''); // output: true
const test = x => console.log(x.toString()==='');
test(""); // true
test(0); // false
test("0"); // false
test("X"); // false
It's turned out that you don't even need toString() it could be just x===''
To check for an empty string, a simple approach would be to use === operator
if (criteria_1 === "") {
//...
}

Pushing variable to an array depending on the checkbox selected

I have an simple example here, the check boxes were already given by the framework we are using so it just checks weather it is checked or not(returns true or false). And I have three variables with different options that will be pushed in an array and gets removed when unchecked. By the way I have made it worked but I think there is more proper way to do this.
var chk1 = data.config.chk1; // returns true or false only
var chk2 = data.config.chk2; // same as above
var chk3 = data.config.chk3;
var settA = "settingsA";
var settB = "settingsB";
var settC = "settingsC";
if (chk1) {
arr.push(settA)
}
if (chk2) {
arr.push(settB)
}
if (chk3) {
arr.push(settC);
}
console.log(arr)
I would eidt your Object that contains the chk# keys (with true or false values) with the actual settings value instead. Then if its in the object you know its true. That way you can make your code easier to handle like so.
var Chks = data.config;
for(var key in Chks)
arr.push(Chks[key])
Now if your object contained data.config.chk3 = 'SettingsA' your array will contain 'SettingsA'.
Maybe this wont work for you, but as a rule of thumb if your repeating the same commands over and over you should probably abstract, like use an itterator.

De-referencing a JavaScript property from inside an array [duplicate]

This question already has an answer here:
Javascript closure not working
(1 answer)
Closed 5 years ago.
I'm trying to de-reference a property on a JavaScript object, but am not getting the expected result.
I have an array of Knockout view-models (I don't think the problem is Knockout-specific), each of which has an observable, Selected. I add a subscription to this observable so that a function, crossSelectTargetLangs is called when the value of Selected is changed.
Furthermore, I add this subscription inside a for... loop.
var tl = 0,
tlMax = allLangVMs.length,
vmLang,
selectedCode;
// for each 'vmLang' view-model in the 'allLangVMs' array...
for (; tl < tlMax; tl++) {
// local variable for the context view-model
vmLang = allLangVMs[tl];
// add the subscription to this observable
vmLang.Selected.subscribe(function() {
// de-reference the vmLang.Code property
selectedCode = (function(code) {
return code;
}(vmLang.Code));
// pass the de-ref'd value to the target function
crossSelectTargetLangs(selectedCode);
});
}
However, regardless of which view-model had its Selected observable updated, the argument passed to the target function is always the Code from the last element in the array, i.e. it doesn't appear to be de-referencing.
What am I doing wrong?
The problem is that you are making dereferencing in a wrong place.
The code should look like this:
var tl = 0,
tlMax = allLangVMs.length,
vmLang,
selectedCode;
// for each 'vmLang' view-model in the 'allLangVMs' array...
for (; tl < tlMax; tl++) {
// local variable for the context view-model
vmLang = allLangVMs[tl];
(function(vmLangParam) {
vmLangParam.Selected.subscribe(function() {
crossSelectTargetLangs(vmLangParam.Code);
});
})(vmLang);
}

For loop not working as expected, what am I doing wrong? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
I'm making a form where the user can RSVP for themselves and up to 5 others. Each guest has a text field for their names and then radio buttons (yes or no) as to whether they are attending or not. By default Guest 1 & 2 are displayed and then there is a button the user can click to add another guest up until guest #6.
Guest's 3 - 6 are contained in their own objects like this:
var guestThree = {
name : document.querySelector('label[for="nameOfThirdGuest"]'),
attendingYes : document.querySelector('label[for="guestThreeAttendingYes"]'),
attendingNo : document.querySelector('label[for="guestThreeAttendingNo"]')
};
var guestFour = {
name : document.querySelector('label[for="nameOfFourthGuest"]'),
attendingYes : document.querySelector('label[for="guestFourAttendingYes"]'),
attendingNo : document.querySelector('label[for="guestFourAttendingNo"]')
};
var guestFive = {
name : document.querySelector('label[for="nameOfFifthGuest"]'),
attendingYes : document.querySelector('label[for="guestFiveAttendingYes"]'),
attendingNo : document.querySelector('label[for="guestFiveAttendingNo"]')
};
var guestSix = {
name : document.querySelector('label[for="nameOfSixthGuest"]'),
attendingYes : document.querySelector('label[for="guestSixAttendingYes"]'),
attendingNo : document.querySelector('label[for="guestSixAttendingNo"]')
};
I am hiding guest's 3 - 6 using the following function which are then converted to methods for the above objects:
function hideFields() {
this.name.style.display = "none";
this.attendingYes.style.display = "none";
this.attendingNo.style.display = "none";
}
I also have the opposite of the above function in showFields:
function showFields() {
this.name.style.display = "block";
this.attendingYes.style.display = "block";
this.attendingNo.style.display = "block";
}
So the idea here is that when the add guest button (which is assigned to the variable addGuest) is clicked guest #3 will be added. Then when it's clicked again guest #4 will be added and so on until #6. I've added the guestThree - guestSix objects to the following array:
var extraGuests = [guestThree, guestFour, guestFive, guestSix];
and then using the following for loop:
for (var guest = 0; guest < extraGuests.length; guest++) {
addGuest.onclick = function() {
extraGuests[guest].showFields();
};
}
But this doesn't work. I have discovered through testing that guest loops all the way round to 4 without executing the showFields methods. If I was to add a break after the onclick event then guestThree will display but that's it (obviously because that's how break works) but this atleast shows that the loop works as I hoped - to an extent.
So what I am asking of you guys is - what am I doing wrong? How do I make it so that the guest variable doesn't loop straight to 4? I need each iteration to be 0, 1, 2 and finally 3 and as far as I can see that is exactly what should be happening?
Cheers!
There are two problems:
The first is that you're overwriting the onclick on addGuest on every loop, so only the last assignment survives. So if we fix the second problem (below), you'll still only show the last set of fields. Probably, we want the handler assigned once, and have it reveal the "next" set of fields.
The second problem is that the function you're assigning to onclick has an enduring reference to the guest variable, not a copy of it as of when the function was created. So later, when the function gets called, it sees the value guest has after the end of the for loop. Your main choices for solving that are a builder function, and Function#bind as described under this question. But since we don't need or want the loop, it doesn't matter.
Instead, I'd suggest a variable telling you what the next set of fields to reveal is, and then simply one function that uses it:
var extraGuests = [guestThree, guestFour, guestFive, guestSix];
var nextGuest = 0;
addGuest.onclick = function() {
var guest = extraGuests[nextGuest];
if (guest) {
++nextGuest;
guest.showFields();
}
};
You've closed over a loop variable, which means that at the time they are called, your click handlers are all looking at a single value of guest, which will be extraGuests.length (the value it settles on when the loop is complete).
You need to capture the loop variable at the time the loop executes, which can be done easily using an Immediately-invoked function expression. :
for (var guest = 0; guest < extraGuests.length; guest++) {
(function(ind){
addGuest.onclick = function() {
extraGuests[ind].showFields();
};
})(guest);
}
There's probably better/more succinct ways to do this using newer language features.
Maybe this.
var guest = 0;
addGuest.addEventListener('click', function() {
if(guest < extraGuests.length)
extraGuests[++guest].showFields();
}, false);

assign variable 1 to variable 2 and variable 2 to variable 3 javascript

i've got an array, and i want to shuffle those according to a certain pattern
(i'm trying to make a rubics cube in javascript).
I want to assign value2 to value 1 and value 1 to value 3 and value 3 to value 2. I can do that within 4 lines of code, but is there a shorter way?
like:
temp = var3; //make temporary variable
(var3 = var2) = var1;//put var2 in var3 and var3 in var1
var1 = temp;//put var3/temp in var1
i know that it doesn't work this way, but do you guys know a way it does work?
that would be usefull when cycling 8 variables.
thanks,
Tempestas Ludi.
If you're dealing with more than 2 variables, it's always best to use an array, since arrays have built in functions you can use
var nums = [1,2,3]; // this is your array. it can have any length you want
// this is one line that does the magic
nums.push(nums.shift()); // to the left
nums.unshift(nums.pop()); // to the right
http://jsfiddle.net/wbKYY/2/
http://jsfiddle.net/wbKYY/4/
Anyway, about your comment. Seeing as the pointers which you will rotate aren't predetermined, and will vary, it's probably best to use a function.A function that will iterate through pointers that you define.
function rotateArr(arr,pointers,dir) {
var narr = arr; // create a local copy we can use it
var savevalue;
if (dir == 1) { // rotate to the right
savevalue = narr[pointers[pointers.length-1]]; // save the last value
for(var i=pointers.length-2;i>=0;i--) {
narr[pointers[i+1]] = narr[pointers[i]];
}
narr[pointers[0]] = savevalue; // set the first value
} else { // rotate to the left
savevalue = narr[pointers[0]]; // save the first value
for(var i=0;i<pointers.length-1;i++) {
narr[pointers[i]] = narr[pointers[i+1]];
}
narr[pointers[pointers.length-1]] = savevalue; // set the last value
}
return narr;
}
// arr is the array of faces
// pointers is the elements which you want to rotate (an array)
// dir is either 1 or -1
you can execute this function with
nums = rotateArr(nums,[pointers],[1,-1]);
// just some examples
nums = rotateArr(nums,[0,1,2,5],1);
nums = rotateArr(nums,[3,6,1,4],-1);
Here's a working example:
http://jsfiddle.net/w2jGr/
However if you prefer to use a prototype function that is just a method of an array, you can define a property and just access it from there.
Object.defineProperty(Object.prototype, "rotateArr", { value: function(pointers,dir) {
var savevalue;
if (dir == 1) { // rotate to the right
savevalue = this[pointers[pointers.length-1]]; // save the last value
for(var i=pointers.length-2;i>=0;i--) {
this[pointers[i+1]] = this[pointers[i]];
}
this[pointers[0]] = savevalue;
} else { // rotate to the left
savevalue = this[pointers[0]]; // save the last value
for(var i=0;i<pointers.length-1;i++) {
this[pointers[i]] = this[pointers[i+1]];
}
this[pointers[pointers.length-1]] = savevalue;
}
}, enumerable : false});
Modifying the prototype of an object is never recommended, but if you aren't going for clean code and want usability or readability, this works great as you can call the function with
nums.rotate([pointers],dir);
http://jsfiddle.net/w2jGr/1/
Why not put your values in an array, and just change the index pointer when you want to use different values?

Categories

Resources