I have an object with two arrays (_licky, _unlucky). and methods that randomly push names into one of the two arrays. But my code does not work for some reason... What is wrong with my code?
const luckGame = {
_lucky: [],
_unlucky: [],
pushGamer(name) {
return name;
},
getRandomNumber (random) {
return random = Math.floor(Math.random() * 2);
},
pushGamerIntoArray () {
return {
if (this.getRandomNumber() === 0 ) {
this._lucky.push(this.pushGamer());
} else {
this._unlucky.push(this.pushGamer());
}
};
},
};
this.pushGamer('John');
this.pushGamer('Nick');
this.pushGamer('Maria');
this.pushGamer('Sarah');
this.pushGamer('Ron');
this.pushGamer('Lisa');
console.log(luckGame._lucky);
console.log(luckGame._unlucky);
I fixed it. Now it works. thank you all!!
const luckGame = {
_lucky: [],
_unlucky: [],
getRandomNumber (random) {
return random = Math.floor(Math.random() * 2);
},
pushGamerIntoArray (name) {
if (this.getRandomNumber() === 0 ) {
return this._lucky.push(name);
} else {
return this._unlucky.push(name);
}
},
};
luckGame.pushGamerIntoArray('John');
console.log(luckGame._lucky);
console.log(luckGame._unlucky);
There were a few small errors on your part. I have rewritten it in a class variant. It works, but I would still improve a few things. You can test it a bit.
const luckyGame = class {
constructor() {
this._lucky = [],
this._unlucky = []
}
pushGamer(name) {
this.pushGamerIntoArray(name)
}
getRandomNumber (random)
{
return random = Math.floor(Math.random() * 2);
}
pushGamerIntoArray (newGamerName)
{
if (this.getRandomNumber() === 0 ) {
this._lucky.push(newGamerName)
} else {
this._unlucky.push(newGamerName)
}
}
getLuckies () {
return this._lucky
}
getUnluckies () {
return this._unlucky
}
}
let luckygame = new luckyGame()
luckygame.pushGamer('John');
luckygame.pushGamer('Nick');
luckygame.pushGamer('Maria');
luckygame.pushGamer('Sarah');
luckygame.pushGamer('Ron');
luckygame.pushGamer('Lisa');
luckygame.pushGamer('John');
console.log(luckygame.getLuckies());
console.log(luckygame.getUnluckies());
Related
I am using 2 different functions to do the same thing and I am trying to merge them into one, but I am unable to do so. I read such a thing can be achieved through Dynamic Event Handling. I have tried but I failed.
Below are the two functions I want to merge
updateProfValue(index, value) {
this.props.profValue(index, value);
}
updatePersonalVaue(index, value) {
this.props.persValue(index, value);
}
And I want them to use in this component dynamically.
{
abc.map((item, index) => { <
FCW
changeHandler = {
this.updatePersonalVaue
}
defaultOption = {
item.value
}
index = {
index
}
key = {
item.Cn
}
name = {
item.dN
}
required = {
item.r
}
/>);
})
}
{
xyz.map((item, index) => { <
FCW
changeHandler = {
this.updateProfVaue
}
defaultOption = {
item.value
}
index = {
index
}
key = {
item.Cn
}
name = {
item.dN
}
required = {
item.r
}
/>);
I am teaching myself coding, learning Java Script. I am working on a problem from a book where I need to make an iterator for a custom object, which acts like a Set.
When I want to access the array I have set up to hold the data in the next() method, I get the following error:
Uncaught TypeError: Cannot read property 'length' of undefined
at Object.next (testerBook.js:34)
at testerBook.js:83
Within the next() method, it has the array as undefined.
Code is as follows:
class Group {
constructor() {
this.values = [];
}
add(value) {
if (!this.values.includes(value)) {
this.values.push(value);
}
}
delete(value) {
if (this.values.includes(value)) {
this.values = this.values.filter(e => e !== value);
}
}
has(value) {
return this.values.includes(value);
}
[Symbol.iterator]() {
let count = 0;
let nvalues = this.values;
console.log('nvalues is ', nvalues);
return {
next() {
console.log('In next in iterator ', this.nvalues);
//try the ++ count afterwards
if (count === this.values.length - 1) {
return {
value: undefined,
done: true
};
} else {
count++;
return {
value: this.values[count - 1],
done: false
};
}
}
}
}
static from(newValues) {
let group = new Group();
for (let value of newValues) {
if (!group.has(value)) {
group.add(value);
}
}
return group;
}
}
let group = Group.from([1, 2, 3, 4, 3, 2, 1, 5]);
console.log(group.values);
for (let value of group) {
console.log(value);
}
I'm hoping it is something easy that I dont see. Any help would be appreciated!
this is not being passed into the next function. You can pass it in implicitly using an arrow function.
Also the iterator ends early, change if (count === this.values.length - 1) { to if (count === this.values.length) {
class Group {
constructor() {
this.values = [];
}
add(value) {
if (!this.values.includes(value)) {
this.values.push(value);
}
}
delete(value) {
if (this.values.includes(value)) {
this.values = this.values.filter(e => e !== value);
}
}
has(value) {
return this.values.includes(value);
}
[Symbol.iterator]() {
let count = 0;
let nvalues = this.values;
console.log('nvalues is ', nvalues);
return {
next: () => {
console.log('In next in iterator ', JSON.stringify(this,null,2));
//try the ++ count afterwards
if (count === this.values.length) {
return { value: undefined, done: true };
} else {
count++;
return { value: this.values[count - 1], done: false };
}
}
}
}
static from(newValues) {
let group = new Group();
for (let value of newValues) {
if (!group.has(value)) {
group.add(value);
}
}
return group;
}
}
let group = Group.from([1, 2, 3, 4, 3, 2, 1, 5]);
console.log(group.values);
for (let value of group) {
console.log(value);
}
this is not captured in traditional closures.
You can use the nvalues local variable, just like you do with count.
class Group {
constructor() {
this.values = [];
}
add(value) {
if (!this.values.includes(value)) {
this.values.push(value);
}
}
delete(value) {
if (this.values.includes(value)) {
this.values = this.values.filter(e => e !== value);
}
}
has(value) {
return this.values.includes(value);
}
[Symbol.iterator]() {
let count = 0;
let nvalues = this.values;
console.log('nvalues is ', nvalues);
return {
next() {
console.log('In next in iterator ', this.nvalues);
//try the ++ count afterwards
if (count === nvalues.length - 1) {
return {
value: undefined,
done: true
};
} else {
count++;
return {
value: nvalues[count - 1],
done: false
};
}
}
}
}
static from(newValues) {
let group = new Group();
for (let value of newValues) {
if (!group.has(value)) {
group.add(value);
}
}
return group;
}
}
let group = Group.from([1, 2, 3, 4, 3, 2, 1, 5]);
console.log(group.values);
for (let value of group) {
console.log(value);
}
I can get to limitfrom in the second case if I rename limitfrom to limitfrom2, but I don't understand how to get to the value without renaming the key. Maybe I'm doing the wrong thing about the destructuring itself.
create an object
const vedPlus = {
transferLegal: {
stageOne: {
limitfrom: 0,
limitUpTo: 60,
commission: 0
},
stageTwo: {
limitfrom2: 60,
limitUpTo2: 1000,
commission2: 29
},
}
then I do the destructuring in 4 steps.
const {transferLegal} = vedPlus
const {stageOne, stageTwo} = transferLegal
const {limitfrom, limitUpTo, commission} = stageOne
const {limitfrom2, limitUpTo2, commission2} = stageTwo
Create a function
function calc (i) {
if (i >= limitfrom && i <= limitUpTo) {
return i * commission
} else if (i >= limitfrom2 && i <= limitUpTo2) {
return i * commission2
} else {
console.log('error')
}
result
const price = 71
console.log(calc(price))
Is there a way to get to the value without renaming the key?
You can use the same property names for both inner objects, and then assign new unique names when destructuring to prevent conflicts, using const { prop: newName } = source syntax.
It may not produce the most readable code, but at least it can be done.
Demo:
const vedPlus = {
transferLegal: {
stageOne: { limitfrom: 0, limitUpTo: 60, commission: 0 },
stageTwo: { limitfrom: 60, limitUpTo: 1000, commission: 29 },
}
}
const { transferLegal } = vedPlus;
const { stageOne, stageTwo } = transferLegal;
const { limitfrom, limitUpTo, commission } = stageOne;
const { limitfrom: limitfrom2, limitUpTo: limitUpTo2, commission: commission2 } = stageTwo;
console.log(limitfrom, limitUpTo, commission);
console.log(limitfrom2, limitUpTo2, commission2);
Yes. But certainly not like this:
const {limitfrom, limitUpTo, commission} = stageOne;
const {limitfrom, limitUpTo, commission} = stageTwo;
Because you'd be re-declaring the same variables in the same scope. After these two lines, if you were to refer to the variable limitfrom, which one would you expect it to be and why?
If the keys have the same name, that's fine as long as they are unique within their context. In this case within their individual objects. You can use those objects to reference them:
const {stageOne, stageTwo} = transferLegal;
//...
if (i >= stageOne.limitfrom && i <= stageOne.limitUpTo) {
return i * stageOne.commission
} else if (i >= stageTwo.limitfrom && i <= stageTwo.limitUpTo) {
return i * stageTwo.commission
}
Basically, absolutely everything doesn't have to be destructured into its own variable with a single value. Objects exist for a reason, use them.
If you want to keep the data (vedPlus) as the same structure you can do the renaming while you are destructuring
const vedPlus = {
transferLegal: {
stageOne: {
limitfrom: 0,
limitUpTo: 60,
commission: 0
},
stageTwo: {
limitfrom: 60,
limitUpTo: 1000,
commission: 29
}
}
}
const {
transferLegal: {
stageOne: {
limitfrom,
limitUpTo,
commission
},
stageTwo: {
limitfrom: limitfrom2,
limitUpTo: limitUpTo2,
commission: commission2
}
}
} = vedPlus
function calc(i) {
if (i >= limitfrom && i <= limitUpTo) {
return i * commission
} else if (i >= limitfrom2 && i <= limitUpTo2) {
return i * commission2
} else {
console.log('error')
}
}
const price = 71
console.log(calc(price))
if the final goal is a simple calculation, then the use of the destructuring mechanism does not bring anything useful
const vedPlus =
{ transferLegal:
{ stageOne: { limitfrom: 0, limitUpTo: 60, commission: 0 }
, stageTwo: { limitfrom: 60, limitUpTo: 1000, commission: 29 }
} }
function calc(i)
{
let obj = vedPlus.transferLegal
for (let stage in obj)
{
if (obj[stage].limitfrom <= i && i <= obj[stage].limitUpTo)
return obj[stage].commission *i
}
throw `error: ${i} is out of range!`
}
console.log( '50 =>', calc(50) )
console.log( '500 =>', calc(500) )
console.log( '5000 =>', calc(5000) )
console.log(myDog) before and after myDog.eatTooManyTreats() prints two different values, 12 and 13. Can't really understand why that's happening, isn't objects passed by reference, which means they can't have two different states. Thanks for your attention.
const dogFactory = (_name, _breed, _weight) => {
return dogObj = {
_name,
_breed,
_weight,
get name () {
return this._name;
},
get breed () {
return this._breed;
},
get weight () {
return this._weight;
},
set name (value) {
return this._name = value;
},
set breed (value) {
return this._breed = value;
},
set weight (value) {
return this._weight = value;
},
bark() {
return console.log('ruff! ruff!');
},
eatTooManyTreats() {
return this._weight++;
}
}
}
const myDog = dogFactory('Dodo', 'Milk', 12);
console.log(myDog); // weight is 12
myDog.eatTooManyTreats();
console.log(myDog); // weight is 13
This code gives the expected result, but is there a more concise way to achieve the same result? This is simply a matter of curiosity though.
The goal is to have a map representing the total students in each school, as well as a map representing the total teachers in each school.
// Example data
const studentsMap = {
student123: {
teacher: 'teacher123'
},
student456: {
teacher: 'teacher123'
},
student789: {
teacher: 'badID'
},
student000: {}
};
const teachersMap = {
teacher123: {
school: 'school123'
},
teacher456: {
school: 'school123'
},
teacher789: {
school: 'school456'
}
};
const studentsTotalBySchool = Object.keys(studentsMap).reduce((totals, key) => {
const current = studentsMap[key];
if (!teachersMap[current.teacher] || !teachersMap[current.teacher].school) {
return totals;
}
totals[teachersMap[current.teacher].school] = (totals[teachersMap[current.teacher].school] || 0) + 1;
return totals;
}, {});
const teachersTotalBySchool = Object.keys(teachersMap).reduce((totals, key) => {
const current = teachersMap[key];
totals[current.school] = (totals[current.school] || 0) + 1;
return totals;
}, {});
Is there a way to write this more succinctly without sacrificing too much readability?
You can use Object.entries and destructuring like so:
const studentsTotalBySchool = Object.entries(studentsMap).reduce((totals, [key, { teacher }) => {
if (!teachersMap[teacher] || !teachersMap[teacher].school) return totals;
totals[teachersMap[teacher].school] = (totals[teachersMap[teacher].school] || 0) + 1;
return totals;
}, {});
const teachersTotalBySchool = Object.entries(teachersMap).reduce((totals, [key, { school }) => {
totals[school] = (totals[school] || 0) + 1;
return totals;
}, {});
this will get you the same results with much less code
let schools = {
school123: {
teacher123 : {
students: ["student123", "student456"]
},
teacher456 : {
students: ["student789"]
}
},
school456: {
teacher123 : {
students: ["student123", "student456"]
},
teacher456 : {
students: ["student789"]
}
}
};
function findTotal(school, totalOf){
let accumulated = 0;
switch(totalOf){
case "students":
for(let teachers of Object.keys(schools[school])){
accumulated += schools[school][teachers].students.length;
}
break;
case "teachers":
accumulated = Object.keys(schools[school]).length;
}
return accumulated;
}
console.log(findTotal("school123", "students"))
console.log(findTotal("school123", "teachers"))