Traversing within javascript object in for loop - javascript

I want to refer to an object within the object itself. The following is not right, i know. But what is the right way?
And when googling for such problems, what would be the right keywords to search for?
for (var key in eName) {
var obj = eName[key];
eName[key] = {
type: 'id',
name: obj.substr(1),
html: this.type + '="' + this.name +'"' //<--- here
}
}

Try using the JS equivalent for class instead:
for (var key in eName) {
var obj = eName[key];
eName[key] = new CustomElement(obj);
}
...
function CustomElement(strData) {
this.type = "id";
this.name = strData.substr(1);
this.html = this.type + '="' + this.name +'"';
}

The this keyword for Javascript might help you understand what this really means. You might have to pass it in as an object to the function.

Try this:
for (var key in eName) {
var obj = eName[key];
eName[key] = {
type: 'id',
name: obj.substr(1),
html: '' //<--- here
}
eName[key].html = eName[key].type + '="' + eName[key].name +'"'
}

for (var key in eName) {
var obj = eName[key];
eName[key] = {
type: 'id',
name: obj.substr(1),
html: function() { return this.type + '="' + this.name +'"' }
}
}
Then you would use eName[key].html()

Related

Cannot read property of undefined of function inside loop

I have the "error: Cannot read property 'shorten' of undefined" error when running my test. I want my loop to run the shorten function to check if the string is longer then 20 characters, and if so limit it to that.
function ListView(list) {
this.list = list;
this.converted;
}
ListView.prototype.convert = function() {
var output = [];
this.list.notelist.forEach(function(element) {
this.shorten(element);
output += "<li><div>" + element.text + "</div></li>";
});
this.converted = "<ul>" + output + "</ul>";
};
ListView.prototype.shorten = function(string) {
if (string.length > 20) {
return string.substring(0, 20);
}
return string;
};
list is from another constructor but i mocked it with;
var mockList = { notelist: [{ text: "hello" }, { text: "goodbye" }] };
There are serveral problems with your code:
You encountered the what is this problem which is a very common problem with beginners, have a look at this link. In the anonymous function body of function (element) { .. it doesn't obtain the context of your custom type, thus this is a reference to your browser window.
Your shorten method is called with a different usage in its semantics. You did not take what it returns, but element is not modified at all with the method.
So, let's try to correct the code for what you attempt to do:
<script>
function ListView(list) {
this.list = list;
this.converted;
}
ListView.prototype.convert = function () {
var output = [];
var that = this;
this.list.notelist.forEach(function (element) {
that.shorten(element);
output += "<li><div>" + element.text + "</div></li>";
});
this.converted = "<ul>" + output + "</ul>";
};
ListView.prototype.shorten = function (el) {
var string = el.text;
if (string.length > 20) {
el.text = string.substring(0, 20);
}
};
var mockList = { notelist: [{ text: "hello" }, { text: "goodbye0123456789012345" }] };
var listview1 = new ListView(mockList);
listview1.convert();
alert(listview1.converted);
</script>
goodbye0123456789012345 is modified intentionally for the test, in the result it will be shorten as goodbye0123456789012.
You lost the this binding in the forEach
Try:
ListView.prototype.convert = function() {
var output = [];
this.list.notelist.forEach(function(element) {
this.shorten(element);
output += "<li><div>" + element.text + "</div></li>";
}.bind(this));
this.converted = "<ul>" + output + "</ul>";
};
or
this.list.notelist.forEach((element) => {
this.shorten(element);
output += "<li><div>" + element.text + "</div></li>";
});
Similar to: Passing scope to forEach
Try by binding this
this.list.notelist.forEach(function(element) {
this.shorten(element);
output += "<li><div>" + element.text + "</div></li>";
}.bind(this));
You can use an ES6 arrow function in this case to ensure that this is maintained within your function.
this.list.notelist.forEach((element) => {
this.shorten(element);
output += "<li><div>" + element.text + "</div></li>";
});
Remember to check the availability of arrow functions on browsers. If you want a more widely supported solution use the bind function like others have mentioned.
forEach accepts a second argument which is the thisArg, by default it is undefined.
Try this:
this.list.notelist.forEach(function(element) {
this.shorten(element);
output += "<li><div>" + element.text + "</div></li>";
}, this); // <-- note the `this` argument passed here

How can iterate over JSON object and print its properties and their values?

I want to navigate each property in the JSON below in JavaScript. The below JSON contains two records for reference but in real time will have numerous such records.
{"Record_0":[{"Status":"CREATED","CreatorLoginId":"sandhya","Name":"G1"}],"Record_1":[{"Status":"CREATED","CreatorLoginId":"San","Name":"G2"}]}
I want to get the values of the fields "Status", "CreatorLoginId" and "Name" to assign them to something else.
How should I do it?
var myJSON = JSON.parse('{"Record_0":[{"Status":"CREATED","CreatorLoginId":"sandhya","Name":"G1"}],"Record_1":[{"Status":"CREATED","CreatorLoginId":"San","Name":"G2"}]}');
for(var pr in myJSON)
{
console.log(myJSON[pr][0].Status);
console.log(myJSON[pr][0].CreatorLoginId);
console.log(myJSON[pr][0].Name);
}
Print how? If you mean output to the js console it would be
for (index in object) {
console.log(index + ': ' + object[index]);
}
If you mean add it to a web page, just replace console.log with a little markup:
var parent = document.getElementById('parentID');
for (index in object) {
parent.innerHTML += index + ': ' + object[index] + '<br>';
}
For nested objects (including arrays)
function print(object, parent) {
for (index in object) {
if (typeof object[index] == 'object') {
print(object[index});
}
parent.innerHTML += index + ': ' + object[index] + '<br>';
}
}
EDIT: don't forget to JSON.parse(): the string first before iterating
//Iterating through the groups
for (var currentRecord in groupInformation)
{
store.data.items.push({serial: {}, groupName: {}, createdBy: {}, status: {} });
store.data.items[iNoOfGroups].serial = iNoOfGroups + 1;
store.data.items[iNoOfGroups].groupName = groupInformation[currentRecord][0].Name;
store.data.items[iNoOfGroups].createdBy = groupInformation[currentRecord][0].CreatorLoginId;
store.data.items[iNoOfGroups].status = groupInformation[currentRecord][0].Status;
iNoOfGroups++;
}
var myJSON = JSON.parse('{"Record_0":[{"Status":"CREATED","CreatorLoginId":"sandhya","Name":"G1"}],"Record_1":[{"Status":"CREATED","CreatorLoginId":"San","Name":"G2"}]}');
for(var key in myJSON){
console.log(myJSON[key][0].Status);
console.log(myJSON[key][0].CreatorLoginId);
console.log(myJSON[key][0].Name);
}`

Iterating through array and not all items are showing

See the example here - http://jsfiddle.net/jayblanchard/b2y1tagk/
With the following code I would think that I would get all three elements appended to result, but I don't. I get:
primary - bar
secondary - glorp
var elements = [{
type: 'secondary',
name: 'foo'
}, {
type: 'primary',
name: "bar"
}, {
type: 'secondary',
name: "glorp"
}];
var elementItem;
$(elements).each(function () {
if (this.type == 'primary') {
elementItem = this.type + ' - ' + this.name + '<br />';
} else {
elementItem += this.type + ' - ' + this.name + '<br />';
}
});
$('#results').append(elementItem);
So I'm thinking that I should add the += operator to the first portion of the if condition, but when I do I get this:
undefinedsecondary - foo
primary - bar
secondary - glorp
It doesn't matter what order these are in when they are generated, they just all have to be there when complete. I feel sure that I am missing something obvious, can someone tell me what that is?
elementItem = this.type + ' - ' + this.name + '<br />';
needs to be:
elementItem = this.type + ' - ' + this.name + '<br />' + elementItem;
Otherwise, you overwrite it if primary is not the first item.
Initialize it with var elementItem = ""; so it doesn't typecast elementItem to the string "undefined"
http://jsfiddle.net/b2y1tagk/3/
You are resetting your elementItem variable with = when you reach the primary type. Try appending every item in your list. Initialize the elementItem by var elementItem=''.
var elements = [{
type: 'secondary',
name: 'foo'
}, {
type: 'primary',
name: "bar"
}, {
type: 'secondary',
name: "glorp"
}];
var elementItem = '';
$(elements).each(function () {
if (this.type == 'primary') {
elementItem += this.type + ' - ' + this.name + '<br />';
} else {
elementItem += this.type + ' - ' + this.name + '<br />';
}
});
$('#results').append(elementItem);

JavaScript inheritance using prototype

I've been programming for over 20 years, but have recently turned to JavaScript. Despite spending hours trawling the web, the penny hasn't yet dropped with the prototype inheritance method.
In the simplified code below, I am trying to inherit the 'name' property from the Synthesizer 'class' to the Roland 'class', but the only way I seem to be able to access it is by using 'Synth2.prototype.name' rather than by 'Synth2.name' (which returns undefined). I would like to get the approach working so that I can use 'Synth2.name', as portability is a design requirement.
I would be very grateful for any assistance.
function Synthesizer(name) {
this.name = name;
}
function Roland(name) {
this.prototype = new Synthesizer(name);
}
Synth1 = new Synthesizer("Analogue");
Synth2 = new Roland("Fantom G6");
document.write(Synth1.name + '<br>');
document.write(Synth2.name + '<br>');
Thanks guys! (Now updated with call to super class)...
function Synthesizer(name) {
this.name = name;
this.rendersound = function () {
document.write("applying envelope to " + this.name + "<br>");
}
}
function Roland(name) {
Synthesizer.call(this, name);
this.prototype = Synthesizer;
this.Synthesizer_rendersound = this.rendersound;
this.rendersound = function () {
document.write("applying differential interpolation to " + this.name + "<br>");
this.Synthesizer_rendersound(this);
}
}
Synth1 = new Synthesizer("Analogue");
Synth2 = new Roland("Fantom G6");
document.write(Synth1.name + '<br>');
document.write(Synth2.name + '<br>');
document.write('<br>');
Synth1.rendersound();
document.write('<br>');
Synth2.rendersound();
document.write('<br>');
document.write('Synth1.prototype ' + Synth1.prototype + '<br>');
document.write('Synth2.prototype ' + Synth2.prototype + '<br>');
document.write('<br>');
document.write('Synth1.constructor ' + Synth1.constructor + '<br>');
document.write('Synth2.constructor ' + Synth2.constructor + '<br>');
You can do this by several way.
For example :
var Synthesizer = function(name){
this.name = name;
}
function Roland(name) {
Synthesizer.call(this, name); // you call the constructor of Synthesizer
// and force Synthesizer's this to be Roland's this
}
function clone(obj){
var ret = {};
for(var i in obj){ ret[i] = obj[i]; }
return ret;
}
Roland.prototype = clone(Synthesizer.prototype); // inheritance of public functions
For Function.prototype.call : https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/Call
I believe you have to set the constructor's prototype, like this:
function Synthesizer(name) {
this.name = name;
}
function Roland(name) {
this.name = name;
}
Roland.prototype = new Synthesizer();
Synth1 = new Synthesizer("Analogue");
Synth2 = new Roland("Fantom G6");
document.write(Synth1.name + '<br>');
document.write(Synth2.name + '<br>');

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