How do you make an object that can kill/remove itself? e.g.
var bullet = [];
function bullet() {
this.removeSelf = () => {
this = false;
}
}
function setup() {
bullet[0] = new Bullet();
bullet[0].removeSelf();
}
setup();
Not sure if I understood your question correctly but if you mean to destroy the object and free the memory then you first need to remove all references to it and then garbage collector will automatically do the job for you.
You're storing a reference to the object in the array so you can do this:
bullet[0] = null
If the goal is to remove it from the parent array, you need to edit that array. So we can pass the parent into the instance and have the removeSelf look for its instance in the parent and splice it out.
I also renamed the constructor to Bullet.
var bullets = [];
function Bullet(parent) {
this.removeSelf = () => {
const index = parent.indexOf(this);
parent.splice(index, 1);
}
}
function setup() {
bullets[0] = new Bullet(bullets);
bullets[1] = new Bullet(bullets); // Add a second isntance to the array
bullets[0].removeSelf();
}
setup();
console.log(bullets.length) // Should be 1
Related
I'm trying to write a custom push function and only override it for a single instance. I'm trying to wire it up so every time I push to this array I can trigger my extra code. I don't want to override it for all Arrays or create a custom class if I don't have to.
First I had this:
let user_progress = {completed: [], inprogress: [] }
user_progress.completed.push = (item) => {
Array.prototype.push.call(user_progress.completed, item)
//do extra stuff
common.store_data(user_progress, RESOURCE_COLLECTION)
return undefined;
}
Then I tried this:
let Progress = function(){
this.completed = new Array()
this.inprogress = new Array()
}
let user_progress = new Progress()
user_progress.completed.push = (item) => {
Array.prototype.push.call(user_progress.completed, item)
common.store_data(user_progress, RESOURCE_COLLECTION)
return undefined;
}
user_progress.completed.push(item) works the first time you call it then it gets overwritten and becomes the standard Array.push. I assume it has something today with the Array.Prototype.push.call() and passing in user_progress.completed. What am i doing wrong? Both don't work and have the same issue. What is going on in the background here and is there an easy fix?
The following image represents an object with two ui controls that are stored as this.state.controls
Initially the statesValue values are set via data that is received prior to componentDidMount and all is good. However updates to the each of the controls statesValues are sent via an event , which is handled with the following function
const handleValueStateChange = event => {
let controls = Object.entries(this.state.controls);
for (let cont of controls) {
let states = cont[1].states;
if (states) {
let state = Object.entries(states);
for (let [stateId, contUuid] of state) {
if (contUuid === event.uuid) {
cont[1].statesValue[stateId] = event.value;
}
}
}
}
};
which updates the values happily, however bearing in mind the updated values that change are a subset of this.state.controls, I have no idea how to use this.setState to update that that has been changed.
thanks in advance for any pointers
Instead of using Object.entries try destructuring to keep the reference to the objects.
And have a look at lodash. There are some nice helper functions to iterate over objects like mapValues and mapKeys. So you can keep the object structure and just replace the certain part. Afterwards update the whole state-object with the new one.
const handleValueStateChange = event => {
let {controls} = this.state;
controls = _.mapValues(controls, (cont) => {
const states = cont[1].states;
if (states) {
_.mapValues(states, (contUuid,stateId) => {
if (contUuid === event.uuid) {
cont[1].statesValue[stateId] = event.value;
}
});
}
return cont;
});
this.setState({controls});
};
Code is not tested but it should work like this.
Problem is you're updating an object which you've changed from it's original structure (by using Object.entries). You can still iterate in the same way however you'll need to update an object that maintains the original structure. Try this:
Make a copy of the controls object. Update that object. Replace it in state.
const handleValueStateChange = event => {
// copy controls object
const { controls } = this.state;
let _controls = Object.entries(controls);
for (let cont of _controls) {
let states = cont[1].states;
if (states) {
let state = Object.entries(states);
for (let [stateId, contUuid] of state) {
if (contUuid === event.uuid) {
// update controls object
controls[cont[0]].statesValue[stateId] = event.value;
}
}
}
}
}
// replace object in state
this.setState({controls});
};
I am making a simple hmtl/js game. I'd like to have all the data of the Game in DataofGame. It is like tennis, it is simpler than tennis: there is only set and match. changeinSet is called on click.
But I think i have a problem with private variable so it doesn't work.
Uncaught TypeError: Cannot read property 'WordsoftheGame' of undefined
//Added
document.getElementById('playboutton').addEventListener('click', newGame);
function newGame() {
var DataofGame = new newGameData();
}
// New game
function newGameData() {
this.pointTeam1 = 0;
this.pointTeam2 = 0;
this.WordsoftheGame = ShuffleListe();
this.ASet = new aSet();
}
//How the set is manage ********************
function aSet() {
var oneWord = DataofGame.ListeMot;
// display the word and delete it from the list
document.getElementById('jouer').innerHTML = oneWord[0];
DataofGame.WordsoftheGame.shift();
this.turn = true;
this.score = 0;
}
function changeinSet() {
DataofGame.ASet.score += 1;
//This is the other team's turn:
DataofGame.ASet.turn = !DataofGame.ASet.turn;
};
//shuffle liste
ListOfWords = ['Artiste', 'Appeler', 'Cheval', 'Choisir', 'Ciel', 'Croire', 'Dormir'];
function ShuffleListe() {
data = shuffle(ListOfWords);
return data;
}
function newGameData(){
this.pointTeam1=0;
this.pointTeam2=0;
this.WordsoftheGame= ShuffleListe();
this.ASet=new aSet();
}
//How the set is manage ********************
function aSet(){
var oneWord=DataofGame.ListeMot;
// display the word and delete it from the list
document.getElementById('jouer').innerHTML=oneWord[0];
DataofGame.WordsoftheGame.shift(); // << DataofGame not assigned yet
this.turn=true;
this.score=0;
}
Here when you're accessing DataofGame, it's not yet assigned because you're inside the constructor when calling aSet().
What you want to achieve is not completely clear, but if it's adding an ASet method to your object, you could write something like this:
function newGameData(){
this.pointTeam1=0;
this.pointTeam2=0;
this.WordsoftheGame= ShuffleListe();
this.ASet = function() {
// your code
};
}
NB your coding style for names is a bit messy, you should use uppercases consistently. The usage is to start constructor names with uppercases, the rest in lower cases.
You can let the function return an object with the data or just set the object.
function newGameData(){
return {
pointTeam1 : 0,
pointTeam2 : 0,
WordsoftheGame : ShuffleListe(),
ASet : new aSet()
}
}
But I would recommend to search for how to work with objects in javascript. Maybe this helps:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
I'm not really sure why my code isn't running correctly.. what I'm trying to do is create a grocery list object that has a couple of functions to add and remove items..
I can instantiate the objects with new items but my functions don't seem to work for some reason.
If you could save me the few hairs left in my head and tell me where the issue is I would greatly appreciate it.
var groceryList = function(itemNames,quantity) {
if (Array.isArray(itemNames)) {
this.items = itemNames;
this.quantity = quantity
this.addItems = function(newItems){
if ( Array.isArray(newItems) ) {
this.items.concat(newItems);
} else {
console.log("Please enter the items in an array fashion!");
};
};
this.removeItem = function(name) {
var listSize = this.items.length;
for (var i = 0; i < listSize; i++) {
if (this.items[i] == name) {
this.items.splice(i,1);
break;
} else {
console.log("Please enter the items in an array fashion!")
};
};
};
} else {
console.log("Please enter the items in an array fashion!")
};
};
.concat() returns a new array so you have to assign the result back to your instance variable.
So this:
this.items.concat(newItems);
needs to be changed to this:
this.items = this.items.concat(newItems);
or, you could actually use this to append to the array directly:
this.items.push.apply(this.items, newItems);
Because .push() can take more than one argument.
Then, in your .removeItem() function, you need to remove the item you actually found by changing this:
this.items.splice(2,1);
to this:
this.items.splice(i,1);
I have a situation here.
Let's show an example:
function ScrewDriver(){
var data = ...;
this.driving = function(){
//Some Stuff Here
}
}
function Hammer(){
var data = ...;
this.stomp = function(){
//Some Stuff Here
}
}
function MultiTools(){
this.screwDriver = new ScrewDriver();
this.hammer = new Hammer();
}
Here is the base of our example.
Now I would like redirect the tools functions from the multiTools but dynamicaly.
Let's explain myself:
function Work(){
this.tools = new MultiTools();
this.tools.screw(); // I want to user directly the function of the proper object
this.tools.hammer.stomp(); // Not like this;
}
I was thinking of something like that:
function MultiTools(){
this.screwDriver = new ScrewDriver();
this.hammer = new Hammer();
for(var prop in this.screwDriver){
this[prop] = this.screwDriver[prop];
}
//Same for each object
}
But it's not working like I want because if I acces to the child object data in the child object function I'll get an error.
When im calling this.tools.screw(); I want in reality this.tools.screwDriver.screw();
In finally I just want a redirection.
Someone know how to do this?
Thanks in advance.
You can use .bind():
this[prop] = this.screwDriver[prop].bind(this.screwDriver);
That ensures that when the functions are called, they'll have the correct value of this.
You could write a general function for your MultiTools object:
function MultiTools() {
var multitool = this;
function promoteMethods(subobj) {
for (var prop in subobj)
if (typeof subobj[prop] == 'function')
multitool[prop] = subobj[prop].bind(subobj);
else
multitool[prop] = subobj[prop];
}
promoteMethods(this.hammer = new Hammer());
promoteMethods(this.screwDriver = new ScrewDriver());
// ...
}