I'm trying to format any kind of variables to achieve some kind of toString() method.
It's working for pretty complex objects and arrays, handling circular references, but when I try to call it on a jQuery object: format($("body")), for testing it on large complex objects, I got this error:
Unhandled exception at line 330, column 21 in ms-appx://8b94d51c-586e-4f3f-bb9c-fa75d62508cd/js/default.js
0x80004005 - Erreur d’exécution JavaScript: Erreur non spécifiée.
0x80004005 - JavaScript Run-time Error: Unspecified error. // I translated it for you
Here is my code (with a // ERROR! comment next to the line 330):
function format(arg, parents, indent) {
var maxParent = 25;
if (parents === undefined) {
parents = [];
}
if (indent === undefined) {
indent = 1;
}
if (contains(parents, arg)) {
return '<span class="brackets">[Circular]</span>';
}
if (typeof arg === 'string' && parents.length > 0) {
return '"' + htmlEntities(arg) + '"';
} else if (Array.isArray(arg)) {
parents.push(arg);
if (parents.length >= maxParent) {
return '<span class="brackets">[Array]</span>';
}
var ret = "[ ";
for (var i = 0, len = arg.length; i < len; i++) {
if (i !== 0) {
ret += ", ";
}
ret += "<br>";
ret += addIndent(indent);
ret += format(arg[i], parents, indent + 1);
}
ret += "<br>";
ret += addIndent(indent - 1);
ret += " ]";
return ret;
} else if (arg === null) {
return '<span class="void">null</span>';
} else if (arg === void 0) {
return '<span class="void">undefined</span>';
} else if (typeof arg === 'number' && (isNaN(arg) || !isFinite(arg))) {
return '<span class="void">' + arg.toString() + '</span>';
} else if (typeof arg === 'object' && arg !== null) {
if (parents.length >= maxParent) {
return '<span class="brackets">[Object]</span>';
} else {
parents.push(arg);
}
var ret = "{";
var first = true;
for (var key in arg) {
if (!first) {
ret += ", ";
}
else {
first = false;
}
ret += "<br>";
ret += addIndent(indent);
ret += key;
ret += ": ";
if (typeof arg[key] === 'function') {
ret += '<span class="brackets">[Function]</span>';
} else {
ret += format(arg[key], parents, indent + 1); // ERROR!
}
}
ret += "<br>";
ret += addIndent(indent - 1);
ret += "}";
remove(parents, arg);
return ret;
}
return arg;
}
Do you have any ideas why this error is occuring?
What can I do to fix it?
Out of the top of my head I can think that arg[key] is null by the time you call the format function. Synchronize the if statement so it executes only after arg[key] is not null.
Related
I feel like I am failing everything this semester. but I was wondering if you all could help me with a JS project. We have been tasked with essentially converting numbers to letters and vica versa using textareas in HTML. I was able to do the numbers to letters function, but am having difficulties going the other way. what I have for all is:
var $ = function(id) {
return document.getElementById(id);
};
window.onload = function() {
$("btnDecode").onclick = fnDecode;
$("btnEncode").onclick = fnEncode;
$("btnClear").onclick = fnClear;
};
function fnDecode() {
var msg = $("textin").value;
if (msg === "") {
$("textin_span").innerHTML = "* Please enter a message to decode *";
$("textin").focus;
return;
} else {
$("textin_span").innerHTML = "";
}
var nums = msg.split(",");
var outstr = "";
for(var i=0; i < nums.length; i++) {
var n2 = parseInt(nums[i]);
if (isNaN(n2)) {
outstr += "?";
} else if (isNallN(nums[i])) {
} else if (n2 === 0) {
outstr += " ";
} else if (n2 < 1 || n2 > 26) {
outstr += "?";
} else {
outstr += String.fromCharCode(n2+64);
}
$("textout").value = outstr;
}
}
function isNallN(s) {
//parse string to check all characters are digits
}
function fnEncode() {
var msg = $("textin").value.toUpperCase();
$("textin").value = msg;
if (msg === "") {
$("textin_span").innerHTML = "* Please enter numberse to decode *";
$("textin").focus;
return;
} else {
$("textin_span").innerHTML = "";
}
var c;
var outstr = "";
for (var i=0; i<msg.length; i++);
c = msg.charCodeAt(i);
if (typeof c === "number") {
outstr += "99";
}else if (c === " ") {
outstr += 0;
/*} else if (c[i] >= "A" && c[i] <= "Z") {
outstr += "99";*/
} else {
outstr += String.charCodeAt(c - 64);
}
$("textout").value = outstr;
//var x = msg.charAT(i);
}
obviously isNallN is not complete, but he promised us if we could figure out fnEncode we should be able to do isNallN with no issues (which I am hoping is true lol) What am doing wrong though in fnEncode? Every time I run it, it gives me "99" even when I put letters in.
I Loop through a complex JSON object but I want to stop the loop after n iterations
n = 0;
maxIterations = 100;
ObjectValues = function(v, k){
if(n == maxIterations){
if (typeof v == "object") {
for (var kp in v) {
if (Object.hasOwnProperty.call(v, kp)) {
ObjectValues(v[kp], k != undefined ? k + "." + kp : kp);
}
}
} else {
console.log(k + ":" + v);
n++;
}
}else{
console.log('I should end the function');
return false;
}
};
But I can't exit the function with return false. The function gets called, even after I tried to exit it with return false.
As I understand it, you want to recursively print maxiteration keys and their values:
n = 0;
maxIterations = 100;
ObjectValues = function(v, k){
if(n < maxIterations){
if (typeof v == "object") {
for (var kp in v) {
if (Object.hasOwnProperty.call(v, kp)) {
if(! ObjectValues(v[kp], k != undefined ? k + "." + kp : kp) )
return false;
}
}
} else {
console.log(k + ":" + v);
n++;
}
return true;
} else {
console.log('I should end the function');
return false;
}
};
I inherited a javascript code base and I am new to javascript. So i am using JSHint to avoid common mistakes, misuses.
JSHint has found this piece of code but i do not know how to avoid the evil eval:
function GetProperties(object) {
var result, property, t;
result = '';
for (property in object) {
if (property.indexOf('Get', 0) === 0) {
t = object[property] + "...";
eval("if (GetNumOfParameter(t) == 0) var m = object." + property + "(); else var m = -100;");
if (window.m != -100) {
result += property + ': ' + window.m + '\r\n';
}
}
}
return result;
}
Use the following, it's far better, you don't need to use m if you don't use it anywhere else.
function GetProperties(object) {
var result, property, t;
result = '';
for (property in object) {
if (property.indexOf('Get', 0) === 0) {
t = object[property] + "...";
if (GetNumOfParameter(t) == 0)
result += property + ': ' + object[property]() + '\r\n';
}
}
return result;
}
Every time I pass an array to this function, when it hits a null or undefined value it stops the loop. I can't work out how to fix this. When I ask whether the current item in the loop is null or undefined or false, it doesn't answer...
function xul(func, loc, arr){
var elem;
var props = {};
for (var i = 0, len = arr.length; i < len; i++){
if (arr[i] == undefined) {
jsdump("undefined" + " - " + len);
}
else if (arr[i] == null) {
jsdump("null" + " - " + len);
}
else if (arr[i] == false) {
jsdump("false" + " - " + len);
}
else if (typeof arr[i] == "string"){
elem = arr[i];
if (typeOf(arr[i + 1]) == "object") {
props = arr[i+1];
i++;
}
loc = createNode(func, loc, elem, props);
}
if (typeOf(arr[i + 1]) == "array") {
xul("append", loc, arr[i+1]);
} else {
return loc;
}
}
}
What is going on here?
Actually the loop stops here (if you return something you exit the loop!):
if (typeOf(arr[i + 1]) == "array") {
xul("append", loc, arr[i+1]);
} else {
return loc;
}
if the next element it's not an array it returns loc and the loop stops. check this fiddle: http://jsfiddle.net/g8SVJ/ it logs two undefined and then returns loc
You should also use === instead of ==
AddPatient = {};
if(GenderValue === undefined) {
AddPatient.Gender = ' ';
} else {
AddPatient.Gender = GenderValue;
}
if(DateOfBirthValue === undefined) {
AddPatient.DateOfBirth = ' ';
} else {
AddPatient.DateOfBirth = DateOfBirthValue;
}
if(SSNValue === undefined) {
AddPatient.SSN = ' ';
} else {
AddPatient.SSN = SSNValue;
}
if(RaceValue === undefined) {
AddPatient.Race = ' ';
} else {
AddPatient.Race = RaceValue;
}
if(ReligionValue === undefined) {
AddPatient.Religion = ' ';
} else {
AddPatient.Religion = ReligionValue;
}
if(CellPhoneValue === undefined) {
AddPatient.CellPhoneNumber1 = ' ';
} else {
AddPatient.CellPhoneNumber1 = CellPhoneValue;
}
if(HomePhoneValue === undefined) {
AddPatient.phonenumber1 = ' ';
} else {
AddPatient.phonenumber1 = HomePhoneValue;
}
if(PrimaryPhoneValue === undefined) {
AddPatient.PrimaryPhoneNumber = ' ';
} else {
AddPatient.PrimaryPhoneNumber = PrimaryPhoneValue;
}
if(EmailValue === undefined) {
AddPatient.EmailAddress1 = ' ';
} else {
AddPatient.EmailAddress1 = EmailValue;
}
AddPatient.ResidentialAddress = {};
if(AddressValue === undefined) {
AddPatient.AddressLine1 = ' ';
} else {
AddPatient.ResidentialAddress.AddressLine1 = AddressValue;
}
if(CityValue === undefined) {
AddPatient.City = ' ';
} else {
AddPatient.ResidentialAddress.City = CityValue;
}
if(StateValue === undefined) {
AddPatient.State = ' ';
} else {
AddPatient.ResidentialAddress.State = StateValue;
}
if(ZipValue === undefined) {
AddPatient.PostalCode = ' ';
} else {
AddPatient.ResidentialAddress.PostalCode = ZipValue;
}
Is there any better way to write the same code?
You can write
AddPatient.Gender = GenderValue || " ";
The || operator returns the left-most "truthy" operand, so this will evaluate to " " if GenderValue is "falsy" (such as undefined, false, "", 0, or null)
function isDefined(value){
if(value != null)
return value;
else
return ' ';
}
AddPatient = {};
AddPatient.Gender =isDefined(AddPatient);
and son on
Here is a suggestion to what you actually asked:
http://jsfiddle.net/mplungjan/b5yRw/
It will of course work with a form instead.
var GenderValue = "F";
var DateOfBirthValue; // undefined
var AddressValue = "some street";
// var CityValue; // undeclared
function addItem(obj,varName) {
obj[varName] = window.hasOwnProperty(varName+"Value")?window[varName+"Value"]||"not set":"not declared";
}
function addItemLoop(obj) {
for (var o in obj) {
if (typeof obj[o] === 'object') {
addItemLoop(obj[o]);
}
else {
addItem(obj, o);
}
}
}
AddPatient = {
Gender : " ",
DateOfBirth: " ",
ResidentialAddress : {
Address:" ",
City: " "
}
}
addItemLoop(AddPatient);
document.write("<br/>Gender (F):"+AddPatient.Gender);
document.write("<br/>DOB (not set):"+AddPatient.DateOfBirth);
document.write("<br/>ResidentialAddress Address (some street):"+AddPatient.ResidentialAddress.Address);
document.write("<br/>ResidentialAddress City (not declared):"+AddPatient.ResidentialAddress.City);
Previous answer
Not better but shorter using the ternary operator
AddPatient.Gender = (GenderValue === undefined)? " ":GenderValue;
or shortcut
AddPatient.Gender = GenderValue || " ";
Note - In the shortcut you WILL get a space if value is 0
In EITHER you will get an error if GenderValue has not been declared.
So somewhere you need a var GenderValue;
Example:
var b="hello", c;
var a = {}
a.x = b||"no b"
a.y = (c===undefined)? "no c here":c
a.z = c || "no c here either"
alert(a.x)
alert(a.y)
alert(a.z)
Here's one option:
function SetOrDefault(value, property) {
if (typeof(value) == 'undefined' || value == null) {
property = ' ';
}
else {
property = value;
}
}
And then call it like this:
SetOrDefault(GenderValue, AddPatient.Gender);