This question already has answers here:
Javascript infamous Loop issue? [duplicate]
(5 answers)
Closed 8 years ago.
I am writing getter and setters dynamically. my code is buggy. I need help in correcting it.
Portion of my code looks like following:
var a = {};
var myArray = ["abc", "xyz", "bbb"];
for (var i = 0; i < myArray.length: i++) {
var tempVar = myArray[i];
Object.defineProperty(this, tempVar, {
get: function () {
var ret = $.extend(true, {}, a[tempVar]);
return ret;
},
set: function (intObj) {
a[intObj.type] = intObj;
}
});
}
The problem of mine is there in get function I want to access value of tempVar but I am not able to access it.
While defining it is not even going in get function.
And while using it is going in get function but the tempVar will be last value of array only.
If some body can guide me in this. It would be great.
Yes that link helped. Thanks. So my code will now look like following. This is a basic concept but always run away from closures. Today learnt! Thanks.
var a = {};
var myArray = ["abc", "xyz", "bbb"];
for (var i = 0; i < myArray.length: i++) {
var tempVar = myArray[i];
Object.defineProperty(this, tempVar, {
get: function (newTemp) {
return function(){
var ret = $.extend(true, {}, a[newTemp]);
return ret;
}
}(tempVar),
set: function (intObj) {
a[intObj.type] = intObj;
}
});
}
Related
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I have a function which is a loop by itself and in this loop I am creating an object. But when after the loop I'm trying to access the object properties, I get an response of undefined.
When I try to just console.log the object itself, I get it. The problem is with properties.
I would be grateful, if someone could help me. I did a good research, but didn't manage to find the solution. My case is very strange. Everything is good except the properties. I need the help of senior developers.
Here is the code.
var countMap = {};
var counter = 0;
$('#share_table_body').find('.js-post').each(function () {
var totalCount = 0;
$(this).find('.js-social').each(function () {
var $this = $(this);
var socialType = $(this).data('social-type');
var url = $this.closest('.js-post').data('url');
getShareStatus(url, socialType)
.then(function (shareCount) {
$this.text(shareCount);
if (!countMap[socialType]) {
countMap[socialType] = 0;
}
if (!countMap['total']) {
countMap['total'] = 0;
}
countMap[socialType] += shareCount;
totalCount += shareCount;
countMap['total'] += shareCount;
$this.siblings('.js-total').text(totalCount);
})
.fail(function (err) {
$('.error-notice').removeClass('hidden');
$this.css('color', 'red').text('!');
});
});
counter++;
});
if (counter == $('#share_table_body').find('.js-post').length) {
console.log(countMap);
$('.total-facebook').text(countMap['facebook']);
}
Are you returning anything from your function? Specifically...
return countMap;
I've searched the questions here and on Google and I find answers, but they don't seem to work in my code. I want to add a new PhotoIndex property to a JSON object in AngularJS. I have the code below which works (the photos appear), but doesn't have the PhotoIndex property:
$scope.GetImagesOnBar = function ()
{
var photos = $scope.$parent.Photos;
return photos;
};
When I try to add the PhotoIndex property to the JSON array object named photos, it breaks the code and the photos no longer appear. Can you tell me why?
$scope.GetImagesOnBar = function ()
{
var photos = $scope.$parent.Photos;
var index = 0;
for (var i = $scope.ImageFirst; i <= $scope.ImageLast; i++)
{
photos[i].PhotoIndex = index;
index = index + 1;
}
return photos;
};
OK, thanks for the comments. I checked the console as suggested and saw the error "$scope.$parent.Photos[i] is undefined". I don't know why, but I decide to try angular.foreach and that worked. See the solution below.
$scope.GetImagesOnBar = function ()
{
var index = 0;
angular.forEach($scope.$parent.Photos, function (photo)
{
photo.PhotoIndex = index;
index = index + 1;
});
return $scope.$parent.Photos;
};
Hi I have this function:
changeTarea: function() {
var self = this;
$("#select_tarea_id").change(function() {
var id_tarea = $("#select_tarea_id").val();
$.each(self.objTareasFlot, function(index,value) {
for(var i = 0; i < value.length; i++) {
if(value[i].Id == id_tarea) {
self.objTareasFlotFinal['id']=value[i].Id;
self.objTareasFlotFinal['id_pro']=value[i].Id_proyecto;
self.objTareasFlotFinal['tarea']=value[i].nombre_tarea;
self.objTareasFlotFinal['porcentaje']=value[i].porcentaje;
console.info(self.objTareasFlotFinal);
}
}
});
});
}
And the function print :
But I need the 3 results in one array
for example :
How can I do that with that function? Sorry for my english I did try to explain of the better way
You can declare an array and push populated object into it. Something like this:
changeTarea: function(){
var self = this;
var container[];
$("#select_tarea_id").change(function() {
var id_tarea = $("#select_tarea_id").val();
$.each(self.objTareasFlot, function(index,value) {
for(var i = 0; i < value.length; i++){
if(value[i].Id == id_tarea){
self.objTareasFlotFinal['id']=value[i].Id;
self.objTareasFlotFinal['id_pro']=value[i].Id_proyecto;
self.objTareasFlotFinal['tarea']=value[i].nombre_tarea;
self.objTareasFlotFinal['porcentaje']=value[i].porcentaje;
console.info(self.objTareasFlotFinal);
container.push(self.objTareasFlotFinal);
}
}
});
});},
Create an array variable var result = []; inside your function.
Within your loop push() the objects into it;
results.push(self.objTareasFlotFinal);
var newArray = [];
self.objTareasFlotFinal['id']=value[i].Id;
self.objTareasFlotFinal['id_pro']=value[i].Id_proyecto;
self.objTareasFlotFinal['tarea']=value[i].nombre_tarea;
self.objTareasFlotFinal['porcentaje']=value[i].porcentaje;
newArray.push(self.objTareasFlotFinal);
// console.log should show the results
console.log(newArray);
If this array is meant to be global and accessible outside the function, you might want to define newArray outside the function first and remove the var from it within the function.
Then every time somebody runs the function, a new object is added to the array.
Alternatively, you could just return the array as the final value:
var newArray = [];
self.objTareasFlotFinal['id']=value[i].Id;
self.objTareasFlotFinal['id_pro']=value[i].Id_proyecto;
self.objTareasFlotFinal['tarea']=value[i].nombre_tarea;
self.objTareasFlotFinal['porcentaje']=value[i].porcentaje;
newArray.push(self.objTareasFlotFinal);
return newArray;
This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 9 years ago.
This is a simplified code that runs on Node.js crawler and it gets all data.
But how do I insert inside the "callback": function value of var "i" from cycle for(var i=0... When I'm adding name: datas[i].name it returns an error:
TypeError: Cannot read property 'undefined' of undefined
var Crawler = require("crawler").Crawler;
var crawler = new Crawler;
var datas = [
{name: 'John', url: 'john025'},
{name: 'Jim', url: 'jim04567'}
];
function crauler(done) {
for (var i = 0; i < datas.length; i++) {
var link = 'http://somesite.com/' + datas[i].url;
crawler.queue([{
"uri": link,
// inside this func
"callback": function (error, result, $, datas, i) {
var arr = $('.blogpost').map(function (index) {
var str = $(this).attr('href');
var object = {
numb: str,
name: datas[i].name
};
return obj;
}).get().join(',');
done(arr);
} }]) }; };
crauler (function (arr) {
console.log(arr);
});
You can't pass datas and i into callback functions like this. What arguments that the callback functions will be called with are up to the caller, you don't have the control of it.
You're seeing "TypeError: Cannot read property 'undefined' of undefined" because you want your callback function to have datas and i as parameters; but the caller will call the callback with the first 3 arguments only [crawler callback reference], so the datas and i are undefined.
Therefore, you should remove the datas and i from in line:
"callback": function (error, result, $, datas, i) {
Because datas is defined in the outer scope of the callback function, the callback can access datas without any special treatment. For the variable i, it's a little bit tricky as mentioned in other answers, so you need to create a closure for it.
So, your callback function definition should be something looks like the following:
"callback": (function(i) { // create closure for i
return function (error, result, $) { // no more datas and i here
var arr = $('.blogpost').map(function (index) {
var str = $(this).attr('href');
var object = {
numb: str,
name: datas[i].name // access datas as it
};
return obj;
}).get().join(',');
done(arr);
}
})(i)
You're trying to create a closure around i inside of a loop which is causing you problems. This answer should help you:
JavaScript closure inside loops – simple practical example
You need a closure to capture the values, this is one way to solve the problem. Read up on closures.
Javascript
var Crawler = require("crawler").Crawler;
var crawler = new Crawler;
var datas = [{
name: 'John',
url: 'john025'
}, {
name: 'Jim',
url: 'jim04567'
}];
function queue(link, i) {
crawler.queue([{
"uri": link,
// inside this func
"callback": function (error, result, $, datas, i) {
var arr = $('.blogpost').map(function (index) {
var str = $(this).attr('href');
var object = {
numb: str,
name: datas[i].name
};
return obj;
}).get().join(',');
done(arr);
}
}]);
}
function crauler(done) {
for (var i = 0; i < datas.length; i++) {
var link = 'http://somesite.com/' + datas[i].url;
queue(link, i);
};
crauler(function (arr) {
console.log(arr);
});
Here is the code:
http://jsfiddle.net/GKBfL/
I am trying to get collection.prototype.add to return a reference such that the final alert will display testing, testing, 123, testing. Is there a way to accomplish what I'm trying to do here?
HTML:
<span id="spantest">testing, testing, 123, testing</span>
JavaScript:
var collection = function () {
this.items = {};
}
collection.prototype.add = function(sElmtId) {
this.items[sElmtId] = {};
return this.items[sElmtId];
}
collection.prototype.bind = function() {
for (var sElmtId in this.items) {
this.items[sElmtId] = document.getElementById(sElmtId);
}
}
var col = new collection();
var obj = {};
obj = col.add('spantest');
col.bind();
alert(obj.innerHTML);
You problem is this line:
this.items[sElmtId] = document.getElementById(sElmtId);
This overwrites the object currently assigned to this.items[sElmtId] with the DOM node. Instead, you should assign the node to a property of that object:
this.items[sElmtId].node = document.getElementById(sElmtId);
That way, obj.node will always refer to the current node:
alert(obj.node.innerHTML);
DEMO
Side note: The problem with your fiddle is also that you execute the code when the DOM is not built yet (no wrap (head)), so it cannot find #spantest. You have to run the code once the DOM is ready, either no wrap (body), onDomRead or onLoad.
Creating a reference like you need is impossible in JavaScript. The closest thing you can get is either a nested or closed object, or just copying it over, like so:
var collection = function() {
this.items = {};
};
collection.prototype.add = function(sElmtId) {
return this.items[sElmtId] = {};
};
collection.prototype.bind = function() {
for(var sElmtId in this.items) {
var element = document.getElementById(sElmtId);
for(var x in element) {
this.items[sElmtId][x] = element[x];
}
}
};
var col = new collection();
var obj = {};
obj = col.add('spantest');
col.bind();
alert(obj.innerHTML);
But it won't be truly "bound". You'll have to use nested objects if you need that kind of functionality, and it will probably defeat the point of your syntactic sugar.
http://jsfiddle.net/GKBfL/7/