JavaScript Language Lawyers,
Any reason introducing this is a bad idea?
function defined(value) {
return typeof value !== ‘undefined’;
}
Behold
if (defined(positions) || defined(normals)) {
}
Compared to
if (positions !== ‘undefined’ || typeof normals === undefined) {
}
How many mistakes did you catch? 1? 2? There are 3.
The only downside I see is remembering to AMD include the file and perhaps minor function call overhead, but this reads cleaner and is less error prone.
Patrick
I suspect that function call overhead is huge compared to an typeof x === ‘undefined’ check. I whipped up this jsperf: http://jsperf.com/typeof-undefined-versus-function-call to confirm my suspicion. 63% slower in Chrome, 23% slower in Firefox (assuming my test case is valid, Scott, please double check my work).
Also, we can probably whip up a few regular expressions to check the code for valid usage of typeof x === ‘undefined’, this way we can automatically check for issues like this.
Just a thought: we could also write simple script that inlines calls to define() (and default() as well), at least in the minified version. I’m not sure it’s worth it, and it’s frustrating that we have to do such things, but I thought I’d just throw it out there.
The microbenchmark is one thing, but is this going to show up on the profiler in practice? 63% and 23% slower of lighting fast is lighting fast, especially compared to rendering - or just setting the uniforms - for a single terrain tile.
If it’s a real issue, inlining as Kevin suggested is reasonable.
Patrick
“The microbenchmark is one thing, but is this going to show up on the profiler in practice?”
That’s a valid point. If people are really gung-ho about this, I won’t object; but I’ll admit that I’m slightly biased against it. The errors you should in your example code would easily because caught by unit tests. (Then against I wasn’t a big fan of defaultValue when it showed up either, and now I’m used to it; plus that’s called thousands of times a second.)
The JSPerf difference is interesting, but a smaller example with node and V8 with the trace flags show that defined is inlined into the call site (as you’d expect), and the hydrogen for the two functions looks basically the same.
So where do we stand with this? Start adding it in new code, and put in an issue to do it everywhere? Or we could put in a issue to try it everywhere and then check the profile before and after?
Patrick
I would go with the second option, convert everything first and profile. especially on mobile.