javascript print nested object using for loop? - javascript

how do i print out all the person in the person object?
For Example i want my output to be like this.
John Doe 25
Paul Vosper 23
var txt = "";
var person = {
p1: {fname:"John", lname:"Doe", age:25},
p2: {fname:"Paul", lname:"Vosper", age:23}
};
var x;
for (x in person)
{
txt += person[x] + " ";
}
document.getElementById("demo").innerHTML = txt;

You can do a map/join:
var txt = Object.keys(person).map(function(k) {
var p = person[k];
return [p.fname, p.lname, p.age].join(' ');
}).join(' ');
Output in the console:
If you want a line break element (<br>) between them, just join on a <br>:
document.getElementById("demo").innerHTML = Object.keys(person)
.map(combineAllProperties)
.join('<br>');
function combineAllProperties(k) {
var p = person[k];
return [p.fname, p.lname, p.age].join(' ');
}

You can use Array.prototype.reduce in conjunction with Object.keys:
var person = {
p1: {fname:"John", lname:"Doe", age:25},
p2: {fname:"Paul", lname:"Vosper", age:23}
};
document.write(Object.keys(person).reduce(function(s, p, i) {
var o = person[p];
return s + (i>0?'<br>':'') + o.fname + ' ' + o.lname + ' ' + o.age
}, '')
);

Related

Data in javascript factory is being overridden if factory is ran multiple times

In the following code pen you can see that I have setup a factory that takes in an array of Objects as data, loops through that data and then add's button's into the page with an onclick event that logs out the data object.
const testData = [{
fruit: 'Banana'
},
{
fruit: 'Apple'
},
{
fruit: 'Pear'
}
];
const scopeCreep = ({
data
}) => {
const outputDiv = document.getElementById('output');
const getID = () => {
return Math.random().toString(36).substring(7);
};
var lastID;
for (let x = 0; x < data.length; x++) {
data[x].ID = getID();
lastID = data[x].ID;
}
//Add a button to the test div
let button = document.createElement('button');
button.innerText = lastID;
button.onclick = () => {
console.log(privateData, lastID);
outputDiv.innerHTML += "Click resulted in: </br>";
outputDiv.innerHTML += "Array data: " + JSON.stringify(data, null, 2) + ", lastID: " + lastID + "</br>";
};
document.body.appendChild(button);
//JSON parse hack
var privateData = JSON.parse(JSON.stringify(data, null, 2));
//Add new IDS and choose a random one to output as selection
return {
privateData,
data
};
};
const tester = () => {
const outputDiv = document.getElementById('output');
var data1 = scopeCreep({
data: testData
});
outputDiv.innerHTML += "1 load: " + JSON.stringify(data1.privateData, null, 2) + " - " + JSON.stringify(data1.data, null, 2) + "</br>";
var data2 = scopeCreep({
data: testData
});
outputDiv.innerHTML += "2 load: " + JSON.stringify(data2.privateData, null, 2) + " - " + JSON.stringify(data2.data, null, 2) + "</br>";
var data3 = scopeCreep({
data: testData
});
outputDiv.innerHTML += "3 load: " + JSON.stringify(data3.privateData, null, 2) + " - " + JSON.stringify(data3.data, null, 2) + "</br>";
};
document.addEventListener("DOMContentLoaded", tester);
<div id="test">
</div>
<div id="output">
</div>
It seems that the data is being overridden with the last loaded data. (I hope that makes sense?)
My question boils down to: Why is this data being changed out of scope & how can I stop it?
Thanks,
you have to put this line var privateData = JSON.parse(JSON.stringify(data, null, 2)); at the top of the function in order to clone it before modify the original object
I am cloning the data in scope using the following, thankfully the data does not contain any functions as the following would not replicate functions.
JSON.parse(JSON.stringify(data));

Get full word containing a specific element

Having the reference to a specific DOM element (e.g. <mark>), how can we get the full word containing that element?
For example :
H<mark>ell</mark>o Wor<mark>l</mark>d, and He<mark>llo</mark>, <mark>Pluto</mark>!
I expect to get the following output :
First <mark>: Hello
Second: World
Third: Hello
Fourth: Pluto
var $marks = $("mark");
var tests = [
"Hello",
"World",
"Hello",
"Pluto",
];
function getFullWord($elm) {
// TODO: How can I do this?
// This is obviously wrong.
return $elm.html();
}
var $marks = $("mark");
tests.forEach(function(c, i) {
var word = getFullWord($marks.eq(i));
if (word !== c) {
alert("Wrong result for index " + i + ". Expected: '" + c + "' but got '" + word + "'");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
H<mark>ell</mark>o Wor<mark>l</mark>d, and He<mark>llo</mark>, <mark>Pluto</mark>!
If you need fast and compact code (one-liner), try this:
var $marks = $('mark');
$marks.each(function() {
var wholeWord = (this.previousSibling.nodeValue.split(' ').pop() +
this.textContent +
this.nextSibling.nodeValue.split(' ')[0]
).replace(/[^\w\s]/gi, '');
});
JSFiddle (with logging into console and comments)

Parsing a JSON Array with JavaScript returning selected parts

I have a very simple snipplet for a json array and a javascript function that now returns a single argument:
<!DOCTYPE html>
<html>
<body>
<h2>JSON Array Test</h2>
<p id="outputid"></p>
<script>
var arrayinput = '{"collection":[' +
'{"firstAttr":"XXXA","secAttr":"13156161","lastAttr":"01" },' +
'{"firstAttr":"XXXB","secAttr":"11153325","lastAttr":"02" },' +
'{"firstAttr":"XXXC","secAttr":"14431513","lastAttr":"03" },' +
'{"firstAttr":"XXXC","secAttr":"161714","lastAttr":"01" },' +
'{"firstAttr":"XXXC","secAttr":"151415","lastAttr":"02" },' +
'{"firstAttr":"XXXC","secAttr":"114516","lastAttr":"02" },' +
'{"firstAttr":"XXXC","secAttr":"131417","lastAttr":"03" },' +
'{"firstAttr":"XXXC","secAttr":"1311865","lastAttr":"03" },' +
'{"firstAttr":"XXXC","secAttr":"1314153","lastAttr":"01" },' +
'{"firstAttr":"XXXC","secAttr":"13312163","lastAttr":"01" }]}';
obj = JSON.parse(arrayinput);
document.getElementById("outputid").innerHTML =
obj.collection[1].firstAttr + " " + obj.collection[1].secAttr;
</script>
</body>
</html>
Now the problem is that I don't want to return just one value but multiple ones. For example all entrys with lastAttr=01 should be returned.
Therefore I would need something along the line of:
for(var i in obj) {
if(lastAttr[i]="01") {
document.getElementById("outputid").innerHTML =
obj.collection[i].firstAttr + " " + obj.collection[i].secAttr;
} else {
}
}
Any idea on how to make this work?
If you want to perform a where you need to use Array.prototype.filter:
var filteredArr = arr.collection.filter(function(item) {
return item.lastAttr == "01";
});
And, finally, you can use Array.prototype.forEach to iterate results and perform some action:
var outputElement = document.getElementById("outputid");
filteredArr.forEach(function(item) {
// Check that I used insertAdyacentHtml to be sure that all items
// will be in the UI!
outputElement.insertAdjacentHTML("afterbegin", item.firstAttr + " " + item.secAttr);
});
Also, you can do it fluently:
var arr = {
collection: [{
firstAttr: "hello",
secAttr: "world",
lastAttr: "01"
}, {
firstAttr: "hello 2",
secAttr: "world 2",
lastAttr: "01"
}]
};
var outputElement = document.getElementById("outputid");
var filteredArr = arr.collection.filter(function(item) {
return item.lastAttr == "01";
}).forEach(function(item) {
outputElement.insertAdjacentHTML("afterbegin", item.firstAttr + " " + item.secAttr);
});
<div id="outputid"></div>
You need to iterate over the collection Array and append the new stuff. Right now you're iterating the outer object and overwriting the .innerHTML each time.
var out = document.getElementById("outputid");
for (var i = 0; i < obj.collection.length; i++) {
if(obj.collection[i].lastAttr=="01") {
out.insertAdjacentHTML("beforeend", obj.collection[i].firstAttr + " " + obj.collection[i].secAttr);
}
}
Note that I used == instead of = for the comparison, and .insertAdjacentHTML instead of .innerHTML.
if you want to replace html try this
(someCollection) array;
var r = new Array();
var j = -1;
r[++j] = '<ul class="list-group">';
for (var i in array) {
var d = array[i];
if (d.attribute== somevalue) {
r[++j] = '<li class="list-group-item">'
r[++j]=d.otherattribute;
r[++j] = '</li>';
}
}
r[++j] = '</ul>';
//for(var b in r) //alert to see the entire html code
//{ alert(r[b]);}
firstLoadOnPage = false;
var list = document.getElementById('SymptomSection');
list.innerHTML = r.join('');
this replaces the inside of element with classname "SymptomSection"

Inject variable into function's scope

So, I want to do something like this:
var a = 'a';
var dummy = function() {
// Print out var 'a', from the scope above
console.log('Dummy a: ' + a);
// Print out 'b', from the 'compelled' scope
console.log('Dummy b: ' + b);
}
(function() {
var b = 'otherscope';
// I know apply won't work, I also don't want to merge scopes
dummy.apply(this);
// I want something like this:
dummy.compel(this, [], {b: 'injected!'});
})();
But that won't work.
I don't actually want a function to be able to reach 2 scopes, I DO want to be able to set the 'b' variable used inside the dummy function from the outside.
You can make b a parameter for the function, or a global variable.
var a = 'a';
var dummy = function(b) {
...
}
or
var a = 'a';
var b;
var dummy = function() {
...
}
The first allows you to choose when the dummy function has access to the variable, the second allows it to be accessed everywhere.
So, I found a little faster way to do such a thing:
var C = function(ctx, funcBody){
var newBody = [];
for(var k in ctx){
var i = "var "+k + " = ctx['"+k+"'];";
newBody.push(i);
}
var res = "return function(t){ " +funcBody+ " }";
newBody.push(res);
var F = new Function("ctx", newBody.join('\n'));
return F(ctx);
}
var newFunction = C({"foo":10, "bar":100}, "return foo+bar*t")
newFunction(50);
Use this:
Function.prototype.applyVars = function(scope, params, scope_variables) {
if (scope_variables) {
var variable, defVars = [];
for (variable in scope_variables) {
if (scope_variables.hasOwnProperty(variable)) {
defVars.push(variable + '=scope_variables["' + variable + '"]');
}
}
eval('var ' + defVars.join(',') + ';');
return eval('(' + this + ').apply(scope, params);');
}
return this.apply(scope, params);
}
// Example
function foo(p1) {
document.write('Variable [p1]: ', p1);
document.write('<br />');
document.write('Variable [x]: ', x);
document.write('<br />');
document.write('Variable [y]: ', y);
}
foo.applyVars(this, ['param X'], { x: "1'2\"3", y: false });
Or this:
function callWithVars(fn, scope, params, scope_variables) {
if (scope_variables) {
var variable, defVars = [];
for (variable in scope_variables) {
if (scope_variables.hasOwnProperty(variable)) {
defVars.push(variable + '=scope_variables["' + variable + '"]');
}
}
eval('var ' + defVars.join(',') + ';');
return eval('(' + fn + ').apply(scope, params);');
}
return fn.apply(scope, params);
}
// Example
function foo(p1) {
document.write('Variable [p1]: ', p1);
document.write('<br />');
document.write('Variable [x]: ', x);
document.write('<br />');
document.write('Variable [y]: ', y);
}
callWithVars(foo, this, ['param X'], { x: "1'2\"3", y: false });
the #vasiliy's solution extended to inject any function
function injectScope(ctx, func) {
var newBody = [];
for (var k in ctx) {
var i = " var " + k + " = ctx['" + k + "'];";
newBody.push(i);
}
let res = (func + '').replace(/^(.*?)\)\s*{(.*)$/gms, `return(\n$1){\n${newBody.join('\n')}\n$2)`);
// console.log(res)
let F = new Function("ctx", res);
return F(ctx);
}
function sum(t) {
return foo + bar * t
}
var injectedSum = injectScope({ "foo": 10, "bar": 100 }, sum)
// console.log(injectedSum+'')
console.log(injectedSum(50));

Javascript: Each Array

Note: No jQuery
How could i do something like this:
var array = new Array();
array[name] = "Tom";
array[age] = 15;
foreach(array as key=>value){
alert(key + " = " + value);
}
First of all, you should call it obj or person instead of array; an array is a sequence of similar elements, not a single object.
You can do it like this:
var person = new Object();
person['name'] = "Tom";
person['age'] = 15;
for (var key in person) {
if(!person.hasOwnProperty(key)) continue; //Skip base props like toString
alert(key + " = " + person[key]);
}
You can also initialize the object using properties, like this:
person.name = "Tom";
person.age = 15;
You can also use JavaScript object literal syntax:
var person = { name: "Tom", age: 15 };
This will work in your simple example scenario:
for (var key in array) {
alert(key + " = " + array[key]);
}
For general use, it's recommended that you test to be sure that the property hasn't been grafted onto the object somewhere else in the inheritance chain:
for (var key in array) {
if (array.hasOwnProperty(key)) {
alert(key + " = " + array[key]);
}
}
Use a javascript object
var object = {};
object.name = "Tom";
object.age = 15;
for ( var i in object ) {
console.log(i+' = '+ object[i]);
}
First, you don't want an array, you want an object. PHP's idea of what constitutes an array is frankly a little weird.
var stuff = {
name: "Tom",
age: 15
};
/* Note: you could also have done
var stuff = {};
stuff.name = "Tom";
stuff.age = 15;
// or
var stuff = {};
stuff["name"] = "Tom";
stuff["age"] = 15;
*/
for (var key in stuff) {
alert(key + " = " + stuff[key];
}
key=0;while(key<array.length) {
alert(key + " = " + array.item(key));
key++;
}

Categories