So I'm trying to check for an undefined object out of multiple ones and then do something with that specific one. This code below works but I can imagine that there's a better way than just using else if 20 times in a row.
if (duelswins === undefined) {
document.getElementById('duels_wins').style.display = 'none'
} else if (duelslosses === undefined) {
document.getElementById('duels_losses').style.display = 'none'
} else if (duelskills === undefined) {
document.getElementById('duels_kills').style.display = 'none'
} else if (duelsdeaths === undefined) {
document.getElementById('duels_deaths').style.display = 'none'
} else if (duelsgoals === undefined) {
document.getElementById('duels_goals').style.display = 'none'
} else if (duelskdr === undefined) {
document.getElementById('duels_kdr').style.display = 'none'
} else if (duelswlr === undefined) {
document.getElementById('duels_wlr').style.display = 'none'
} else if (duelsgwr === undefined) {
document.getElementById('duels_gwr').style.display = 'none'
}
There can be multiple ones of those being undefined but it could also be also none of them.
This is just an example, I'm mostly interested if there's and alternative for using so many if statements just for checking basically the same thing over and over again.
Instead of using individual variables you can put these values into an object and then loop over the keys/values. I'm not sure what your requirements are exactly but this might be a step in the right direction:
const data = {
duels_wins: undefined,
duels_losses: 123,
duels_deaths: undefined,
// ...
};
Object.entries(data).forEach(([key, value]) => {
if (value === undefined) {
document.getElementById(key).style.display = 'none';
}
});
<div id="duels_wins">duels_wins</div>
<div id="duels_losses">duels_losses</div>
<div id="duels_deaths">duels_deaths</div>
Related
Background: Below coding work fine, and i am able to use both function and return the expected value.
Question: Is there any way to simplify below function coding?
red_messages_disabled_p1() {
let s = this.status;
if (s.red_messages[0] === null) {
return 'none';
} else {
return 'inline-block';
}
},
red_messages_disabled_p2() {
let s = this.status;
if (s.red_messages[1] === null) {
return 'none';
} else {
return 'inline-block';
}
},
What did I try?
I tried to figure it out but no idea, guessing it's not possbile to simplify any more, am i correct?
Expecting?
I expecting there maybe simplify way for this coding.
First option :
red_messages_disabled_p(i) {
return this.status.red_messages[i-1] === null ? 'none' : 'inline-block';
}
Second option :
red_messages_disabled_p(i) {
return this.status.red_messages[i-1] ? 'inline-block' : 'none';
}
Get rid of code duplication. Both of your functions contain the same logic. So move that logic into a separate method as shown below:
class MyClass {
status = {red_messages: []}
redMsgDisplayStyle(msg) {
if (msg === null) {
return 'none';
}
return 'inline-block';
}
red_messages_disabled_p1() {
return this.redMsgDisplayStyle(this.status.red_messages[0])
}
red_messages_disabled_p2() {
return this.redMsgDisplayStyle(this.status.red_messages[1])
}
}
This will not only simplify the code, but also make it less error prone in case of you decide to change the logic in the future.
Also, replacing if-else with a ternary operator is probably not a good idea because: 1) it doesn't actually simplify the logic, just a different syntax and 2) ternary operator is less readable.
use a parameterized function
red_messages_disabled(index) {
let s = this.status;
if (s.red_messages[index] === null) {
return 'none';
} else {
return 'inline-block';
}
}
red_messages_disabled_p1() {
return this.red_messages_disabled(0);
};
red_messages_disabled_p2() {
return this.red_messages_disabled(1);
};
Use a ternary operator
red_messages_disabled_p1() {
let s = this.status;
return s.red_messages[0] === null ? 'none' : 'inline-block';
}
red_messages_disabled_p2() {
let s = this.status;
return s.red_messages[1] === null ? 'none' : 'inline-block';
}
There are already lots of good answers for this question, but I wanted to submit my own solution.
const redMessageDisabled => (index) {
return (s.red_messages[index] === null)?"none":"inline-block";
}
However, I think you can just pass s.red_messages[index] to the function
const redMessageDisabled => (data) {
return (data === null) ? "none" : "inline-block";
}
I am trying to jQuery-like script that supports selectors, show, hide, text, and html methods.
Running a test, no matter which method I call, it always throws a custom "No Element Selected" error. How do I fix this?
The full code is here --> https://jsfiddle.net/7ado13vg/
The relevant code is below
var storingAttributes = {};
class MONEY {
constructer(string) {
try {
//check for action
if (string != null) {
//Check Selection Type
storingAttributes.selectorArray = string.split('')
if (storingAttributes.selectorArray[0] == '#') {
storingAttributes.selectionType = 'id';
storingAttributes.selectorArray.splice(0, 1);
}
if (storingAttributes.selectorArray[0] == '.') {
storingAttributes.selectionType = 'class';
storingAttributes.selectorArray.splice(0, 1);
}
if (storingAttributes.selectorArray[0] != '#' && storingAttributes.selectorArray[0] != '.') {
storingAttributes.selectionType = 'tag';
}
//Select Elem
if (storingAttributes.selectionType == 'id') {
storingAttributes.selectedElem = document.querySelector(string);
}
if (storingAttributes.selectionType == 'class') {
storingAttributes.selectedElem = document.querySelectorAll(string);
}
if (storingAttributes.selectionType == 'tag') {
storingAttributes.selectedElem = document.querySelectorAll(string);
}
}
} catch (error) {
}
}
//The reason I checked what was being selected is because querySelectorAll returns an array, and I do not believe that ids are supported
//trying to use my method 'show'
show() {
try {
if (typeof storingAttributes.selectedElem == 'undefined' || storingAttributes.selectedElem == null) {
throw "No Element Selected";
} else {
if (storingAttributes.selectionType == 'tag') {
for (n = 0; n < storingAttributes.selectedElem.length; ++n) {
storingAttributes.selectedElem[n].style.display = 'block';
}
return;
}
if (storingAttributes.selectionType == 'class') {
for (n = 0; n < storingAttributes.selectedElem.length; ++n) {
storingAttributes.selectedElem[n].style.display = 'block';
}
return;
}
if (storingAttributes.selectionType == 'id') {
storingAttributes.selectedElem.style.display = 'block';
return;
}
}
} catch (e) {
console.log(e);
}
}
}
As you can see, the constructor simply assigns/initializes a value for selectionType, selectedElem, and selectorArray in the object storingAttributes
When you log storingAttributes, it returns an empty object.
The following replaces the code you've posted to show how much simpler it can be written and without erroneously using try/catch.
I understand that it doesn't answer your question, but the code you are working with is really so unnecessarily excessive, it's hard to sift through it to find your problem without refactoring it. Simpler code is easier to debug.
var storingAttributes = {};
// Just test for the non-existance of a value
if (!storingAttributes.selectedElem) {
throw "No Element Selected";
} else {
// switch is more concise when you have a single value to
// check against multiple possible values
switch (storingAttributes.selectionType){
case "tag":
// And since you want to do the exact same code if
// it's "tag" or "class", we'll allow fall through here
case "class":
// The Array.prototype.forEach method makes looping much simpler
storingAttributes.selectedElem.forEach(function(item){
item.classList.add("block");
});
break;
case "id":
storingAttributes.selectedElem.classList.add("block");
}
}
/* Avoid inline styles which lead to duplication of code.
Instead, use CSS classes where possible. */
.block { display:block; }
im studying JavaScript and im trying to solve the problem in this test exercise:
FreeCodeCamp Record Collection
I can't understand why it doesnt work. The object details and the problem description are in the link above.
function updateRecords(object, id, prop, value) {
if (value === '') {
delete object[id][prop];
} else if (prop === 'tracks') {
if (object[id][prop].hasOwnProperty('tracks') == false) {
object[id][prop] = [value];
} else if (value !== '') {
object[id][prop].push(value);
}
} else if (prop !== 'tracks' && value !== '') {
object[id][prop] = value;
}
return object;
}
This is the error i get:
// running tests
After updateRecords(collection, 5439, "tracks", "Take a Chance on Me"), tracks should have Take a Chance on Me as the last element.
After updateRecords(collection, 2468, "tracks", "Free"), tracks should have 1999 as the first element.
// tests completed
Thank you for your support.
Let's take a look at this line:
if (object[id][prop].hasOwnProperty('tracks') == false) {
If we replace the variables with their values, we get:
if (object[5439]['tracks'].hasOwnProperty('tracks') == false) {
^ ^
... which is always going to fail. Here is a simplified version:
function updateRecords(object, id, prop, value) {
if (value === '') {
delete object[id][prop];
} else if (prop === 'tracks') {
if (!object[id].hasOwnProperty('tracks')) {
object[id][prop] = [];
}
object[id][prop].push(value);
} else {
object[id][prop] = value;
}
return object;
}
I have the following the condition:
useEffect(() => {
const hasFalsyValue = (
dropdownValue === undefined
|| dropdownValue === null
);
if (hasFalsyValue && !onChangeText) {
return;
}
onChangeText(dropdownValue);
}, [
dropdownValue,
onChangeText,
inputProps,
]);
If hasFalsyValue is true, then, the effect will return right away. But TS is yelling on me saying the dropdownValue can still be undefined
If I extract the conditions from the constant and put it inside the conditional parenthesis, it will work
If hasFalsyValue is true, then, the effect will return right away.
No - only when hasFalsyValue is true and onChangeText is falsy. You might have meant
const hasFalsyValue = (dropdownValue === undefined || dropdownValue === null);
if (hasFalsyValue || !onChangeText) {
return;
}
onChangeText(dropdownValue);
or
const hasFalsyValue = (dropdownValue === undefined || dropdownValue === null);
if (!hasFalsyValue && onChangeText) {
onChangeText(dropdownValue);
}
Btw I'd recommend to shorten this to
if (dropdownValue != null) {
onChangeText?(dropdownValue);
}
That's almost OK. you misused && and TypeScript is not so smart to pick up variable, so this should work:
#1 Define guard
function isDefined<T>(v: T|undefined): v is T {
return v!= null
}
#2 use it
if (!isDefined(dropdownValue) || !onChangeText) {
return;
}
onChangeText(dropdownValue);
I am calling an object method in two ways in my code:
this.reveal.updateVisuals(i, 'show');
or
this.reveal.updateVisuals(i, 'hide');
and I am passing the hide and show condition as a string, to be later evaluated and used as a method. Please note the condition: if (effect === 'show/hide').
updateVisuals: function (time, effect) {
// Check if parameter exists and property can be read
if (this.breakpointsMap && typeof this.breakpointsMap[checkTime] !== "undefined") {
if (effect === 'show') {
// display the items that were fast forwarded
var k = this.breakpointsMap[checkTime].length;
while (k--) {
try {
this.breakpointsMap[checkTime][k].show();
} catch (err) {}
}
} else if (effect === 'hide') {
// display the items that were fast forwarded
var k = this.breakpointsMap[checkTime].length;
while (k--) {
try {
this.breakpointsMap[checkTime][k].hide();
} catch (err) {}
}
}
}
}
However the code seems duplicated and I was wondering if there is a way to pass hide or show as a method to the method and apply it on the array, when needed. I tried something like this:
this.reveal.updateVisuals(i).show
There are a lot of ways you can use to simplify this, here are a couple:
updateVisuals: function (time, effect) {
if (this.breakpointsMap && typeof this.breakpointsMap[checkTime] !== "undefined") {
this.breakpointsMap[checkTime].forEach(e => e[effect]());
}
}
Or returning the array:
updateVisuals: function (time, effect) {
if (this.breakpointsMap && typeof this.breakpointsMap[checkTime] !== "undefined") {
return this.breakpointsMap[checkTime];
}else{
return [];
}
}
this.reveal.updateVisuals(i).forEach(e => e.show());
You can access a method property by it's (string) name using [bracket] notation.
updateVisuals: function (time, effect) {
// Check if parameter exists and property can be read
if (this.breakpointsMap && typeof this.breakpointsMap[checkTime] !== "undefined") {
var k = this.breakpointsMap[checkTime].length;
while (k--) {
try {
this.breakpointsMap[checkTime][k][effect]();
} catch (err) {}
}
}
}
if you are using Es6, you can do:
function updateVisuals (time, effect) {
// Check if parameter exists and property can be read
if (this.breakpointsMap && typeof this.breakpointsMap[checkTime] !== "undefined") {
let execFn= (arrindex) => breakpointsMap[checkTime][arrindex].show();
if (effect === 'hide')
{
execFn = (arrindex) => breakpointsMap[checkTime][arrindex].hide();
}
// display the items that were fast forwarded
var k = this.breakpointsMap[checkTime].length;
while (k--) {
try {
execFn(k);
} catch (err) {}
}
}
}
I assume that var checkTime is global or in closure. If you are using version lower tan es6 you can use execFn= function (arrindex) {...}, a then bind this argument when calling method after.