The last two line of code unable two understand [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
function makeArmy () {
let shooters = [];
let i = 0;
while (i < 10) {
let shooter = function() {
console.log(i);
};
shooters.push(shooter);
i++
}
return shooters;
}
let army = makeArmy();
army[0]();
army[5]();
i didnt understand this what-why this need for output
army[0]();
army[5]();
i know [0 and 5 are index numbers]
im not understaning why this army is calling two times and why we need to call this for output?

The army is an array of closures. Each closure print's the content of the variable i. But at the time that you execute the closure (e.g. when calling army[5]()) the while loop did already finish and thus i will always be 10. That is, because i was declared using the var keyword and thus the scope of i is the makeArmy() function. This is why army[0]() and army[5]() both print 10.
The code below is what you aim for:
Now i is passed into a let variable x and because the let keyword is used instead of var, the scope of x now is the individual shooter closure for that particular i-th iteration instead of the makeArmy function.
function makeArmy () {
var shooters = [] // <-- use var here
var i = 0 // <-- because they're simple variables
while (i < 10) {
let x = i // <-- use let here to make x a block-scoped local variable that is bound to the closure
const shooter = function() { // <-- use const here because you never change the shooter thus it's a simple constant
console.log(x)
}
shooters.push(shooter)
i++
}
return shooters
}
More details, explainations and simple examples can be found here.

Related

cannot access the data of the first API in second API function [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
<script>
/* 1st API*/
$.getJSON("http://cricapi.com/api/matches/?apikey=6aP8B4MImxSNxI6fevBmC2ZshO42",function(data){
var len = data.matches.length;
for(i=0;i<len;i++){
id = data.matches[i].unique_id;
ms = data.matches[i].matchStarted;
x = data.matches[i].date;
team_1 = data.matches[i]['team-1']
/* 2nd API*/
$.getJSON("https://cricapi.com/api/cricketScore/?apikey=6aP8B4MImxSNxI6fevBmC2ZshO42&unique_id="+id,function(data1){
console.log(team_1);
});
}
});
why i cannot get the team_1 of each match in second getJSON(). It is giving the output of same team name multiple times please help me to get the team names of each match. Appreciate any help!!
This "bug" is caused by hoisting.
Index i is stored as var, and it isn't in local for loop scope, so, when the index has gained its final value, the same value is used.
You can use let keyword:
for(let i=0;i<len;i++){ ..
so the variable will be loop scoped
Also Check out this link
function getScore(id, callback) {
$.getJSON("https://cricapi.com/api/cricketScore/?apikey=6aP8B4MImxSNxI6fevBmC2ZshO42&unique_id="+id, function(data1) {
callback(data1);
});
}
$( document ).ready(function() {
$.getJSON("http://cricapi.com/api/matches/?apikey=6aP8B4MImxSNxI6fevBmC2ZshO42",function(data){
var len = data.matches.length;
for(i=0;i<len;i++){
id = data.matches[i].unique_id;
ms = data.matches[i].matchStarted;
x = data.matches[i].date;
team_1 = data.matches[i]['team-1']
/* 2nd API*/
getScore(id, function(data1) {
console.log(data1);
});
}
});
});

Having issues preserving variable contents in closure [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 7 years ago.
(This question is related to this and this but answers there haven't helped me figure out what's wrong in my case.)
I am trying to create an array of clickable elements where each element is bound to a separate instance of some object.
I've simplified the real code I'm working on as much as possible for this question here:
//----------
// Setup part
// SomeObject just holds a number
var SomeObject = function(number) {
this.number = number;
this.getNumber = function() {
return this.number;
};
};
// contains SomeObject(1) through SomeObject(9)
var someArrayContainingObjects = [];
for(var i=1; i<=9; i++)
{
someArrayContainingObjects.push(new SomeObject(i));
}
//----------
// Problem part
for(var y=0; y<3; y++)
{
for(var x=0; x<3; x++)
{
var obj = someArrayContainingObjects[y*3 + x]; // Creating new variable in the loop every time explicitly with var statement?
$("body").append(
$("<button />")
.text("Should output ("+obj.getNumber()+")")
.click(function() {
alert(obj.getNumber()); // Will always be 9
})
);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
I thought by explicitly using var obj = ... inside the loop I would create a new context/scope/however it's called for each anonymous click() callback function I'm creating – so that when I click one of the objects, the appropriate number of the respective SomeObject is alert()ed and not always the number of the last SomeObject the loop takes from the array.
Could someone please explain to me why this code snippet does not work as expected, and what to change to have the code function correctly?
To create closure scope in JavaScript you need to invoke a function. In JavaScript we can also invoke functions as soon as you declare them. They are called immediately invoked function expressions
This way you can preserve your x and y values in the scope of the IIFE.
for(var y=0; y<3; y++) {
for(var x=0; x<3; x++) {
(function (x, y) {
var obj = someArrayContainingObjects[y * 3 + x]
$("body").append(
$("<button />")
.text("Should output ("+obj.getNumber()+")")
.click(function() {
alert(obj.getNumber())
})
)
}(x, y))
}
}
Working codepen
Also, this is a big problem that people encounter when they try to write JavaScript as if it was a class based language. I would try to look into writing JS from a more functional perspective

Don't Repeat Yourself [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Would like to know if there is a better way to write this small block of code keeping DRY in mind. I see the similarities in the functions of course, but I am not sure how to shorten it. Also, I would like to know how much of a difference the shortening would make if any. Thank you, Jason
var adminAlert = {
alert: function() {
var sumAlert = sumSupport = sumCashout = sumPhone = 0;
$.getJSON("alertFeed.JSON", function(data) {
$.each(data.alertData, function(i, allAlerts) {
sumAlert += parseFloat(allAlerts.value);
sumSupport += parseFloat(allAlerts.support);
sumCashout += parseFloat(allAlerts.cashout);
sumPhone += parseFloat(allAlerts.phone);
$(".alertPoints").html(sumAlert);
$(".support-requests").html(sumSupport);
$(".cashout-giftcards").html(sumCashout);
$(".phone-verification").html(sumPhone);
});
});
}
};
The version undernearth is more DRY. Basically, to make your code DRY, you:
Identify repeated stuff. In your case it was parseFloat(allAlerts.foobar) and $(".blablabla").html(foobar);
Identify what is different between those repetitions. In your case you used a series of 4 keys within the allAlerts object: 'value', 'support', 'cashout' and 'phone'. Each of those 4 keys correspond to a CSS selector, e.g. cashout corresponds to ".cashout-giftcards";
Take what you identified in step 2 and put it into a declarative map. In your case:
{
'value': 'alertPoints',
'support': 'support-requests',
'cashout': 'cashout-giftcards',
'phone': 'phone-verification'
}
4. Replace what you identified in step 1 with a more unified / abstract code using the map you created in step 3. In your case, the four lines like sumCashout += parseFloat(allAlerts.cashout); can be replaced with only one line like sum[k] = parseFloat(allAlerts[k])
var
// To avoid repeatedly doing stuff like $(".alertPoints").html(sumAlert),
// we'll declare a concise map defining what will be updated by what:
map = {
'value': 'alertPoints', // later we will use this to update $(".alertPoints") with what comes from allAlerts.value
'support': 'support-requests', // later we will use this to update $(".support-requests") with what comes from allAlerts.support
'cashout': 'cashout-giftcards',
'phone': 'phone-verification'
},
adminAlert = {
alert: function(){
var
// Let's define an object that will hold the sums for us
sum = {},
// And also a variable to iterate our map;
k;
$.getJSON("alertFeed.JSON", function(data) {
$.each(data.alertData, function(i, allAlerts) {
// So we have 4 things to sum and update.
// They all are defined in our map.
// Lets go through the map and get things done:
for (k in map) {
// The value of k will be "value", "support" etc...
if (!(k in sum)) {
// In case the `sum` object does not yet have a key equal to the value of `k`, we initiate it.
// This is to have a start value of 0 to start adding to it:
sum[k] = 0;
}
// This is effectively the same as
// sumAlert += parseFloat(allAlerts.value) etc. etc.
// but written in unified manner to cover all the four cases.
// So when say `k` equals to `cashout`, this
// will be the same as `sum.cashout += parseFloat(allAlerts.cashout)`
sum[k] += parseFloat(allAlerts[k]);
// Again, a unified version of
// $(".alertPoints").html(sumAlert) etc. etc.
$('.' + map[k]).html(sum[k]);
}
});
});
}
};
In terms of difference — it is just easier to maintain / fix / debug / extend etc. Performance will probably be about the same.

JS loop producing no result [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Trying to create an array with a loop and then sum all the contents of the array and put the result as the contents of a DIV but when I run the fiddle I get no result and jshint says everything is well formed.
var begin = 500000;
var stop = 999999;
var arrInt = [];
// Create an array worth summing
var CreateArray = function (begin,stop) {
while(begin < stop +1){
arrInt.push(begin++);
}
};
// Sum all ints in an array
var IntSum = function (ManyInts) {
var i = arr.length; while (i--) {
return;
}
};
var example = document.getElementById("example").innerHTML;
example=IntSum(arrInt);
<div id="example"></div>
http://jsfiddle.net/7b8rqme5/
At no point do you call CreateArray. You call your other function, IntSum, which does precisely nothing. Also, you create a variable example and assign a dom element to it, then you immediately overwrite it with a (noop) function result. There are additional issues with your code as well.
My advice: slow down, determine what it is you need to accomplish, and take it step by step.
I think this is what you wanted. But not really sure what you are trying to do here.
var begin = 500000;
var stop = 999999;
var arrInt = [];
var CreateArray = function (begin,stop) {
while(begin < stop +1){
arrInt.push(begin++);
}
};
var IntSum = function (ManyInts) {
var sum = 0
var i = ManyInts.length; while (i--) {
sum += ManyInts[i];
}
return sum;
};
var example = document.getElementById("example").innerHTML;
CreateArray(begin, stop);
var saic=IntSum(arrInt);
document.getElementById("example").innerHTML = saic
http://jsfiddle.net/wpnkL6k2/

Why does this addition result in NaN? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I try to add prices to find the total, but console.log prints either NaN or just a repetition of the number :
This is my JavaScript code:
var qt_articles = new Array();
var tab_prix = new Array();
function print_nb_article(article, nb){
$('#top_ten_nb_'+article).text(nb);
var prix = $('#top_ten_nb_'+article+'_prix').val();
var prix_tt = $('.prix_'+article).text(prix*nb);
if (prix_tt > 0) tab_prix.push(prix_tt);
for(i=0; i<tab_prix.length; i++){
prix_global += parseFloat(tab_prix[i]);
console.log(prix_global);
}
}
$('#plus_veste').click(function() {
veste++;
print_nb_article('veste', veste);
return false;
});
My HTML:
<span id="prix_global">0</span>
Where is the problem?
Because you don't initialize prix_global. Add
var prix_global = 0;
In some browsers, it would be initialized to the element due to the id (but never to the parsed content of the span...). If you try to add to the initial value of the span, do
var prix_global = parseFloat(document.getElementById('prix_global').innerHTML);
... computations...
document.getElementById('prix_global').innerHTML = prix_global;
More generally, pay attention to the initialization of your variables (see also veste) and their parsing (you're lucky with prix*nb).
I see several issues, highlighted with comments:
var qt_articles = new Array();
var tab_prix = new Array();
function print_nb_article(article, nb) {
$('#top_ten_nb_' + article).text(nb);
var prix = $('#top_ten_nb_' + article + '_prix').val();
// Note 1: Below, `prix_tt` will be a jQuery object, not a string or number.
// You might want to set `prix_tt`, *then* set it as the text of the element.
var prix_tt = $('.prix_' + article).text(prix * nb);
// Note 2: So this comparison will compare `"[object Object]"` to `"0"`,
// and get `false`. This'll get fixed if you fix the above.
if (prix_tt > 0) tab_prix.push(prix_tt);
for (i = 0; i < tab_prix.length; i++) {
// Note 3: If the push *had* happened, here you'd be retrieving
// the object and trying to parse `"[object Object]"` as a number.
// This would also get fixed by the above.
// Note 4: You're not setting `prix_global` to `0` before the loop,
// so either it's `undefined` or you're going to get the wrong total
prix_global += parseFloat(tab_prix[i]);
console.log(prix_global);
}
// Note 5: Do you ever do anything with `prix_global`??
}
$('#plus_veste').click(function () {
veste++;
print_nb_article('veste', veste);
return false;
});
Also note that your'e not declaring i anywhere (the variable you use for your loop), so you're almost certainly falling prey to The Horror of Implicit Globals. That also applies to veste unless it's declared somewhere you haven't shown (and possibly others).
So to fix it:
Probably change the code under Note 1 to:
var prix_tt = prix * nb;
$('.prix_' + article).text(prix_tt);
Declare your variables in the innermost scope where you need them.
Set prix_global to 0 prior to the loop.
Do something with prix_global when you're done calculating it.
Other things I would do:
Get rid of the globals. You almost certainly don't need them.
Use [], not new Array(), to create arrays.

Categories