I would like to know why using for loop is not displaying a method when iterating the object.
Please check below example where method getFullList is not listed:
let list = {
firstElement: "Element 1",
secondElement: "Element 2",
thirdElement: "Element 3",
getFullList: function() {
return this.firstElement + ', ' + this.secondElement + ', ' + this.thirdElement;
}
};
for (let key in list) {
if (list.hasOwnProperty(key)) {
console.log(key + ' ' + list[key])
}
}
From your question, I guess you're expecting the function to actually be called.
To do so, you'd need to check the type of list[key] and actually call the function
const list = {
firstElement: "Element 1",
secondElement: "Element 2",
thirdElement: "Element 3",
getFullList: function() {
return this.firstElement + ', ' + this.secondElement + ', ' + this.thirdElement;
}
};
for (const key in list) {
if (list.hasOwnProperty(key)) {
const value = list[key];
console.log(key + " " + value);
if (typeof value === "function") {
value();
}
}
}
The console output when logging the function as the value of "getFullList" will be something like
ƒ () {
return this.firstElement + ', ' + this.secondElement + ', ' + this.thirdElement;
}
Related
Using Javascript, I wrote this code to create an object:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function(){
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
emp_bonus : function(){
return (this.emp_salary*1);
}
};
Now, i'm interested in printing each property & its value so i wrote this code:
for (let eachEle in employee){
if(typeof eachEle=='string' || typeof eachEle=='number'){
console.log(eachEle + ":" + employee[eachEle]);
}
else if(typeof eachEle=='function'){
console.log(eachEle + ":" + employee.eachEle());
}
}
But, on executing, it works fine except for "emp_fullname" & "emp_bonus". Instead of showing the value, it shows me the function:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function() {
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal: "QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary: 13579,
emp_bonus: function() {
return (this.emp_salary * 1);
}
};
for (let eachEle in employee) {
if (typeof eachEle == 'string' || typeof eachEle == 'number') {
console.log(eachEle + ":" + employee[eachEle]);
} else if (typeof eachEle == 'function') {
console.log(eachEle + ":" + employee.eachEle());
}
}
How am I supposed to retrieve the value for those two properties? I'm looking for answers using which I can modify the for...in loop & retrieve the value.
How am i supposed to retrieve the value for those two properties?
The function is the value of those properties. If you want to get the return value of the function, you have to call it.
Note that the typeof check you're doing in your for-in loop is unnecessary. The eachEle variable is the property name, not the property value. In a for-in loop, the name will always be a string. (Not all properties are named with strings, but for-in only covers the ones that are.)
You want to get the value of the property, check if it's a function, and if so call it:
for (let name in employee){
let value = employee[name];
if (typeof value === "function") {
value = employee[name]();
}
console.log(name + ":" + value);
}
Live Example:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function(){
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
emp_bonus : function(){
return (this.emp_salary*1);
}
};
for (let name in employee){
let value = employee[name];
if (typeof value === "function") {
value = employee[name]();
}
console.log(name + ":" + value);
}
You said you just wnated to change the loop, but another approach is to change the object definition to use an accessor property rather than an explicit function:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
get emp_fullname() {
// ^^^ ^^
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
get emp_bonus() {
// ^^^ ^^
return (this.emp_salary*1);
}
};
Then the loop doesn't have to check:
for (let name in employee){
console.log(name + ":" + employee[name]);
}
Live Example:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
get emp_fullname() {
// ^^^ ^^
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
get emp_bonus() {
// ^^^ ^^
return (this.emp_salary*1);
}
};
for (let name in employee){
console.log(name + ":" + employee[name]);
}
That works because when you get the value of an accessor property, its accessor function is run behind the scenes and that function's return value is provided as the property value.
You need to check the type of value, eachEle is value of key which for your object is always string.
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function() {
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal: "QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary: 13579,
emp_bonus: function() {
return (this.emp_salary * 1);
}
};
for (let eachEle in employee) {
if (typeof employee[eachEle] == 'string' || typeof employee[eachEle] == 'number') {
console.log(eachEle + ":" + employee[eachEle]);
} else if (typeof employee[eachEle] == 'function') {
console.log(eachEle + ":" + employee[eachEle]());
}
}
Two things you need to change
You need to check for the value of element for string, number and function and not the key
While executing the function you need to use the brackets notation since its a dynamic key
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function(){
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
emp_bonus : function(){
return (this.emp_salary*1);
}
};
for (let key in employee){
let eachEle = employee[key];
if(typeof eachEle=='string' || typeof eachEle=='number'){
console.log(key + ":" + employee[key]);
}
else if(typeof eachEle=='function'){
console.log(key + ":" + employee[key]());
}
}
Your mistakes are:
1. You wrote: typeof eachEle insted of: typeof employee[eachEle]:
2. The execute is: employee.eachEle() insted of employee[eachEle](). eachEle is a string.
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function(){
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
emp_bonus : function(){
return (this.emp_salary*1);
}
};
for (let eachEle in employee){debugger
if(typeof employee[eachEle]=='string' || typeof employee[eachEle]=='number'){
console.log(eachEle + ":" + employee[eachEle]);
}
else if(typeof employee[eachEle]=='function'){
console.log(eachEle + ":" + employee[eachEle]());
}
}
In your for loop, you iterate over the keys in the object, and those will never be objects. Instead, you should retrieve the item before checking its type.
for(let key in employee){
let value = employee[key];
if(typeof value=='string' || typeof vlaue=='number'){
console.log(key + ":" + value);
}
else if(typeof value=='function'){
console.log(key + ":" + value());
}
}
I am manipulating string to display in UI, Data is being dynamically with below code sometime i don't get header and details so how to make IHeader and IResponse optional for the string concatenation below.
if i dont have IHeader it will break at IHeader.id and throw exception i want to display whatever data is available to render.
main.js
const data = [{
id: "header",
name: "IHeader"
}, {
id: "param",
name: "IParams"
}, {
id: "details",
name: "IResponse"
}]
function buildText(data) {
var IParams;
var IResponse;
var IHeader;
for (var item of data) {
if (item.id === "param") {
IParams = item;
} else if (item.id === "header") {
IHeader = item;
} else if (item.id === "details") {
IResponse = item;
}
}
var text = '';
text += app + '.setConfig({\n' + "env:" + getEnv() + '\n});' + '\n\n';
text += 'let param:' + IParams.name + ' ' + '=' + '' + JSON.stringify(request, null, 4) + ';\n\n';
text += ref + '(' + 'param,(result:' + ' ' + '{' + '\n' + IHeader.id + ':' + IHeader.name + '\n' + IResponse.id + ':' + IResponse.name + '\n' + '})' + ' ' +
' => {\n console.log(result); \n});';
}
1 - You can try to create an object with empty values. That'll prevent the exception.
emptyObject = {id: ""} // more empty keys, if there is
IParam = (item.id === "param") ? item : emptyObject
2 - Or ignore that concatenation of the variable if undefined or null.
if (Iparam) {
// concatenation ..
}
I have an array of items:
var myArr = ['item1', 'item2', 'item3'];
I'm attempting to loop over these items and check if they exist in my database. If the item does not exist, then I add it to the database.
var sql = 'Select * from DB where item="' + myArr[i] + '"';
connection.query(sql, function(e, r, f) {
if(!e && r.length <= 0) {
performInsertOnDB(myArr[i]);
}
});
My trouble is, the reference to variable i will not stay as connnection.query is asynchronous. I need to wait until the first select finishes before I can continue. I'm trying to use the Async library to accomplish this, but I must not be fully grasping how to perform the task.
This is what I have so far:
async.each(lootArray, function(lootItem, addLootItem) {
var sql = "SELECT * FROM loot_history WHERE date = DATE('" + moment(lootItem[1]).format('YYYY-MM-DD') + "') AND time = '" + lootItem[2] + "' AND itemId = " + lootItem[4];
connection.query(sql, function(error, results, fields) {
if (error) {
sendDiscordMessage(loachannel, error + ', <#105094681141977088>');
return false;
} else {
if (results.length > 0) {
//duplicates.push(lootArray[i]);
} else {
addLootItem(lootItem);
}
}
});
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if (err) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('A file failed to process');
} else {
console.log('All files have been processed successfully');
}
});
function addLootItem(lootItem) {
var sql = "INSERT INTO loot_history SET player = " + lootItem[0] + ", date = " + moment(lootItem[1]).format('YYYY-MM-DD') + ", time = '" + lootItem[2] + ", item = " + lootItem[3] + ", itemId = " + lootItem[4] + ", itemString=" + lootItem[5] + ", response= " + lootItem[6] + ", votes= " + lootItem[7] + ", class= " + lootItem[8] + ", instance=" + lootItem[9] + ", boss=" + lootItem[10] + ", gear1=" + lootItem[11] + ", gear2=" + lootItem[12] + ", reasponseId=" + lootItem[13] + ", isAwardReason=" + lootItem[14];
connection.query(sql, function(error, results, fields) {
if (error) {
sendDiscordMessage(loachannel, error + ', <#105094681141977088>');
}
});
}
EDIT: Everything works, except the callback AddLootItem is not firing. Why is this callback not getting called? I can set log events in that if statement that execute, but the function itself never fires.
The problem is that the name of async callback is the same as the function you want to be called when the item does not exist. Try to change the name in the function to something else let's say: callback, and call it in your if statement or pass it to addLootItem, and call it there once the item added.
async.each(lootArray, function(lootItem, callback) {
var sql = "SELECT * FROM loot_history WHERE date = DATE('" + moment(lootItem[1]).format('YYYY-MM-DD') + "') AND time = '" + lootItem[2] + "' AND itemId = " + lootItem[4];
connection.query(sql, function(error, results, fields) {
if (error) {
sendDiscordMessage(loachannel, error + ', <#105094681141977088>');
calback(err);
} else {
if (results.length > 0) {
//duplicates.push(lootArray[i]);
callback();
} else {
addLootItem(lootItem, callback);
}
}
});
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if (err) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('A file failed to process');
} else {
console.log('All files have been processed successfully');
}
});
function addLootItem(lootItem, done) {
var sql = "INSERT INTO loot_history SET player = " + lootItem[0] + ", date = " + moment(lootItem[1]).format('YYYY-MM-DD') + ", time = '" + lootItem[2] + ", item = " + lootItem[3] + ", itemId = " + lootItem[4] + ", itemString=" + lootItem[5] + ", response= " + lootItem[6] + ", votes= " + lootItem[7] + ", class= " + lootItem[8] + ", instance=" + lootItem[9] + ", boss=" + lootItem[10] + ", gear1=" + lootItem[11] + ", gear2=" + lootItem[12] + ", reasponseId=" + lootItem[13] + ", isAwardReason=" + lootItem[14];
connection.query(sql, function(error, results, fields) {
if (error) {
sendDiscordMessage(loachannel, error + ', <#105094681141977088>');
}
done();
});
}
I try to reach a subfuntion that is element of an array.
In the below example we can reach the name property like window['name'].
But if property is a function it can not be called like this. What I try to do is in .each function if item is a function run the function. How can I do that ?.
$(document).ready(function() {
var human = {
name: 'Emin',
surname: 'Çiftçi',
job: 'Software Developer',
func: function() {
alert(name + ' ' + surname + ', ' + job);
}
};
$.each(human, function(index, item) {
//if(item is a function) {
// run the function
//}
$('<div>').text(index + ': ' + item).appendTo('#deneme');
});
});
Use typeof
PS: You also need to fix the name, surname and job in the alert
$(document).ready(function() {
var human = {
name: 'Emin',
surname: 'Çiftçi',
job: 'Software Developer',
func: function() {
alert(human.name + ' ' + human.surname + ', ' + human.job);
}
};
$.each(human, function(name, item) {
console.log(typeof item);
if (typeof item == "function") item();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
You can use typeof:
if(typeof item === 'function'){
item(); // run it
}
I'm trying to parse JSON in JavaScript. If my JSON data looks like below, I want to iterate through all the JSON elements that start with "custom" and not with any other string. How do I do this?
{
"fields": {
"custom12": {
value: "dsada"
},
"custom45": {
value: "adsadad"
},
"test12": {
value: "12323"
}
}
}
var newObject = {}, key;
for(key in data.fields){
if(key.search(/custom/) > -1){
newObject[key] = data.fields[key];
}
}
console.log(newObject);
The following iterates the properties of the fields object and checks whether the property's name contains custom:
var data = yourObjectLiteral, i, current;
for(i in data.fields) {
if(i.indexOf('custom') > -1) {
current = data.fields[i];
// ... your logic ...
}
}
With the json string you provided I'd do it as such:
<script src="json2.js"></script>
<script>
var raw = '{'
+ ' "fields": {'
+ ' "custom12": {'
+ ' "value": "dsada"'
+ ' },'
+ ' "custom45": {'
+ ' "value": "adsadad"'
+ ' },'
+ ' "test12": {'
+ ' "value": "12323"'
+ ' }'
+ ' }'
+ '}';
var data = JSON.parse(raw);
var fields = data.fields;
var message = '';
for (var key in fields) {
if (key.indexOf('custom') === 0) {
message += key + ': ' + fields[key].value + '\n';
}
}
alert(message);
</script>
But, if you can rewrite the incomming message a little it will look simpler.
<script src="json2.js"></script>
<script>
var raw = '{'
+ ' "custom12": "dsada",'
+ ' "custom45": "adsadad",'
+ ' "test12": "12323"'
+ '}';
var fields = JSON.parse(raw);
var message = '';
for (var key in fields) {
if (key.indexOf('custom') === 0) {
message += key + ': ' + fields[key] + '\n';
}
}
alert(message);
</script>