Javascript / jQuery + length = problem - javascript

A small version of my script would be this:
var x = null;
for(var i=0; i<x.length; i++)
{
//do stuff
}
I noticed (by doing some 'alert' debugs) that my script halts when evaluating x.length. Even when i try to print it in an alert, the script stops.
The idea is that somethimes my x variable is an array, sometimes is null.
Of course, I am a beginner, so probably i've done something stupid. No errors appear in my Firefox 6 error console.
Thanks a lot for any ideas!

try
var x = null;
for(var i = 0; x && i < x.length; i++) {
//do stuff
}
This will first check whether x is not null. If x is null, for will not run. If it is not null, for will run as usual.

In your code x is null and you are trying to get the length property from a null value which will throw a javascript error. Please check your console you will definitely see an error.
In such situations you should always make sure you do null check before accessing any property of the object or variable. Try this
var x = null;
if(x){
for(var i=0; i<x.length; i++)
{
//do stuff
}
}

That's because it's null. Add this if statement
if (x !== null){
for(var i=0; i<x.length; i++)
{
//do stuff
}
}
and it should be fine.

var x = null;
if(x !== null){
for(var i=0; i<x.length; i++)
{
//do stuff
}
}
Seems to fix the problem

Why don't you initialize x with var x = [];? This way, you can make sure that it is always an array, yet the loop won't do anything if it's empty.

You can't call the method length on a null object.
So you need to test if the object is null before calling it.
var x = null;
if(x != null)
{
for(var i=0; x!= null && i < x.length; i++)
{
//do stuff
}
}
or
var x = null;
for(var i=0;x!= null && i<x.length; i++)
{
//do stuff
}

Another option here would be to initialize x to an object with the length property -
x = {
length : 0
};
instead of
x = null;
EDIT : pulsar's answer makes more sense!

Related

Missing letters freecodecamp

Actually I found an answer a few minutes ago.
But I found something strange.
This is my answer for 'Missing letters' in freeCodeCamp challenges.
function fearNotLetter(str) {
var string;
for (i=0;i<str.length;i++) {
if(str.charCodeAt(i)+1 < str.charCodeAt(i+1)){
string = String.fromCharCode(str.charCodeAt(i)+1);
}
}
return string;
}
When I change < operator in if statement into != (not same), it doesn't work!
For me, it seems that != works exactly same as < operator does.
(Because 'not same' can mean something is bigger than the other.)
What is the difference between < and != in the code above?
Your code has a small defect that works when you use < but not !=.
If you see str.charCodeAt(i+1); this code is checking one spot past the end of the string on the last iteration and will return a NaN result.
If I provide the string "abce" it will check if f is < NaN. I believe NaN can't be compared to f's value so it doesn't go into the if statement. So it will keep the missing letter d that was found in the previous iterations which is stored in your string variable.
However, if you provide the !=, then with the same scenario it knows f != NaN and goes into the if statement. This then overwrite the actual missing letter and fails your FCC test case because it is replacing the missing d with f in your string variable.
To fix your code, simply change the for loop to end one iteration before the length of the string.
for (i = 0; i != str.length-1; i++) {
}
This is my method without using .charCodeAt() function :)
function fearNotLetter(str) {
var ind;
var final = [];
var alf =['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
str = str.split('');
ind = alf.splice(alf.indexOf(str[0]),alf.indexOf(str[str.length-1]));
for(var i=0;i<ind.length;i++){
if(str.indexOf(ind[i]) == -1){
final.push(ind[i]);
}
}
if(final.length != 0){
return final.join('');
}
return;
}
fearNotLetter("bcef");
My solution:
function fearNoLetter(str){
var j= str.charCodeAt(0);
for(var i=str.charCodeAt(0); i<str.charCodeAt(str.length-1); i++){
j = str.charCodeAt(i - str.charCodeAt(0));
if (i != j){
return String.fromCharCode(i);
}
}
}
My solution:
function fearNotLetter(str) {
let y = 0;
for (let i = str.charCodeAt(0); i < str.charCodeAt(str.length - 1); i++) {
if (str.charCodeAt(y) != i) {
return String.fromCharCode(i);
}
y++;
}
return;
}
console.log(fearNotLetter("ace"));
function fearNotLetter(str) {
let alpha = "abcdefghijklmnopqrstuvwxyz";
let alphabet = []
for(let j = 0; j< alpha.length; j++){
alphabet.push(alpha[j])
}
if (alphabet.length == str.length){
let result = undefined;
return result
}else{
const start =alphabet.indexOf(str[0])
let end = (str.length)-1
const stop = alphabet.indexOf(str[end])
const finish = alphabet.slice(start,stop)
let result = finish.filter(item => !finish.includes(item) || !str.includes(item))
result = String(result)
return result
}
return result
}
console.log(fearNotLetter("abcdefghijklmnopqrstuvwxyz"));

Getting html elements in a for loop

This for loop does not run. This simple code is supposed to get all of the H5 elements on the page then get the "innerHTML" but the code never runs the for loop.
function myFunction() {
var x = document.getElementsByTagName("h5").length;
alert(x);
var y;
var z;
for (i = 0; i < x.length; i++) {
y = document.getElementsByTagName("h5")[i];
z = y.innerHTML;
alert(z + " this");
}
}
You're looking for a .length property on x which is itself a length number. I think you mean:
var x = document.getElementsByTagName("h5");
Or of course
for (i = 0; i < x; i++) {
Depending on what you're doing with x afterwards
var x = document.getElementsByTagName("h5").length;
// ...
for (i = 0; i < x.length; i++) {
You're calling .length twice.
The other answers are correct, but here's a little refactoring with some explanations.
function myFunction() {
// Taking out the '.length' means you have a reference to all the h5s
var x = document.getElementsByTagName("h5");
alert(x);
var y;
var z;
//Now since you're not including the .length above, this loop is correct
for (i = 0; i < x.length; i++) {
//You since x is a reference to all the h5s now you don't
//have to search for them again.
y = x[i];
z = y.innerHTML;
alert(z + " this");
}
}
The important part there is just to use one getElementsByTagName call since that's a relatively expensive function. You definitely don't want to call it in a loop if you can avoid it. Generally to write good javascript you want to reuse references to DOM Elements as much as possible since the DOM is much slower than Javascript.

setting fields of an object contained in an array in for-loop in JavaScript

I query a websql database and some of the fields returned have the string-value "undefined".
In a loop, I want to check if the fields have undefined and if so, assign them an empty string as a value.
All works well, except for the assignment. Here's my code:
for (var i = 0; i < result.length; i++) {
for (temp in result[i]) {
if (result[i][temp] == "undefined") {
console.log(typeof(result[i][temp])); // outputs "string" as it should
result[i][temp] = "";
}
}
}
result is an array that contains objects. The code in the if-block is executed except for the assignment, which never takes effect.
What do I need to change?
EDIT:
When I add this immediately after the loop above , it outputs "undefined" for each field that already was undefined before the loop above (hope that makes sense :D).
for (var i = 0; i < result.length; i++) {
for (temp in result[i]) {
if (result[i][temp] == "undefined") {
console.log(result[i][temp]);
}
}
}
I use the whole thing in a callback function, but that shouldnt matter, right? I mean inside a callback function, the code is executed in order just like anywhere else, right?
2nd EDIT:
var arr = [];
arr.push(result[0]); // result currently only holds one object
for (var i = 0; i < arr.length; i++) {
for (temp in arr[i]) {
console.log(arr[i][temp]);
console.log(typeof(arr[i][temp])); // outputs "string" for the undefined fields
if (arr[i][temp] == "undefined") {
arr[i][temp] = "szszsz";
}
}
}
for (var i = 0; i < arr.length; i++) {
for (temp in arr[i]) {
console.log(arr[i][temp]); // still outputs undefined
}
}
ANSWER:
See ArinCool's comment: I copied the array into another array and then I was able to overwrite the fields.

Why does this for loop not run? jQuery

http://jsfiddle.net/leongaban/BvuT5/
Trying to get the 2nd alert to popup twice, however seems like the for loop isn't even running.
jQuery
var wireRequestorCard = function(jarjar) {
alert('1st alert');
var loop_num = 0;
for (var i = 0, length = jarjar.length; i < length; i++) {
loop_num = i;
alert('Where is this Alert? '+i);
}
alert('Closing Alert');
}
var jarjar = 2;
wireRequestorCard(jarjar);
You aren't passing an array or string to the function, which does not have a length property. Instead jarjar is a number.
jarjar is an integer.
it does not have a length property.
You just need to compare i to jarjar:
for (var i = 0; i < jarjar; i++) {
alert('Here is this Alert! '+i);
}
http://jsfiddle.net/daCrosby/BvuT5/5/

Get minimum and maximum of object property names that are integers

UPDATED (formulated the problem wrong, see note below)
I have an object that has a set of properties that are named with numbers as shown in the example. The 'numbered names' are not necessarily consecutive, nor do I know where they start or end. I do know that other properties will not be named with numbers.
I know that myObject["propName"] is the same as myObject.propName, but I deliberately write it in the first way because myObject.0 looks weird and doesn't get recognized by all editors.
How do I get the min- and maximum array index?
So in a situation like this
myObject["0"] = undefined
myObject["1"] = {}
myObject["2"] = undefined
myObject["3"] = {}
myObject["4"] = {}
myObject["5"] = undefined
myObject["someOtherProperty"] = {}
would give me this
minIndex(myObject) == 1
maxIndex(myObject) == 4
To all the answers before this edit
Thanks for your replies. I shouldn't have posted this question in a hurry and should have re-read it before committing. It was late and I was in a hurry. My apologies.
By actually seeing my wrong statement (using an array instead of an object) I think that, based on answers for my reformulated problem, I might need to rewrite my code to use an array instead of an object. The reason I'm using an object rather then an array is material for another question.
Efforts so far
I have tried finding a way of converting the property names to an array and then looping through them, but that has proven cludgy. I'm kind of looking for a less error-prone and elegant way.
Edit: Aha! Now the problem becomes more interesting.
Solution 1: Let's solve this in one shot, shall we? For max:
function maxIndex(obj){
var max = -1;
for(var i in myObject){
var val = parseInt(i);
if(isFinite(val)){
if(typeof obj[val] !== 'undefined' && val > max){
max = val;
}
}
}
return max;
}
I think you can convert this to min on your own ;)
Solution 2: Here I'll your object back into what we originally thought it was, in case you really loved one of the other solutions. Then the rest of the answer applies.
function convertObject(obj){
var output = [];
for(var i in myObject){
var val = parseInt(i);
if(isFinite(val)){
output[val] = obj[i]; //Gotta love JS
}
}
return output;
}
Continue as planned!
To find the smallest, begin at the bottom and work your way up until you find it.
function minIndex(myArray){
for(var i = 0; i < myArray.length; i++){
if(typeof myArray[i] !== 'undefined')
return i;
}
}
To get the biggest, start at the top.
function maxIndex(myArray){
for(var i = myArray.length - 1; i >= 0; i--){
if(typeof myArray[i] !== 'undefined')
return i;
}
}
Both are worst case O(n). You can't really do better because the whole array could be empty, and you'd have to check every element to be positive.
Edit: As is mentioned, you can also check if something is not undefined by simply writing if(myArray[i]). Whatever suits your fancy.
var myObject = {};
myObject["0"] = undefined;
myObject["1"] = {};
myObject["2"] = undefined;
myObject["3"] = {};
myObject["4"] = {};
myObject["5"] = undefined;
myObject["someOtherProperty"] = {};
var keys = Object.keys(myObject).map(Number).filter(function(a){
return isFinite(a) && myObject[a];
});
var min = Math.min.apply(Math, keys);
var max = Math.max.apply(Math, keys);
console.log(min, max); //Logs 1 and 4
Documentation and compatibility information for all:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/filter
Try looping through the array until you find the 1st non-undefined element.
function minIndex(arr){
for(var i = 0, len = arr.length; i < len; i++){
if(arr[i] !== undefined){
return i;
}
}
}
For max index, do the same thing, except in reverse.
function maxIndex(arr){
for(var i = arr.length-1, len = 0; i >= len; i--){
if(arr[i] !== undefined){
return i;
}
}
}
Min:
for(var i = 0; i < myArray.length; i++) {
if(myArray[i] != undefined) {
return i;
}
}
Max:
for(var i = myArray.length-1; i >= 0; i--) {
if(myArray[i] != undefined) {
return i;
}
}
try something like this:
function minIndex(var array){
for(var i = 0; i < array.length; i++)
{
if(typeof array[i] != "undefined")
return i;
}
return null;
}
function maxIndex(var array){
var returnIndex = -1;
for(var i = 0; i < array.length; i++)
{
if(typeof array[i] != "undefined")
returnIndex = i;
}
if(returnIndex !== -1) return returnIndex;
else return null;
}
this takes advantage of the fact that for..in only iterates over defined elements, and uses the index:
function minIndex(arr){ for(el in arr){return el} }
function maxIndex(arr){var v; for(el in arr){v = el}; return v }
CAVEATS:
The second function is not very efficient though, since it loops through the entire array.
This wont work if you are EXPLICITLY setting the undefined indexes.
var max=0;
var min=myArray.length;
for (var i in myArray)
if (myArray[i]!==undefined)
{
max=Math.max(i, max);
min=Math.min(i, min);
}

Categories