New to JS here, so I apologize if I'm missing something obvious. Trying to build a random number generator (it works in a nested manner, so something like a list of tuples of random number), but I get a OOM error with this code. (Say, if i try to do something like generateList(6))
function generateList(num){
var arr = [];
for(i=0;i<num;i++){
arr.push(generateTuple());
}
return arr;
}
function generateTuple(){
var tuple = [];
for(i=0;i<3;i++){
tuple.push(Math.floor(Math.random() * 300));
}
return '(' + tuple[0] + ',' + tuple[1] + ',' + tuple[2] + ')';
}
OTOH, if I just generate the random numbers individually and return them (instead of using a list), it works without errors. Can anyone enlighten me as to what is going on here?
function generateTuple(){
var a = Math.floor(Math.random() * 300);
var b = Math.floor(Math.random() * 300);
var c = Math.floor(Math.random() * 300);
return '(' + a + ',' + b + ',' + c + ')';
}
EDIT: So basically if you run the code, it gets stuck in some loop, and after a period of time in the console it returns the OOM error. So I assume it's some memory overflow or something somewhere.
You are creating global i by declaring it without var or let, then you loop with it. That creates unprecedented values for i, leading to the loop will never complete. Declare your variables correctly.
for(var i=0;i<num;i++) // better: let i = 0; ...
and
for(var i=0;i<3;i++) // better: let i = 0; ...
Your is are global variables. Always declare variables with const or let (or var) to avoid global pollution and unexpected behavior (like what's happening here).
Each time generateTuple is run, i gets set to 3 at the end of the for loop in generateTuple. So, the i referenced by generateList - which references the same global variable - never has a chance to get any higher than 4. So if you call generateList with higher numbers, you'll get an infinite loop.
Just declare your variables properly:
function generateList(num){
var arr = [];
for(let i=0;i<num;i++){
arr.push(generateTuple());
}
return arr;
}
function generateTuple(){
var tuple = [];
for(let i=0;i<3;i++){
tuple.push(Math.floor(Math.random() * 300));
}
return '(' + tuple[0] + ',' + tuple[1] + ',' + tuple[2] + ')';
}
console.log(generateList(10));
Related
I'm currently learning javascript and I would appreciate some help.
I've been playing around trying to create a program that would multiply two numbers without using the * operator. I already found an easier way to do it than my approach but I'd like to know why the code I wrote doesn't work:
function addToItself(a) {
a = a + a;
return a;
}
function times(b) {
for (count = 0; count < b; count++) {
addToItself(a)
}
return a;
}
function multiply (x, y) {
a = x;
times(y);
}
let output = multiply(5, 2);
alert(output);
Is it not working because the binding "a" in the addToItself function has a local scope and the multiply function can't read it or is it something else?
Thanks a lot in advance!
The issue is with the scope of each variable. In JavaScript, a variable declated within a function is scoped to that function. This means that a variable declared within a function can only be accessed within the function. Scopes are nested, so a variable declared globally is accessible inside a function too, though that's often discouraged.
Additionally, function arguments (such as a in addToItself and b in times) are treated like variables scoped to the function.
I would advise looking at the MDN docs for "scope" and familiarizing yourself with how variables are scoped in JavaScript.
I have included a fixed version of your code is below, for reference:
function addToItself(a) {
// I used a new variable here since reassigning to an argument is discouraged
const twoA = a + a;
return twoA;
}
console.log('5 + 5 = ' + addToItself(5));
function times(value, times) {
let temp = 0;
for (let count = 0; count < times; count++) {
temp += value;
}
return temp;
};
console.log('5 * 5 = ' + times(5, 5));
No you can't read variable inside another function, there are easier way, like
function multiply(x, y) {
var result = 0;
for (var count = 0; count < y; count++) {
result += x
}
return result;
}
console.log("5 * 2 = " + multiply(5, 2));
I would like to override toString using ES5. Given the following function which returns a complex number:
function complex(real, imaginary){
var z = Object.create(complex.prototype);
z.real = real;
z.imaginary = imaginary;
return z;
}
In order to override toString inherited from Object I do the following:
complex.prototype.toString = function(){ return this.real + " + " + this.imaginary + "*i";};
TEST:
var z = complex(1,1);
console.log(z);
RESULT:
{ real: 1, imaginary: 1 }
Do I miss something?
There are two things going on:
In many environments (including most browsers), console.log doesn't use toString, and
Your complex function doesn't return an object that uses complex.prototype as its prototype, so it doesn't have your toString. You're creating the object you return using {}, which creates an object directly inheriting from Object.prototype.
If you want to call complex without new, you need to explicitly use complex.prototype when creating your object, for instance via Object.create(complex.prototype). (And then when logging, trigger toString on purpose, either calling it directly or converting to string in various other ways.)
Example:
function complex(real, imaginary){
var z = Object.create(complex.prototype);
z.real = real;
z.imaginary = imaginary;
return z;
}
complex.prototype.toString = function(){ return this.real + " + " + this.imaginary + "*i";};
var z = complex(1, 1);
console.log(String(z));
You could call complex via new if you like (but I'm guessing you chose not to on purpose). Just FWIW:
function Complex(real, imaginary){
this.real = real;
this.imaginary = imaginary;
}
Complex.prototype.toString = function(){ return this.real + " + " + this.imaginary + "*i";};
var z = new Complex(1, 1);
console.log(String(z));
or even
class Complex {
constructor(real, imaginary) {
this.real = real;
this.imaginary = imaginary;
}
toString() {
return this.real + " + " + this.imaginary + "*i";
}
}
const z = new Complex(1, 1);
console.log(String(z));
Side note: I've changed "imagenary" to "imaginary" above, which is the correct spelling in English. (Most of the text in your code seemed to be in English, but apologies if it's just that you translated the code in the question from another language and just forgot to translate "imagenary".)
This is my current assignment :
Add a method that will increase the value of one of the numeric properties.
Add a method that will decrease the value of the same numeric property.
Create a for loop after creating an instance of the character. The loop will iterate 100 times.
Inside the loop call one of the methods based on a random number from zero to 3. Using a switch statement, if the value is 0 then call the method that losses; 1 don’t call anything; 2 call the method that gains.
Here is my current coding. I know I'm doing something wrong. I just can't figure out what I am doing wrong with the switch statement.
var BR = "<br />";
function person(name, sandwiches) {
this.name = name;
this.sandwiches = sandwiches;
function jump() {
var text = " leaps over an obstacle.";
return fname + text;
}
function run() {
var text = " runs as fast as they can";
return fname + text;
}
function dodge() {
var attack = math.random();
var att = math.round(attack);
var defense = math.random();
var def = math.round(defense);
if(att > def) {
return "You missed";
}
else {
return "You dodged";
}
}
function date() {
var today = new Date();
return today.toDateString();
}
function shout() {
var word = "Oh no";
return word.toUpperCase();
}
this.addSandwich = function (sandwiches) {
sandwiches = sandwiches + 1;
return sandwiches;
};
this.loseSandwich = function (sandwiches) {
sandwiches = sandwiches - 1;
return sandwiches;
};
}
var character = new person("Jerry", 1);
for(i=0; i < 100; i++) {
var random = Math.floor(Math.random() * 3);
switch(random) {
case 0:
character.loseSandwich(character.sandwiches);
console.log(sandwiches);
break;
case 1:
break;
case 2:
character.addSandwich(character.sandwiches);
break;
}
}
document.write("Name: " + character.name + BR);
document.write("Sandwiches: " + character.sandwiches + BR);
Math.floor(Math.random() * 3) is not what you want.
You want something like Math.random() % 3 to get 0, 1, or 2 every single time
Not sure if this is your problem, but it is at least one of them;
In a few places you have a lowercase math, for example:
function dodge() {
var attack = math.random();
JavaScript is case-sensitive, and it should be Math.random() not math.random()
Another issue is that these functions:
this.addSandwich = function (sandwiches) {
sandwiches = sandwiches + 1;
return sandwiches;
};
do not change the number of sandwiches. You get in a value of sandwiches, add or subtract 1, then return that changed number, but never use the returned result.
You are only changing the value of the variable that was passed in, not changing the number of sandwiches on the instance of the person.
Note that this.sandwiches (the variable on the instance of a person) is not the same variable as sandwiches (the function argument)
I dont think there is any reason to pass the number of sandwiches into those functions, and they could just do:
this.addSandwich = function () {
this.sandwiches = this.sandwiches + 1;
};
or more simply:
this.addSandwich = function () {
this.sandwiches++;
};
Another problem here:
character.loseSandwich(character.sandwiches);
console.log(sandwiches);
The console.log statement is trying to log sandwiches but that is not a variable at that point. You probably wanted console.log(character.sandwiches); However this wouldn't cause an exception, it would just always log undefined.
I am bit unclear in understanding why this below piece of code is not showing the message box,
http://jsfiddle.net/KendoDev/p8Mk2/
function findMax(var x, var y) {
//alert("x is:" + x + " y is: " +y);
var max = 0;
if(x>y)
max = x;
else
max = y;
alert("max is: " + max);
return max;
}
var c=4,d=9;
var m = findMax(c,d);
http://jsfiddle.net/p8Mk2/1/
function findMax(x,y) {
}
No var statement as explained here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
Your javascript isn't syntactically correct - function findMax(var x, var y) should just be function findMax(x, y).
In general, if you write some javascript and nothing happens when you run it, it probably means something went wrong syntactically, and you should check your browser's Error Console. (In this case, it tells you that the function definition is where the error occurred, right on the first "var".)
Your function syntax is wrong: you don't need var in the parameter list.
function findMax(x, y) {
you do not need to put a var
see updated fiddle
http://jsfiddle.net/p8Mk2/2/
Remove var from arguments. Like this:
function findMax(x, y) {
//alert("x is:" + x + " y is: " +y);
var max = 0;
if(x>y)
max = x;
else
max = y;
alert("max is: " + max);
return max;
}
var c=4,d=9;
var m = findMax(c,d);
I have this data response from an AJAX call:
{"18:00":{"twopersons":1,"fourpersons":0}}
Which gets stored into a variable by statsarray = data;
Now how can i loop through statsarray and output the twopersons value?
So I can alert:
18:00 - There's 2 x 2persons and 0 x 4persons
Here is the Ajax call:
var statsarray;
var currentloopeddate = test_date.toString('yyyy-MM-dd')
$.post("/home/sessions",
{ action: 'partner_calendar_checkseats', date: currentloopeddate },
function(data) { statsarray = data; }
);
Just do the following:
var twopersons = data["18:00"].twopersons;
var fourpersons = data["18:00"]["fourpersons"];
(Both variants are possible)
A variant would be:
var shorter = data["18:00"];
var twopersons = data.twopersons;
// ...
Something like:
var tst = {"18:00":{"twopersons":1,"fourpersons":0}};
for(k in tst) {
for(var z in tst[k]) {
console.log(k + ": Theres "+tst[k][z] + " X " + z);
}
}
You can try something like this:
(UPDATE: better example)
var statsarray = {"18:00":{"twopersons":1,"fourpersons":0}};
var hour, persons, line, array;
for (hour in statsarray) {
if (statsarray.hasOwnProperty(hour)) {
array = [];
for (persons in statsarray[hour]) {
if (statsarray[hour].hasOwnProperty(persons)) {
array.push(statsarray[hour][persons] + " x " + persons);
}
}
line = hour + " - There's " + array.join(' and ');
alert(line);
}
}
See: DEMO.
Unfortunately you have to test with .hasOwnProperty to make sure it will work with some libraries.
UPDATE: You have added the code from your AJAX call in your question and I noticed that you declare the statsarray variable outside the callback function, but assign some value to that variable inside the callback. Just keep in mind that you have to run your iteration code inside the function that is the AJAX callback, where you have: statsarray = data; - just after this line, to make sure that you actually have some values to iterate over.