I have following issue.
I have array of objects, and when I want to get one of the items and update data, it updates last data.
for example:
var arr = [];
for (var i = 0; i < 8; i++){
var c = new MyClass1(i);
arr.push (c)
}
and the MyClass1
(function () {
var score = 0;
function MyClass1(id){
this.id = id;
this.x = 100;
//some code. not important
}
var p = MyClass1.prototype;
p.updateScore = function (s){
score = s;
}
window.MyClass1 = MyClass1;
}());
and function which returns one of these classes
var getMyClassesById = function(/* int */ id){
var size = arr.length;
for (var i = 0; i<size; i++){
if (id == arr[i].id){
return arr [i];
}
}
}
Finally I'm calling function and want to update Score
getMyClassesById(1).updateScore (122);
it's updates last index item Score, and calls last item "updateScore" function... why?
but when i'm changing some other property its changes correctly for example "x". I can't understand is here something not right with prototypes?
Your variable score is not defined as a member of MyClass - it is only defined in the scope of your closure. Your code will work, but there will only be 1 "score" for all instances of MyClass.
If score is supposed to be part of MyClass then move it
function MyClass1(id){
this.id = id;
this.x = 100;
this.score = 0
//some code. not important
}
And update the method:
var p = MyClass1.prototype;
p.updateScore = function (s){
this.score = s;
}
(function () {
function MyClass1(id){
this.id = id;
this.x = 100;
this.score = 0;
//some code. not important
}
var p = MyClass1.prototype;
p.updateScore = function (s){
this.score = s;
}
window.MyClass1 = MyClass1;
}());
var arr = [];
for (var i = 0; i < 8; i++){
var c = new MyClass1(i);
arr.push (c)
}
var getMyClassesById = function(/* int */ id){
var size = arr.length;
for (var i = 0; i<size; i++){
if (id == arr[i].id){
return arr [i];
}
}
}
getMyClassesById(1).updateScore (122);
console.log(arr);
Related
I'm trying to create a board game and would like to instantiate the class Human based on a number of times provided by the user. Obviously I'm trying to assign a different ID per object and the following loop doesn't work in order to instantiate the number of players:
var question = prompt('how many players');
var numOfPlayers = parseInt(question);
class Human {
constructor (id) {
this.id = id;
this.health = 100;
this.hammer = false
this.knife = false;
this.sword = false;
this.baseballbat = false;
this.damage = 0;
this.location = {
x: Math.floor(Math.random() * 8),
y: Math.floor(Math.random() * 8)
}
}
moveTo(x, y){
this.location.x += x;
this.location.y += y;
}
}
var i;
for (i = 0; i < numOfPlayers; i++) {
const player = new Human(id = i);
}
Firstly, I hope I have understood what you are trying to achieve here. The scope of the "const player" is limited within the loop. If you want to be able to access it outside the loop you need to declare a list/array likewise.
Code may go like this for the same:
var players = [];
for(let i = 0; i < numOfPlayers; i++) {
players.push(new Human(i));
}
Note: If you don't want to use variable 'i' outside the loop you can declare it inside 'for' using 'let' keyword as can be seen in the code above.
class Human {
constructor (id){
this.id = id;
this.health = 100;
this.hammer = false
this.knife = false;
this.sword = false;
this.baseballbat = false;
this.damage = 0;
this.location = {
x:Math.floor(Math.random()*8),
y:Math.floor(Math.random()*8)
}
console.log(`Human created with id of ${id}`); //Remove this just to show you that your class is being instantiated for each 'player'
}
moveTo(x,y){
this.location.x += x;
this.location.y += y;
}
}
let numOfPlayers = prompt('How many players?');
const _init = () => {
if(parseInt(numOfPlayers) > 0) {
for (let i = 0; i < numOfPlayers; i++) {
new Human(i)
}
}
}
_init();
I want to create a function called totalPriceCheck that console.log's the total of all shoppingCart items together.
var shoppingCart = [];
function addToCart (name, price) {
var object = {};
object.name = name;
object.price = price;
shoppingCart.push(object);
}
function priceCheck(item){
for (var i = 0; i < shoppingCart.length; i += 1) {
if (item === shoppingCart[i].name) {
console.log(shoppingCart[i].price + " sheqalim");
} else {
console.log("the searched item is not in the shopping cart array!");
}
}
}
function totalPriceCheck(){
for (var i = 0; i < shoppingCart.length; i += 1) {
var totalPriceOf = shoppingCart[i].price;
var myTotal = 0;
for(var i = 0, len = totalPriceOf.length; i < len; i++) {
myTotal += totalPriceOf.price;
}
console.log(myTotal);
}
}
addToCart ('beer', 5);
totalPriceCheck();
I can't understand your question properly but I think you need output like this.
I am doing some changes in your code, please refer below code
output of below code is :- 15
if you add addToCart('beer', 5); than out put will be 20
var shoppingCart = [];
function addToCart(name, price) {
var object = {};
object.name = name;
object.price = price;
shoppingCart.push(object);
}
addToCart('beer', 5);
addToCart('beer', 5);
addToCart('beer', 5);
function totalPriceCheck() {
var myTotal = 0;
for (var i = 0; i < shoppingCart.length; i += 1) {
var totalPriceOf = shoppingCart[i].price;
myTotal += totalPriceOf;
}
console.log(myTotal);
}
totalPriceCheck();
You can use reduce to get the sum :
function totalPriceCheck(){
return shoppingCart.reduce(
(acc, elem)=>acc + elem.price,
0
);
}
guys i know it is dummy question but i tried alot and never reached .. i want to define the variables of Javascript file inside the scope of the class not to be overridden by any outside source .. here is my code
var pageSize = 5;
var startIndex = 0;
var endIndex = startIndex + pageSize;
var page = 1;
var textField;
var check = 0;
// i want all of the above variables to be defined inside the scope of the class not outside
function bindContext(fn, context) {
return function() {
fn.apply(context, arguments);
}
}
function GridLibraryDep(data) {
this.data = data;
this.columns = $.map(this.data[0], function(item, key) {
return key;
});
document.getElementById("from").innerHTML = 1;
document.getElementById("to").innerHTML = pageSize;
document.getElementById("total").innerHTML = data.length;
$("#first").click(bindContext(this.first, this));
$("#last").click(bindContext(this.last, this));
}
GridLibraryDep.prototype = {
first : function() {
var size = this.data.length;
page = 1;
// document.getElementById("lbl").innerHTML = page;
endIndex = page * pageSize;
startIndex = endIndex - pageSize;
this.deleteTable();
document.getElementById("from").innerHTML = 1;
document.getElementById("to").innerHTML = endIndex;
document.getElementById("total").innerHTML = size;
this.display();
},
last : function() {
var size = this.data.length;
endIndex = size;
startIndex = Math.floor(size / pageSize) * pageSize;
page = Math.ceil(size / pageSize);
this.deleteTable();
// document.getElementById("lbl").innerHTML = page;
document.getElementById("from").innerHTML = startIndex + 1;
document.getElementById("to").innerHTML = endIndex;
document.getElementById("total").innerHTML = size;
this.display();
}};
This is a common way to create a prototype Class - https://jsfiddle.net/aaronfranco/fysbbdp7/10/
var MyClass = MyClass || {};
(function () {
"use strict";
//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
MyClass = function () {
this.created = true;
};
//============================================================
// Member Functions & Variables
//------------------------------------------------------------
MyClass.prototype = {
pageSize:5,
startIndex:0,
endIndex:0,
page:1,
textField:null,
check:0,
init: function(){
this.endIndex = this.startIndex + this.pageSize;
},
first : function() {
// function here
console.log(this.endIndex);
},
last : function() {
// function here
//alert(this.pageIndex);
console.log(this.pageSize)
},
iterater: function(int) {
console.log(this.pageSize);
this.pageSize += int;
}
}
})();
Here is the example usage available in the JSFiddle link above:
var newClass = new MyClass();
newClass.init();
newClass.first();
for(var i=0; i<10; i++){
newClass.iterater(i);
newClass.last();
}
Using this "namespaced" technique, you can instantiate this class using
var newClass = new MyClass();
newClass.init();
You could then create protected variables in the class by making them private. There is a good article about some potential ways to create protected variables here.
http://philipwalton.com/articles/implementing-private-and-protected-members-in-javascript/
I am getting an error saying Arc is not a constructor. I have checked my code and can't understand why.
/*
Exception: Arc is not a constructor
RouteFinder/this.getPairs#Scratchpad/8:72:6
#Scratchpad/8:5:3
*/
The other answers for this error suggest that this because Arc has previously been defined, but I cant find anywhere that it is. This is a big chunk of code, so scroll down for the error - it is commented where it is
var lats = [ 51.445371, 51.45526, 51.426765, 51.441304 ]
var lons = [ -0.077581, -0.113248, -0.13091, -0.060596 ]
var finder = new RouteFinder(lats, lons);
finder.getPairs();
var nodeList = ''
for(var count = 1; count < lats.length; count++) {
nodeList += count;
}
finder.permutation("", nodeList);
finder.removeDuplicateRoutes();
var shortestRoute = finder.getShortestRoute();
var finalRouteOrder = [];
shortestRoute.nodeList.forEach(function(node) {
finalRouteOrder.push(+node);
});
alert(finalRouteOrder);
var Route = function() {
this.totalWeight = 0;
this.nodeList = [];
};
var Node = function() {
this.lat = 0;
this.lon = 0;
this.number = 0;
};
var Arc = function() {
this.startNode = new Node();
this.endNode = new Node();
this.weight = 0;
};
function reverseString(initialString) {
var reversed = '';
for(var count = initialString.length -1; count > -1; count--) {
reversed += initialString.charAt(count);
}
return reversed;
}
function calcDistance(lat1, lng1, lat2, lng2) {
var earthRadius = 6371;
var dLat = (lat2 - lat1)/180*Math.PI;
var dLng = (lng2 - lng1)/180*Math.PI;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1/180*Math.PI) * Math.cos(lat2/180*Math.PI) * Math.sin(dLng/2) * Math.sin(dLng/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var dist = earthRadius * c;
return dist;
}
function RouteFinder(lats, lons) {
this.latArray = lats;
this.lonArray = lons;
this.orders = [];
this.arcArray = [];
this.routes = [];
this.shortestRoute;
this.numOfPoints = lats.length - 1;
this.shortestRouteLength = -1;
this.getPairs = function() {
var timesLooped = 0;
for(var count1 = 0; count1 < this.numOfPoints; count1++) {
for(var count2 = 0; count2 < (this.numOfPoints - count1); count2++) {
//I get an error here for new Arc()
this.arcArray.push(new Arc());
this.arcArray[timesLooped].startNode = {
number: count1,
};
this.arcArray[timesLooped].endNode = {
number: this.numOfPoints - count2,
};
this.arcArray[timesLooped].weight = calcDistance(this.latArray[count1], this.lonArray[count1], this.latArray[this.numOfPoints - count2], this.lonArray[this.numOfPoints - count2]);
timesLooped++;
}
}
};
this.permutation = function(prefix, str) {
var n = str.length;
if(n === 0) this.orders.push('0' + prefix + '0');
else {
for(var i = 0; i <n; i++) {
this.permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i + 1, n));
}
}
};
this.removeDuplicateRoutes = function() {
var numberOfPermutations = this.orders.length -1;
var temp;
var size;
var toRemove = [];
for(var count1 = 0; count1 < numberOfPermutations; count1++) {
for(var count2 = 0; count2 < (numberOfPermutations - count1); count2++) {
if(this.orders[count1] == reverseString(this.orders[numberOfPermutations - count2])) {
toRemove.push(count1);
}
}
}
size = toRemove.length;
for(var count3 = 0; count3 < size; count3++) {
temp = toRemove[size - 1- count3];
var index = this.orders.indexOf(temp);
if(index > -1) {
temp.splice(index, 1);
}
}
};
this.getShortestRoute = function() {
var routesMade = 0;
for(var routeNumber = 0; routeNumber < (this.orders.length -1); routeNumber++) {
this.routes.push(new Route());
this.routes[routesMade].totalWeight = 0;
for(var count1 = 0; count1 < this.orders[routeNumber].length; count1++) {
this.routes[routesMade].nodeList.push(+this.orders[routeNumber].charAt(count1));
}
for(var count2 = 1; count2 < this.orders[routeNumber].length; count2++) {
for(var count3 = 0; count3 < this.arcArray.length; count3++) {
if(this.routes[routesMade].nodeList[count2 - 1] === this.arcArray[count3].startNode.number) {
if(this.routes[routesMade].nodeList[count2] === this.arcArray[count3].endNode.number) {
this.routes[routesMade].totalWeight += this.arcArray[count3].weight;
}
} else if (this.routes[routesMade].nodeList[count2 - 1] === this.arcArray[count3].endNode.number) {
if(this.routes[routesMade].nodeList[count2] === this.arcArray[count3].startNode.number) {
this.routes[routesMade].totalWeight += this.arcArray[count3].weight;
}
}
}
}
if(!this.shortestRoute) {
this.shortestRoute = this.routes[routesMade];
} else if(this.routes[routesMade].totalWeight < this.shortestRoute.totalWeight) {
this.shortestRoute = this.routes[routesMade];
}
routesMade++;
}
return this.shortestRoute;
};
}
I'm tearing my hair out trying to work out the problem. Help is greatly appreciated, thanks!
This
var finder = new RouteFinder(lats, lons);
gets executed before Arc variable gets its value (function). Thus at the moment of RouteFinder call that Arc variable is undefined and cannot be used as a constructor.
Update: it is about finder.getPairs(); actually where you try to call that new Arc();
You need to have Route, Node, and Arc like this:
function Route() {
this.totalWeight = 0;
this.nodeList = [];
}
function Node() {
this.lat = 0;
this.lon = 0;
this.number = 0;
}
function Arc() {
this.startNode = new Node();
this.endNode = new Node();
this.weight = 0;
}
The issue is that Arc is not yet defined. Either move your function expression assignment (var Arc = function ...) to the top of your script or convert them to function definition statements like this
function Arc() {
this.startNode = new Node();
this.endNode = new Node();
this.weight = 0;
}
Statements are hoisted and their order does not matter, but assignment to var happens in the order they appear in the file (the declaration is hoisted, but the assignment isn't).
Same goes for your Route and Node functions.
Read more about var hoisting on MDN.
here is my code :
var BoxUtility = function() {
var boxList = Array.prototype.pop.apply(arguments);
};
Object.defineProperties(BoxUtility, {
totalArea: {
value: function(){
var x = 0;
for(var i = 0, len = boxList.length; i <= len - 1; i++){
x = x + boxList[i].area;
};
return x;
}
}
});
I'm trying to achieve this syntax for my Code :
var boxArray = [box01, box02, box03];
box are objects, box01.area => boxes have area property
var newElement = new BoxUtility(boxArray);
alert(newElement.totalArea);
I WANT TO SEE THE RESULT AS I EXPECT but I think boxList is in another scope
How can I reach it in defineProperties
You have to assign the value to a property of this in your constructor.
var BoxUtility = function() {
// this.boxList
this.boxList = Array.prototype.pop.apply(arguments);
};
// instance methods go on the prototype of the constructor
Object.defineProperties(BoxUtility.prototype, {
totalArea: {
// use get, instead of value, to execute this function when
// we access the property.
get: function(){
var x = 0;
// this.boxList
for(var i = 0, len = this.boxList.length; i <= len - 1; i++){
x = x + this.boxList[i].area;
};
return x;
}
}
});
var boxUtil = new BoxUtility([{area:123}, {area:456}]);
console.log(boxUtil.totalArea); // 579
Variable scope is always at the function level. So you declared a local variable that is only usable inside your constructor function. But every time you call the constructor function you get a new object (this). You add properties to this in order to have those properties accessible in your instance methods on the prototype.
this works
var BoxUtility = function() {
this.boxList = Array.prototype.pop.apply(arguments);
Object.defineProperties(this, {
totalArea: {
get: function(){
var x = 0;
for(var i = 0, len = this.boxList.length; i <= len - 1; i++){
x = x + this.boxList[i].area;
};
return x;
}
}
});};
var y = new BoxUtility(boxArray);
alert(y.totalArea)
This is simple way to pass array as argument in constructer and declare function prototype for public access.
function BoxUtility(boxArray) {
this.boxArray = boxArray;
this.len = boxArray.length;
}
Color.prototype.getAverage = function () {
var sum = 0;
for(let i = 0;i<this.len;i++){
sum+=this.boxArray[i];
}
return parseInt(sum);
};
var red = new BoxUtility(boxArray);
alert(red.getAverage());