Strange && operator behaviour in node.js - javascript

My node application just spat out this error, which I don't understand:
trendData && trendData.forEach(function(trendDataItem){
^
TypeError: Object Error: HTTP Error undefined: undefined has no method 'forEach'
at /home/myapp/node/dataSource/enabled/twitterTrending.js:9:36
The && operator should be preventing any undefined values of trendData reaching the second part of the expression, but it seems not to have worked. My understanding of node.js is that my code doesn't have to concern itself with multi-threading issues, so I assume there's no chance that the value of trendData changed between the evaluation of the first part of the expression and the second.
The trendData value is passed in from a callback made by a twitter library, source code here, the line that is failing is inside the 'callback' function, from what I can see it should be the result of JSON.parse if everything worked, otherwise it will contain failure information.
Anybody have a clue what's going on?

Your understanding is correct, which means in this case trendData isn't undefined or some other falsy value, but instead is an object which doesn't have a forEach method. Based on the limited snippet provided trendData is a string containing an error message rather than the array you are expecting.

Related

Why doesn't undefined?.fun() throw an error?

I was very surprised to see the following behavior in Node 14.18.0:
> {}?.fun();
Uncaught TypeError: b?.fun is not a function
> undefined?.fun();
undefined
I understand why the first statement throws a TypeError. {}?.fun is undefined, which is not callable. But undefined?.fun is also undefined, so why can it be called without throwing? What part of the ECMAScript specification defines this behavior? Did the ECMAScript working group provide any reasons why it should work this way?
During optional chaining, if the current value within the chain is null or undefined, the expression short-circuits with a return value of undefined.
This is in the official docs:
The ?. operator is like the . chaining operator, except that instead of causing an error if a reference is nullish (null or undefined), the expression short-circuits with a return value of undefined. When used with function calls, it returns undefined if the given function does not exist.
Since {} is an actual object—without a method called fun()—it blows up, because you called a function that did not exist.
To fix your issue, you will need to call the function with optional chaining:
console.log(({})?.fun?.()); // undefined
the work of? and say that possibly the value is undefined
normally used like this in typescript
console.log(myobj?.value ?? 'does not exist');
in javascript "?" it's useless
"?" doesn't do anything, it just signals that the value can be undefined, so when you put an object, it returns an error because this property doesn't exist in your object, whereas in undefined javascript it just ignores everything

Checking for null or undefined VS handling errors VS returning bogus in JS

similar question in Java: Java: check for null or allow exception handling
related:How to deep check for "null" or "undefined" with JS?
assuming a.foo() is a well-tested function that returns either
undefined or an object with a function such as {bar:()=>log('baz')},
hence, it would seem logical to write
a.foo().bar()
which obviously won't work.
(the undefined is the result of an empty return; when no information can be delivered)
Should
1. The operation be tried,
try{a.foo().bar();}catch(e){}
2. a new variable be declared
const u = a.foo();
if(u) u.bar();
3. or foo() return {bar:()=>{}} instead of undefined?
so that
a.foo().bar();
can be written normally?
what is the industry standard? what is fastest?
As already commented, this is a personal opinion and I would also stick to it that most people would try to avoid the try-catch story...
But anyway I wanted to add that you can also simply check:
a.foo() && a.foo().bar()
in case a.foo() will return undefined, then the right side wont be executed and thus this expression return undefined.
On the other side, if a.foo() is not undefined than the right side will be executed and this expression will evaluate to the result of a.foo().bar()

Why does assigning to `NaN` or `undefined` cause a TypeError?

A.S.: The question is about type of error, not about the phenomenon
"use strict" throws TypeError if system variables like NaN and undefined got changed.
But why is it a TypeError? Why not SyntaxError?
Edit: Really, it is not the SyntaxError here since there are no errors in syntax of the snippet.
But the root of the error lies in the fact, that some protected object cannot be changed manually; so, it is lkely the AccessError (there are no such, I know).
Then, why access-errors appear like type-ones?
In ES5, there are 6 different kinds of native errors:
EvalError
This exception is not currently used within this specification. This
object remains for compatibility with previous editions of this
specification.
RangeError
Indicates a numeric value has exceeded the allowable range.
ReferenceError
Indicate that an invalid reference value has been detected.
SyntaxError
Indicates that a parsing error has occurred.
TypeError
Indicates the actual type of an operand is different than the expected
type.
URIError
Indicates that one of the global URI handling functions was used in a
way that is incompatible with its definition.
In your case, the error is thrown because you attempt to assign a value to window.NaN or window.undefined, which are non-writable properties.
Before assigning the new value, the internal [[Put]] method checks [[CanPut]], which will return false because the property is non-enumerable. And therefore [[Put]] will throw.
So the problem is that the writability of the assigned reference (left operand in the assignment expression) is not the expected one. Then, among the 6 error kinds above, the most appropriate seems TypeError, even if writability is not exactly a type.
Because NaN and undefined are just read only properties of window. They are not operators (like > or +), or keywords (like var or class).
Trying to assign something to NaN gives the following error in Chrome:
TypeError: Cannot assign to read only property 'NaN' of object '#<Window>'
Because it's a valid argument that does not make sense. But it does not make sense in the SEMANTIC level, not the syntactic.
Here's an example:
1+1=42
This is wrong, but it's wrong in a different way than, say:
42 1 1 + =
You can read the first one as an arithmetic equation (one plus one equals forty-two). The second one, you can't even read.
The same goes here. the statement NaN=300; can be read in Javascript as "have NaN point to the value 300`. But when the parser submit this request to the engine, the engine goes "Nope, can't do this".
syntax error
In most programming & scripting languages this generally means that you've used an operator in the wrong place.
For more info on "syntax errors", have a look at this article: https://en.wikipedia.org/wiki/Syntax_error
type error
These occur when a data-type miss-matches some requirement.
For more information on "data-types", have a look at this article: https://en.wikipedia.org/wiki/Data_type
So, the type error is thrown because NaN and undefined are "data-types", which are global constants with a specific (designated) value, and "strict mode" prevents issues by not allowing to change these.

Weird JS syntax: math operator in function declaration

I just played with Twitter API and found very weird construction. It's division operator between function name and arguments passing.
c/({"count":8098,"url":"http:\/\/example.com\/"});
I supposed that this should throw parser exception, but it works − just returning NaN instead of undefined. Also it works similar with * and - operators, while + returns c.toString() (or .valueOf, I dunno).
Even more, it's really syntax error thrown if i don't pass object to function. Here's examples:
function c() {}
>> undefined
c
>> function c() {}
c/()
>> SyntaxError: Unexpected token )
c/({});
>> NaN
c+({})
>> "function c() {}[object Object]"
c({})
>> undefined
I ran this in Chrome, but I belive it works everywhere if Twitter put it in response.
So. Why this even work, and how it works exactly? I believe this somehow releated to function returning value and its implicit type coercion, but I still don't get it.
Your URL is not escaped in that API call so twitter reads it incorrectly and creates meaningless syntax.
If you set the URL parameter to an escaped value (via encodeURIComponent) it will produce c({some:"Object"}) which is a JSONP response - JSONP is inherently a function call and works by injecting a script tag.
So, twitter does not produce this response deliberately, you're passing it problematic parameters and it's not failing gracefully.
As for why dividing a function in an object is NaN - in JS generally math operators don't throw very often. JavaScript is telling you - you tried to perform a math operation that doesn't make sense and the result is not a number - NaN.
For the funky results:
c/()
Is just invalid syntax, simply put you're diving something by nothing, 5/() would fail equally well.
c/({})
Diving a function by an object makes no sense, so it is giving you "Not a Number". I can add a spec quote but I don't think there is much more to add beyond "There is no way to interperet this differently".
c+({})
The + operator performs string concatenation in addition to numeric addition - so what's happening here is that toString is called for both the function and the object and you see the concatenated result.
c({})
This is just the return value of the function call

Error "Cannot call toString on undefined" but variable is defined

In this piece of Javascript
creds = cp[0];
data[creds.toString()] = cp[1]; // data is an object
Chrome gives me the error TypeError: Cannot call method toString of undefined on the second line. However, I've verified via the debugger that the value of creds is at that point the number 1400.
What's going on?
You should be very cautious when using for in loop to array. Use normal loop instead.
The array cpl has not just data but functions, so third cp in the loop is function. That's why creds turned to undefined.
This link has good explanation: Why is using "for...in" with array iteration a bad idea?
Javascript don't need variable type so do it by removing toString().
btw I'm not sure you can call toString() on a primitive type as int

Categories

Resources