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);
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?
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 have an array of objects. I want to remove multiple objects from that array.
I have used below code which is working absolutely fine, but I need to check with you guys if there is better way to do that or its fine.
I have done it with angularjs and js.
Orders is the main array on which operations are performed.
Order is array of selected items to remove from main array Orders
$scope.Order = {};
$scope.removeOrders = function () {
angular.forEach($scope.Order, function (data) {
for (var i = $scope.Orders.length - 1; i >= 0; i--) {
if ($scope.Orders[i].Name == data.Name) {
$scope.Orders.splice(i, 1);
}
}
});
}
You can make it quite a bit shorter using filter:
$scope.removeOrders = function () {
$scope.Orders = $scope.Orders.filter(function(order){
return !$scope.Order.some(function(remove){
return remove.Name === order.Name;
});
}); // remove the order from $scope.Orders, if it's name is found in $scope.Order
};
Is it possible to create an array that will only allow objects of a certain to be stored in it? Is there a method that adds an element to the array I can override?
Yes you can, just override the push array of the array (let's say all you want to store are numbers than do the following:
var myArr = [];
myArr.push = function(){
for(var arg of arguments) {
if(arg.constructor == Number) Array.prototype.push.call(this, arg);
}
}
Simply change Number to whatever constructor you want to match. Also I would probably add and else statement or something, to throw an error if that's what you want.
UPDATE:
Using Object.observe (currently only available in chrome):
var myArr = [];
Array.observe(myArr, function(changes) {
for(var change of changes) {
if(change.type == "update") {
if(myArr[change.name].constructor !== Number) myArr.splice(change.name, 1);
} else if(change.type == 'splice') {
if(change.addedCount > 0) {
if(myArr[change.index].constructor !== Number) myArr.splice(change.index, 1);
}
}
}
});
Now in ES6 there are proxies which you should be able to do the following:
var myArr = new Proxy([], {
set(obj, prop, value) {
if(value.constructor !== Number) {
obj.splice(prop, 1);
}
//I belive thats it, there's probably more to it, yet because I don't use firefox or IE Technical preview I can't really tell you.
}
});
Not directly. But you can hide the array in a closure and only provide your custom API to access it:
var myArray = (function() {
var array = [];
return {
set: function(index, value) {
/* Check if value is allowed */
array[index] = value;
},
get: function(index) {
return array[index];
}
};
})();
Use it like
myArray.set(123, 'abc');
myArray.get(123); // 'abc' (assuming it was allowed)
I have an js, object which is something like this:
function test{
this.variable = {};
this.populate = function(){
// do some crap....
// and i populate the object like this
this.variable{xyz..} = new object();
}
this.outputThecrap(){
for (var key in data) {
if (data.hasOwnProperty(key)) {
if(data[key].idParent != '0'){
//do some stuff
}
}
}
}
this.addSomeOnBeginigQQ(){
// how do i do that!!!!Q_Q
this.variable{blabla...} = new blabla();
}
}
now after I populate the object like
var t = new test();
t.populate();
t.addSomeOnBegining();
t.outputThecrap();
I get the problem that the added properties wind up on the end of the loop ... and I need them to be on the top
Anyone has some idea how to solve this?
UPDATE:
The structure of the object is not open to change. i cant use the array as a container either, that s out of question.
If you want a stack, you will need to use an Array - a list with a defined order. Object properties have none in JavaScript, there is nothing like "associative arrays". Also, you should the prototype.
You can set properties of array just as you do with objects, but the property names need to be numerically (i.e. integers). You then loop over them with a for-loop. Array objects also have some extra methods, for example to add items in the beginning or the end (which I have used below):
function Test() {
this.data = []; // an array
}
Test.prototype.populate = function(){
// populate the array like this
this.data.push({…});
};
Test.prototype.outputThecrap = function(){
for (var i=0; i<this.data.length; i++) {
var item = this.data[i];
if (item /* has the right properties*/)
//do some stuff
}
};
Test.prototype.addSomeOnBeginning(){
this.data.unshift({…});
};
Then use it like this:
var t = new Test();
t.populate();
t.addSomeOnBeginning();
t.outputThecrap();
The "ordered key array" looks like this:
function Test() {
this.data = {}; // the object
this.order = []; // an array
}
Test.prototype.populate = function(){
this.data["something"] = {…}
this.order.push("something");
};
Test.prototype.addSomeOnBeginning(){
this.data["other"] = {…};
this.order.unshift("other");
};
Test.prototype.outputThecrap = function(){
for (var i=0; i<this.order.length; i++) {
var key = this.order[i],
item = this.data[key];
if (item && key /* fulfill your requirements */)
// do some stuff
}
};