How to push all objects in class into one array javascript? - javascript

I'm trying to make language learn app and i have a problem. I have class "Word"
class Word {
constructor(englishWord, polishWord){
this.englishWord = englishWord
this.polishWord = polishWord
this.displayTranslation = () =>{
console.log(`${englishWord} = ${polishWord}`)
}
}
}
and lots of objects like
const intimate = new Word('intimate', 'intymny/prywatny')
const insurance = new Word('insurance', 'ubezpieczenie')
and I honestly don't have idea how to push all objects into one array. Can I use 'foreach' on every class object? Or is there a better solution for this?

You have to declare a global array where all instances will be pushed to
const instances = [];
class Word {
constructor(englishWord, polishWord){
this.englishWord = englishWord;
this.polishWord = polishWord;
this.displayTranslation = () =>{
console.log(`${englishWord} = ${polishWord}`);
};
instances.push(this);
}
static GetWords() {
instances.forEach( x => {
x.displayTranslation();
});
}
}
new Word('intimate', 'intymny/prywatny');
new Word('insurance', 'ubezpieczenie');
Word.GetWords();

Let's build up your problem in natural language before we write some code:
A Word has its nativ and translation. A Word is stored in a Dictionary. You can add translations to a Dictionary and so on..
For that the array would be hide in a Dictionary like
class Dictionary {
constructor() {
this.words = []
}
addTranslation(word) {
this.words.push(word)
}
// more ..
}
Code Snippet
class Word {
constructor(englishWord, polishWord) {
this.englishWord = englishWord
this.polishWord = polishWord
this.displayTranslation = () => {
console.log(`${englishWord} = ${polishWord}`)
}
}
}
class Dictionary {
constructor() {
this.words = []
}
addTranslation(word) {
this.words.push(word)
}
print() {
for (let i = 0; i < this.words.length; i++) {
this.words[i].displayTranslation()
}
}
}
const dictionary = new Dictionary()
const intimate = new Word('intimate', 'intymny/prywatny')
const insurance = new Word('insurance', 'ubezpieczenie')
dictionary.addTranslation(intimate)
dictionary.addTranslation(insurance)
dictionary.print()
Improvement
I suggest to use a Map instead of an Array. If the Dictionary will be extended by methods for finding words than you have to find the words in an Array by your self..
class Word {
constructor(englishWord, polishWord) {
this.englishWord = englishWord
this.polishWord = polishWord
this.displayTranslation = () => {
console.log(`${englishWord} = ${polishWord}`)
}
}
}
class Dictionary {
constructor() {
this.words = {}
}
addTranslation(word) {
this.words[word.englishWord] = word.polishWord
}
getTranslation(english) {
return this.words[english]
}
print() {
for (let i = 0; i < this.words.length; i++) {
this.words[i].displayTranslation()
}
}
}
const dictionary = new Dictionary()
const intimate = new Word('intimate', 'intymny/prywatny')
dictionary.addTranslation(intimate)
console.log(dictionary.getTranslation('intimate'))

You can push class objects into an Array without any issue:
// using your class declared above
const intimate = new Word('intimate', 'intymny/prywatny')
var array = [];
array.push(intimate);
But depending on your needs, you could put something like this directly into the constructor and have it collect all of the items it's constructed for you:
const instances = [];
class Word {
constructor(englishWord, polishWord){
this.englishWord = englishWord
this.polishWord = polishWord
this.displayTranslation = () =>{
console.log(`${englishWord} = ${polishWord}`)
}
Word.addInstance(this);
}
static addInstance(item){
instances.push(item);
}
static getInstances(){
return instances;
}
static clearInstances(){
instances.length = 0;
}
}
With this every time you construct an instance it's added to the external array. If you need to get everything from the array you can call Word.getInstances() or Word.clearInstances() if you want to empty it.

Related

JavasScript Show first two images, and then 1 random images from an array using a class method

I have all of the components for this project with the exception of a class method to show the first two images in the array (the Pokeball, and the default eevee) then randomly choose from an array one more image(eevee evolutions) and then stop.
Please be patient I am very new to this.
class Pokemon {
constructor() {
this.listOfCharmander = [
"./images/pokeball.png",
"./images/charmander/charmander0.png",
"./images/charmander/charmander1.png",
"./images/charmander/charmander2.png",
];
this.index = 0;
this.pokemon = document.createElement("img");
}
handleClick = () => {
if (this.index < 3) {
++this.index;
this.pokemon.src = this.listOfCharmander[this.index];
}
};
buildPokemon = () => {
this.pokemon.src = this.listOfCharmander[0];
this.pokemon.classList.add("pokemon");
this.pokemon.addEventListener("click", this.handleClick);
main.appendChild(this.pokemon);
};
}
const pokemon = new Pokemon();
const pokemon1 = new Pokemon();
pokemon.buildPokemon();
pokemon1.buildPokemon();
class Eevee {
constructor() {
this.eeveeEvolutions = [
"/images/pokeball.png",
"images/eevee/eevee0.png",
"images/eevee/eevee1.png",
"images/eevee/eevee2.png",
"images/eevee/eevee3.png",
"images/eevee/eevee4.png",
"images/eevee/eevee5.png",
"images/eevee/eevee6.png",
"images/eevee/eevee7.png",
"images/eevee/eevee8.png",
];
this.index = 0;
this.eevee = document.createElement("img");
}
handleClick = () => {
if (this.index < 9) {
++this.index;
this.eevee.src = this.eeveeEvolutions[this.index];
}
};
buildEevee = () => {
this.eevee.src = this.eeveeEvolutions[0];
this.eevee.classList.add("eevee");
this.eevee.addEventListener("click", this.handleClick);
main.appendChild(this.eevee);
};
}
const eevee = new Eevee();
const eevee1 = new Eevee();
eevee.buildEevee();
eevee1.buildEevee();
...
I apologize if my question isnt exactly clear. I need to add to my handClick method. A way display the first image (the Pokeball) and then the 2nd image (default eevee) And then randomly choose (including having it stay the same there could be no evolution at all) one more evolution from the remaining array.
if you always need first two images in your array then you can add extra attribute to your Eevee class to store those images path, and for random image you can add this code to your handleClick()
handleClick = () => {
this.index=Math.floor(Math.random(2,9)*10)
this.eevee.src = this.eeveeEvolutions[this.index];
};

i'm trying to create a route that returns the sum of all the values of a params in a collection

i really don't know what I'm doing wrong... it returns an array with the number of rows in the collection but all null.
i followed the documentation perfectly but i'm just extremely confused
basically i have a collection in my database called mytest, and i'm trying to add the valuses in each document (token) to return when i call the route /mytest-sum
module.exports = {
/**
* Retrieve records.
*
* #return {Array}
*/
async Sum(ctx) {
let entities;
if (ctx.query._q) {
entities = await strapi.services.mytest.search(ctx.query);
} else {
entities = await strapi.services.mytest.find(ctx.query);
}
//return entities.map(entity => sanitizeEntity(entity, { model: strapi.models.mytest}));
entities = entities.map(entity => (entity, { model: strapi.models.mytest }));
entities = entities.map(entry => {
entry = Object.assign(entry, {
sumField: entry.token
});
});
return entities;
},
};``
module.exports = {
async Add(ctx) {
let add = 0;
let fruits = []
// get data from database
let entities;
if (ctx.query._q) {
entities = await strapi.services.mytest.search(ctx.query);
} else {
entities = await strapi.services.mytest.find(ctx.query);
}
//get specific data-field from data and map it to an array
fruits = entities.map(entity => sanitizeEntity(entity, { model: strapi.models.mytest }).token);
// add array values in for loop
for (let i = 0; i < fruits.length; i++) {
add += fruits[i];
}
//return sum as a number
return add;
}};

How to write a function that pushes an object to an array of objects?

I am trying to create a function that takes an object as parameter and pushes it into an array of objects.
const listOfProjects = [];
function Project(title) {
this.title = title;
this.tasks = [];
}
Project.prototype.addProjectToList = function (projectObj) {
listOfProjects.push(projectObj);
}
function createProject(projectName) {
const projectObject = new Project(projectName);
projectObject.addProjectToList(projectName);
}
createProject('Workout');
createProject('Biology');
createProject('JavaScript')
I don't know why this returns an array of strings!
You need push this reference for save the object context, at same time you pass as argument the projectName, not the object itself, if you have the this reference, don't pass it like arg.
const listOfProjects = [];
function Project(title) {
this.title = title;
this.tasks = [];
}
Project.prototype.addProjectToList = function () {
listOfProjects.push(this);
}
function createProject(projectName) {
const projectObject = new Project(projectName);
projectObject.addProjectToList();
}
createProject('Workout');
createProject('Biology');
createProject('JavaScript');
console.log(listOfProjects);
Because you call addProjectToList with the name instead of the created object.
Change
projectObject.addProjectToList(projectName);
to
projectObject.addProjectToList(projectObject);
const listOfProjects = [];
function Project(title) {
this.title = title;
this.tasks = [];
}
Project.prototype.addProjectToList = function (projectObj) {
listOfProjects.push(projectObj);
}
function createProject(projectName) {
const projectObject = new Project(projectName);
projectObject.addProjectToList(projectObject);
}
createProject('Workout');
createProject('Biology');
createProject('JavaScript')
console.log(listOfProjects);
You were pushing the name into the array instead of the newly created object. The confusion probably stemmed from the object having the same name as the instance.
const listOfProjects = [];
function Project(title) {
this.title = title;
this.tasks = [];
}
Project.prototype.addProjectToList = function (projectObj) {
listOfProjects.push(projectObj);
}
function createProject(projectName) {
projectObject = new Project(projectName);
projectObject.addProjectToList(projectObject);
}
let projectObject
createProject('Workout');
createProject('Biology');
createProject('JavaScript')
console.log(projectObject)
console.log(listOfProjects)

Function to count lists of objects

Hey guys I am trying to build a function that counts the number of employees in each store. As you can see I have a class for stores, and a class for employees down below.
class Stores {
constructor(place, employees) {
this.place = place;
this.employees = employees;
}
}
class Employees {
constructor(name) {
this.name = name;
this._EmployeeID = Employees.counter; //ID for the employee
}
get EmployeeID() {
return this._EmployeeID
}
static get counter() {
Employees._counter = (Employees._counter || 0) + 1;
return Employees._counter
}
}
Here I have listed some employees and stored them into lists
//employees
const employee1 = new Employees("Torben")
const employee2 = new Employees("Mike")
const employee3 = new Employees("Rikke")
const employee4 = new Employees("Walid")
const employee5 = new Employees("Jens")
I have tried to build this function that loops over the objects, to count them, however for some reason I am not getting the correct result.
const copenhagenstore = new Stores("Copenhagenstore", {employee1, employee2, employee5})
function countemployees(store) {
var length = 0;
for(var key in store) {
console.log(key)
if(store.hasOwnProperty(key) ) {
++length;
}
}
return length;
};
console.log("the number of employees are: " + countemployees(copenhagenstore))
Below is my output, and as you can see, there should be 3 employees instead of two. I am pretty sure my function needs a bit of rework to account for this, and I was hoping that you guys could help me with that.
//OUTPUT
the number of employees are: 2
Stores {
place: 'Copenhagenstore',
employees: {
employee1: Employees { name: 'Torben', _EmployeeID: 1 },
employee2: Employees { name: 'Mike', _EmployeeID: 2 },
employee5: Employees { name: 'Jens', _EmployeeID: 5 }
}
}

Is using Eval a good idea?

I'd come to a situation where I had to get the object value dynamically from an array having object keys coming from an api. I came to this approach by using eval.
class App extends React.Component {
constructor() {
super();
this.state = {
title: 'Developers',
descp: 'They are just amazing! JK',
names: ['title', 'descp']
}
}
getVal(objKey) {
let { title, descp } = this.state;
return eval(objKey);
}
render() {
let {names} = this.state;
return (
<div>
<h2>{this.getVal(names[0])}</h2>
<div>{this.getVal(names[1])}</div>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
The above code works correctly.
Another approach I found later:
render() {
let {names} = this.state;
return (
<div>
<h2>{this.state[names[0]]}</h2>
<div>{this.state[names[1]]}</div>
</div>
)
}
Outputs the same result. But my question is that if I use eval with the following case, is it a good approach to do so?
Eval should be avoided as it can be very dangerous. You can safely replace your eval call with accessing property via bracket notation.
getVal(objKey) {
if(this.state.hasOwnProperty(objKey)){
return this.state[objKey];
} else {
// handle missing property
}
}
Eval is generally avoided as it allows the client to insert and evaluate their own expressions in your code.
That being said, JavaScript being a client side language already allows full access to the user, so there isn't really a good reason not to use it.
As long as the user can only mess with their own session, i wouldn't worry. Security should be handled server side anyway so: Beware but don't simply ignore Eval.
EDIT 1 - Defending Eval
The comments pointed out some issues, mainly Performance/Optimization impact, which this answer explains in depth. Basically, since it's Just-In-Time compiling anyway, you don't really lose that much in terms of performance.
As for an example on a use case, here is a template example i whipped up, which also uses the controversial with statement:
var Template = /** #class */ (function () {
function Template(html) {
this.html = html;
}
Template.prototype.apply = function (params, returnDOMObject) {
if (params === void 0) { params = {}; }
if (returnDOMObject === void 0) { returnDOMObject = false; }
with (params) {
var html = eval('`' + this.html.replace(Template.regexes.encapsulated, function (n) {
return n
.replace(Template.regexes.start, '${')
.replace(Template.regexes.end, '}');
}) + '`');
}
if (returnDOMObject) {
return document.createRange().createContextualFragment(html);
}
return html;
};
Template.regexes = {
encapsulated: new RegExp('{{.*?}}', 'igm'),
start: new RegExp('\{{2,}', 'igm'),
end: new RegExp('\}{2,}', 'igm')
};
return Template;
}());
//TEST
var persons = [
{ name: "Peter", age: 25 },
{ name: "Ole", age: 55 },
];
var templates = [];
var container = document.body.appendChild(document.createElement("div"));
var leftBox = container.appendChild(document.createElement("div"));
var rightBox = container.appendChild(document.createElement("div"));
leftBox.style.width = rightBox.style.width = "50%";
leftBox.style.height = rightBox.style.height = "500px";
leftBox.style.cssFloat = rightBox.style.cssFloat = "left";
var leftList = leftBox.appendChild(document.createElement("select"));
leftBox.appendChild(document.createElement("br"));
var leftText = leftBox.appendChild(document.createElement("textarea"));
leftText.style.width = "100%";
leftText.style.resize = "vertical";
var rightOutput = rightBox.appendChild(document.createElement("div"));
function updateLists() {
leftList.innerHTML = '';
for (var i = 0; i < templates.length; i++) {
var template = templates[i];
var option = document.createElement("option");
option.value = option.innerHTML = template.name;
leftList.appendChild(option);
}
}
var h1Template = new Template("<h1>{{name}}</h1>");
var h2Template = new Template("<h2>{{age}} is no age!</h2>");
var pTemplate = new Template("<p>{{name}} may be {{age}}, but is still going strong!</p>\n<p>(When he's {{age*2}} though...)</p>");
var personTemplate = new Template("<p>\n{{ h1Template.apply(params) }}\n{{ h2Template.apply(params) }}\n{{ pTemplate.apply(params) }}\n</p>");
templates.push({ name: "personTemplate", template: personTemplate });
templates.push({ name: "h1Template", template: h1Template });
templates.push({ name: "h2Template", template: h2Template });
templates.push({ name: "pTemplate", template: pTemplate });
function updateOutput() {
rightOutput.innerHTML = '';
for (var pi = 0; pi < persons.length; pi++) {
var person = persons[pi];
rightOutput.appendChild(personTemplate.apply(person, true));
}
}
function leftTextChange() {
templates.find(function (val) { return val.name === leftList.value; }).template.html = leftText.value;
updateOutput();
}
function leftListChange() {
leftText.value = templates.find(function (val) { return val.name === leftList.value; }).template.html;
}
updateLists();
leftList.onchange = leftList.onkeyup = leftListChange;
leftText.onchange = leftText.onkeyup = leftTextChange;
leftListChange();
updateOutput();
Here the users input text is being interpreted live, while the user is watching. No security concerns, since it's all client side.

Categories