JavaScript: why .forEach doesn't work? - javascript

Here is a little piece of code:
window.addEventListener('load', function() {
['echo'].forEach(function(entity) {
console.log('loaded entity=' + entity)
})
})
console.log(['echo'])
console.log(['echo'].forEach)
['echo'].forEach(function(entity) {
console.log('entity=' + entity)
})
Output looks like this:
["echo"]
function forEach() { [native code] }
Uncaught TypeError: Cannot read property 'echo' of undefined
loaded entity=echo
Why does this error occur? I assume that undefined is this inside .forEach. Why doesn't it get passed when calling .forEach?

SEMICOLONS!
window.addEventListener('load', function() {
['echo'].forEach(function(entity) {
console.log('loaded entity=' + entity);
})
});
console.log(['echo']);
console.log(['echo'].forEach);
['echo'].forEach(function(entity) {
console.log('entity=' + entity);
});
The problem is here:
console.log(['echo'].forEach)
['echo'].forEach(function(entity) {
The line break is ignored, at it gets parsed as this:
console.log(['echo'].forEach)['echo'].forEach(function(entity) {
console.log() returns undefined, and undefined['echo'] raises an exception.
So use semicolons and be happy. Or don't and suffer.

You need to add semi-colons. Your script is being evaluated as:
console.log(['echo'].forEach)['echo'].forEach(function(entity) {
console.log('entity=' + entity)
})
And since console.log returns undefined, you get an uncaught TypeError because you can't access an echo property on undefined.

Javascript can work without semicolons (treating newlines as end of statement), as long as concatenation of following lines is syntactically incorrect & parsing makes no sense.
For eg:
var a=1
var b=2
would work since the semicolon will be added as var a=1 var b=2 doesn't make sense.
Thus it will be treated as var a=1; var b=2. Similarly,
console.log(['echo'].forEach)
['echo'].forEach(function(entity) {
console.log('entity=' + entity)
})
is read as :
console.log(['echo'].forEach)['echo'].forEach(function(entity) {
console.log('entity=' + entity)
})
Here console.log(...) is treated an object with the property 'echo'. Hence the error.

Related

Should I pass an objects as a parameters of a function?

So I have this code:
const failure1 = false;
const failure2 = false;
function callbackFunction(callback, errorCallback) {
if (failure1) {
errorCallback({
name: 'Negative event1 occurred',
message: ':('
})
} else if (failure2) {
errorCallback({
name: 'Negative event2 occurred',
message: ':/'
})
} else {
callback('Mission complete!')
}
}
callbackFunction((message) => {
console.log('Success: ' + message)
}, (error) => {
console.log(error.name + ' ' + error.message)
})
And that looks absolutely awful:
errorCallback({
name: 'Negative event2 occurred',
message: ':/'
})
Is it even ethical to pass an object as a function parameter like that? Because right now, my brain is frying only from looking at it.
How should I read it? Is that an unnamed object (assigned to the errorCallback function - that is a parameter of callbackFunction) with two properties (name and message) that is later assigned to an error parameter of an unnamed function (bottom of code)? Is that correct?
I also heard that this is a really easy piece of code - is that true? Because for me that's super convoluted.
Thank you in advance, for the time spent on an answer.
Passing Object as parameter sometimes actually makes more sense and more easy to read.
Example of a very simple function:
function minus(b,a){
return b-a
}
Usually people will use it as:
minus(1,5)
// Expected : 4, Because the latter number minus the first.
// But, it will return result of -4, without look into the function
// we do not know which number came first.
But if we make it an object:
function minus(param){
return param.b-param.a
}
minus({a:1,b:5})
//Return : 4
//Like this, even if you don't know the content of the function
//you can still assign the correct value without knowing the order.

Cannot read property of undefined in class

I'm new to javascript so can anyone help me figure out why this code is not working?
I have a class and it calls a cordova barcode scanning function. I've got an example that works, however I want to be able to separate out the function(result) and function(error) and use onSuccess(result) and onFailure(error).
I have no idea why this is happening so if anyone can help that would be great.
EDIT: so ive updated the code based on Stradosphere said however im still getting result is not defined errors.
Full error message:
Uncaught ReferenceError: result is not defined at barcodeScanner.scanBarcode (barcodeScanner.js:10) at HTMLButtonElement.myFunction (main.js:18)
var me = this;
class barcodeScanner {
constructor() {
this._barcodeResult = 0;
}
scanBarcode() {
//THIS THROWS result is not defined error
cordova.plugins.barcodeScanner.scan(me.onSuccess(result), me.onFailure(error));
//THIS WORKS
cordova.plugins.barcodeScanner.scan(
function (result) {
me._barcodeResult = result.text;
alert("Barcode Scanned:" + me._barcodeResult);
},
function (error) {
alert("Scanning failed: " + error);
}
);
}
onSuccess(result) {
this._barcodeResult = result.text;
alert("Barcode Scanned:" + this._barcodeResult);
}
onFailure(error) {
alert("Scanning failed: " + error);
}
}
Looking at the docs, it appears that cordova.plugins.barcodeScanner.scan() expects you to pass a function into it. But you are calling it like this:
cordova.plugins.barcodeScanner.scan(me.onSuccess(result), me.onFailure(error));
This is passing the result of the function .onSuccess(result), but result is not defined, so you are getting an error. Additionally, you want this to be the class instance, but by defining me as this outside the class, me won't equal the class instance like you want it to. But you don't need it anyway.
Try passing functions in instead:
cordova.plugins.barcodeScanner.scan((result) => this.onSuccess(result),(error)=> this.onFailure(error))
Maybe a scope issue on your use of this. Try:
var me = this; //(put this at class level)
cordova.plugins.barcodeScanner.scan(me.onSuccess, me.onFailure);

Unable to pass string into a function?

My Javascript code is
function ad_cart(nm, mmi, pr) {
alert(imm);
}
The value i'm passing from onclick is this
onclick="ad_cart(Drafting Factory Folders ,2,3.50)"
But it is showing a error as
SyntaxError: missing ) after argument list
In mozilla
In chrome the error is
Uncaught SyntaxError: Unexpected identifier
But if i pass integer instead of string like
onclick="ad_cart(1,2,3.50)"
then it is working fine
Try like
onclick="ad_cart('Drafting Factory Folders' ,2,3.50);"
And your function will be like
function ad_cart(nm, mmi, pr) {
alert(mmi); // Instead of `imm`
}
function ad_cart(nm, mmi, pr) {
alert(imm);
}
Seems to spell mistake also, getting mmi and showing imm
And the string should be wrap by ''
edit:
function ad_cart(nm, mmi, pr) {
alert(mmi);
}
ad_cart('string' ,number,number)

How to do elegant exception handling while retaining JavaScript debugger capabitilities

You know JavaScript can basically throw any object or even primitive as an exception:
throw 1;
throw { text: "hello" }
Sadly, debuggers like Firefox will log exceptions to console including a link to the code line where the exception was thrown if we throw built-in Error object.
In order to solve that limitation I thought: why don't I override toString and I give an exception instance as argument of Error constructor so exception will be implicitly converted to string?
var ArgumentException = function(args) {
this._argName= args.argName;
}
ArgumentException.prototype = {
_argName: null,
get argName() { return this._argName; },
toString: function() {
return "ArgumentException was thrown. Affected argument: " + this.argName;
}
};
throw Error(new ArgumentException({ argName: "someArgument" }));
Obviously, above code listing is a simplification of a real-world case.
Ok, this works and solve the whole problem.
But this kills the purpose of using exceptions since a try/catch won't be able of handling exceptions by type:
try
{
throw Error(new ArgumentException({ argName: "someArgument" }));
} catch(e) {
if(e instanceof ArgumentException) {
// This will happen never! "e" will hold a Error instance!!!!
}
}
How do you solve this problem? In fact, it's something with Web browser's debugger rather than a problem with actual JavaScript, but as debugging is an important point in any development cycle, it should be took seriously.
Thank you in advance.
EDIT
I want to share my other conclusion:
try
{
debugger;
throw new ArgumentException({ argName: "someArgument" });
} catch(e) {
if(e instanceof ArgumentException) {
}
}
Above solution will log the exception to the debugger console, but it'll stop the debugger before it's ever thrown. Ok, you don't get the link to the exact line but the debugger gets stopped there so you can know where the exception is going to be thrown.
Why not make your exception inherit from Error?
function ArgumentException(data) {
this.name = "ArgumentException";
this.message = arguments.length ? 'Affected argument: ' + data.argName : "Illegal argument";
}
// set up inheritance
ArgumentException.prototype = Object.create(Error.prototype);
ArgumentException.prototype.constructor = ArgumentException;
// use it
try {
throw new ArgumentException({argName: "someArgument"});
} catch(e) {
if(e instanceof ArgumentException) {
console.log(e); // hi there
}
}
// see it normally
throw new ArgumentException({argName: "someOtherArgument"});
// ArgumentException: Affected argument: someOtherArgument
For more, look at Custom Error Types on MDN

chrome exceptions object (nearly) empty

I'm trying to get useful information from the exception object (passed to the a "catch") and it is nearly empty in chrome. I have used it before and was able to get a reasonable stack trace, among other things. Is this a change to chrome, or am I doing something wrong? I'm doing this:
http://jsfiddle.net/R9Wkg/
function pr(s) {
document.body.innerHTML += s.toString() + "<br>";
}
function test() {
try {
var a = b; // err: b not defined
} catch (ex) {
pr('==== print exception object =====');
pr(ex);
pr('======= typeof exception object =====');
pr(typeof ex);
pr('===== members ======');
for (var i in ex) {
pr(' ----- ' + i + " ------");
pr(ex[i]);
}
console.log(ex);
}
}
function first() {
second();
}
function second() {
test();
}
first();
In Chrome it gives me nothing more than the string "ReferenceError: b is not defined" if I do a toString() on the exception object, but if I try to look at the object's individual members, there is nothing there. Notably there is no "stack" member. Then again, if looked at in the console, there is more there (but the stack is simply "-")
That hyphen means it's a getter, and is not automatically executed because it could have side effects. You can log them separately however: http://jsfiddle.net/R9Wkg/1/.
The fact that the error isn't enumberable is filed as an issue at V8's project site.
You can get the members of the error using Object.getOwnPropertyNames(ex) to enumerate them.
pr('===== members ======');
Object.getOwnPropertyNames(ex).forEach(function(i) {
pr(' ----- ' + i + " ------");
pr(ex[i]);
});
http://jsfiddle.net/gilly3/R9Wkg/3/

Categories