template strings inside if statements - javascript

is it correct syntax to use string literals inside if statements. please guide. how can i use categ dynamically in the function based on different values so that i dont have to write the same function for every button clicked.
const filterButtons= document.querySelectorAll(".filter-btn")
let categ;
filterButtons.forEach(function (btn) {
btn.addEventListener("click",function (e) {
if(e.currentTarget.dataset.id=="price") {
categ = "price";
console.log(categ);
}
if(e.currentTarget.dataset.id=="discountPercentage") {
categ = "discountPercentage";
console.log(categ);
}
if(e.currentTarget.dataset.id=="rating") {
categ = "rating";
console.log(categ);
}
let newModData = [...mainProducts];
let i=0;
let j=0;
let fixed = 0
while(j< newModData.length-1) {
while(i< newModData.length-1)
{
if(`newModData[i+1].${categ}`< `newModData[fixed].${categ}`)
{
const temp = Object.assign({}, newModData[fixed]);
newModData[fixed] = newModData[i+1];
newModData[i+1] = temp;
}
i++;
}
i=j+1;
fixed++;
j++;
}
displayNew(newModData);
})
is it correct syntax to use string literals inside if statements. please guide. how can i use categ dynamically in the function based on different values so that i dont have to write the same function for every button clicked.

If newModData is an array of objects, then the correct syntax is:
if(newModData[i+1][categ] < newModData[fixed][categ]) {
// Your logic here
}
To access properties of an object dynamically you must use brackets [] instead of dot .:
const prop = "name"; //
const someObj = {
name: "Jane",
age: 20
}
console.log(someObj[prop]); // --> Jane

Related

Get each variable from class in a for loop

I'm creating an interpreter that reads
variable1: 2
variable2: 400
variable3: 31
from a text file, and initializes the variables on runtime. using eval() and Regular Expressions
class Rules{
getSegmentArgs_string(sgmnt, scope)
{
let argarray = new Array;
let vardeclaration;
for(let i=0; i<this.rules[sgmnt].length; i++)
{
let regexp = /(\w+): ([0-9\.]+)/g;
for (const match of this.rules[sgmnt][i].matchAll(regexp)) {
vardeclaration = (scope+match[1].toString() + " = "+match[2].toString()+";");
argarray[i] = vardeclaration;
}
}
return argarray;
}
setSegment(sgmnt)
{
this.segment = sgmnt;
}
init()
{
this.defaultvars = this.getSegmentArgs_string(this.segment,"this.")
for(let i=0; i<this.defaultvars.length; i++)
{
eval(this.defaultvars[i]);
}
delete(this.rules);
delete(this.defaultvars);
delete(this.segment);
}
constructor() {
this.rules = this.dump();
}
}
let rules = new Rules;
rules.setSegment(3);
rules.init();
However, I can not understand how to access these initialized variables in a for loop that dumps each variable's name, as well as its' value
for (const variables in rules)
{
console.log({variales});
console.log({variables}.value);
}
I'm capable of accessing the value when doing
console.log(rules.variables1,rules.variables2,rules.variables3)
but due to the nature of the task, I need to loop through all variables without naming them in code.
for...in gives you the key of the object properties. You have to access the value with the key
for (const key in rules)
{
console.log(key, rules[key]);
}

How to connect a button function to an object property?

This is the simplified code I'm working with. Is there a better way to find the correct bool?
I'm a beginner so I dont understand keyword "this" completely, but is there a way to connect button with a coresponding object maybe with "this" or something simmilar?
arr = [
{
name: "obj1",
bool: false,
},
{
name: "obj2",
bool: false,
}
];
function buildButtons() {
for (var i = 0; i < arr.length; i++) {
let button = document.createElement("button");
button.innerHTML = arr[i].name;
button.onclick = function() {
// is there a better way to find the correct bool?
for (i = 0; i < arr.length; i++) {
if (this.innerHTML === arr[i].name) {
arr[i].bool = true;
}
}
};
window.document.body.appendChild(button);
}
}
buildButtons();
Your best bet is to change the data structure to a more appropriate one. Rather than having to loop through an array to find the correct name, just use the names as keys in a single object, so you can look them up directly. Altered code follows:
obj = { obj1: false, obj2: false}
function buildButtons() {
for (let name in obj) {
let button = document.createElement("button");
button.innerHTML = name;
button.onclick = function() {
obj[name] = true;
}
window.document.body.appendChild(button);
}
}
buildButtons();
Note that I've used let rather than var for the loop variable - this is necessary (in your version too) for the event handler functions to "capture" the correct value of the loop variable. See here for a very thorough explanation of this.

Compare value within nested object

So I've been trying to find a solution to this for a little while with no luck.
const nameTest = 'testName';
const test = {
RANDOM_ONE: {
NAME: 'testName',
SOMETHING: {...}
},
RANDOM_TWO: {
NAME: 'Name',
SOMETHING: {...}
}
}
Is there any simple, easy way where I can compare the nameTest and the NAME key without knowing what the RANDOM_X is in order to access NAME?
You can use Object.keys() to get the array of all the keys. Then loop through the array to check the property:
const nameTest = 'testName';
const test = {
RANDOM_ONE: {
NAME: 'testName',
SOMETHING: {}
},
RANDOM_TWO: {
NAME: 'Name',
SOMETHING: {}
}
}
let testKeys = Object.keys(test);
testKeys.forEach(function(k){
console.log(test[k].NAME == nameTest);
});
You can use a for ... in loop:
for (let key in test) {
if (test[key].NAME === nameTest) {
// do something
}
}
I hope we know that 2 levels down into test is your object. You could write a function, to compare the name key.
function compare(obj, text){
for(let x in obj){
if(obj.x.name == text) return true;
else ;
}
}
Then call the function with your object and the string.
let a = compare(test, nameTest);
Note: this would compare the object to only ascertain if it contains the nameTest string.
var obj= test.filter(el){
if(el.NAME==nameTest)
{
return el;
}
}
var x= obj!=null?true:false;
You could use find.
The find method executes the callback function once for each index of
the array until it finds one where callback returns a true value. If
such an element is found, find immediately returns the value of that
element. Otherwise, find returns undefined.
So it is more memory efficient, than looping over the whole object with forEach, because find returns immediately if the callback function finds the value. Breaking the loop of forEach is impossible. In the documentation:
There is no way to stop or break a forEach() loop other than by
throwing an exception. If you need such behavior, the forEach() method
is the wrong tool.
1. If you want to get the whole object
var nameTest = 'testName';
var test = {
RANDOM_ONE: {
NAME: 'testName',
SOMETHING: {}
},
RANDOM_TWO: {
NAME: 'Name',
SOMETHING: {}
}
};
function getObjectByNameProperty(object, property) {
var objectKey = Object.keys(object)
.find(key => object[key].NAME === property);
return object[objectKey];
}
var object = getObjectByNameProperty(test, nameTest);
console.log(object);
2. If you just want to test if the object has the given name value
var nameTest = 'testName';
var test = {
RANDOM_ONE: {
NAME: 'testName',
SOMETHING: {}
},
RANDOM_TWO: {
NAME: 'Name',
SOMETHING: {}
}
};
function doesObjectHaveGivenName(object, nameValue) {
var objectKey = Object.keys(object)
.find(key => object[key].NAME === nameValue);
return objectKey ? true : false;
}
console.log( doesObjectHaveGivenName(test, nameTest) );

Convert to lower case and upper case , inside class with method using Javascript

Create a Str class with methods to:
Add lower method to convert a string to lower case.
Str.lower('EAT') // eat
Add upper method to convert a string to upper case.
Str.upper('today') // TODAY
I try with code below , but did not work
class Str {
constructor(lower,upper) {
this.lower = lower.toLoweCase();
this.upper = upper.toUpperCase();
}
}
Str.lower('HALO');
It is working
class Str {
constructor(lower,upper) {
this.lower = lower.toLowerCase();
this.upper = upper.toUpperCase();
}
}
let x = new Str('HALO','what');
x.lower; //halo
Your code this.lower = lower.toLowerCase(); is not creating a function. It is simply declaring a variable that holds the value of lower.toLowerCase(). Instead you should try the following
class Str {
constructor(lower,upper) {
this.lowerName = lower.toLowerCase();
this.upperName = upper.toUpperCase();
}
lower(input) {
return input.toLowerCase();
}
}
let y = Str.prototype.lower('WHAT'); //what
Unless you're creating an instance of Str, else invoking the function lower like above because the function sits inside prototype of class/object. You can picture it as function borrowing from Str class
Another way you can try as below:
class Str {
constructor(lower = "",upper="") {
this.lowerName = lower.toLowerCase();
this.upperName = upper.toUpperCase();
}
lower(input) {
return input.toLowerCase();
}
}
let strInstance = new Str();
console.log(strInstance.lower('WHY'));
Now the above code lets you create an instance of Str and invoke the function

new Object with prototype function vs regular function which returns an object

The basic idea is to check if it starts with an underscore and if there is split the string and return whatever comes after the underscore. This function will be run many times, but for different strings, it is unlikely i will need to retrieve the information more than once for each stirng.
A simple function which will return an object with the data I need:
var parseElementName = function(i) {
var sliced = [i.slice(0, 1), i.slice(1, i.length)];
var obj = {
isClass: null,
name: ''
}
if(sliced[0] === '_') {
obj.name = sliced[1];
obj.isClass = true;
} else {
obj.name = i;
obj.isClass = false;
}
return obj
}
Called with parseElementName(i);
Object with prototyped function
var parsedElement = function(i) {
this.className =
this.isClass = null;
if(this.setElementName(i))
return true
}
parsedElement.prototype.setElementName = function(i) {
var sliced = [i.slice(0, 1), i.slice(1, i.length)];
if(sliced[0] === '_') {
this.className = sliced[1];
this.isClass = true
} else {
this.className = i;
this.isClass = false
}
}
Called with var parsed_element = new parsedElement();
then parsed_element.className or parsedElement.isClass
Which approach is recommended?
I like the object prototype approach best, but I have a few notes about your code:
Use semicolons at the end of each line
Class names should be capitalized. So it should be ParsedElement
I wouldn't call it className, because it is confusing when it is not a class, I would rename it name
The two ways have different outcomes - that constructor+prototype approach will yield an instance which has a setElementName method. Will you ever need this to change the fields of an existing object? It's a simple parser function, so I would assume no. In that case, you should go with returning the object literal:
function parseElementName(i) {
var isClass = i.charAt(0) == '_';
return {
isClass: isClass,
name = isClass ? i.slice(1) : i
};
}
If you really need that method later, consider #MaxMeier's and #HMR's points.

Categories

Resources