I admit that I asked a question about why Closure Compiler does not shorten certain code which looks shortenable at first sight a few days ago already, but that reason is not applicable in this case and I'm not really sure why it isn't shortened here.
What code I have is:
var a = 0;
function b() {
return a++ >= 3;
}
Now there is pre-incrementing and post-incrementing. The difference is the return value - a++ returns a and then increments it, ++a first increments a and then returns it.
What this comes down to is that my code could be shortened to (ignoring whitespace removal):
var a = 0;
function b() {
return ++a > 3;
}
However, Closure Compiler does not seem to alter (or recognise) this.
My question therefore is: what side effects could ++a > have when used instead of a++ >=?
There is a particular edge-case for this construct (but not for 3).
It occurs because JavaScript stores numbers as IEEE-754 float-point 64-bit doubles and "only" has a guaranteed "exact" integer-representation up to 2^53 (although implementations may have lee-way to have a higher range, I do not know).
This is on Firefox 4:
a = 2e53
a++ >= 2e53 // true
a = 2e53
++a > 2e53 // false
Real question is what realized gain would such a very particular transformation have? :-0
Happy coding.
It’s safe to apply this size-optimisation if the right-operand (3 in your example) is a constant integer in the range [-252, 252]. In any other case (for example, if the right-operand is fractional or very large), it is not safe.
I would imagine that Closure does not implement this optimisation because:
it requires a lot of checking to ensure that the optimisation is safe,
it only applies in very specific circumstances that probably don’t come up very often, and
It only saves a single character, which hardly seems worth the bother.
Why not check all of the edge conditions yourself?
function b(a) {
return a++ >= 3;
}
function b2(a) {
return ++a > 3;
}
console.log(b(2) === b2(2))
console.log(b(3) === b2(3))
console.log(b(4) === b2(4))
The output is true in each case.
Related
My book says something and I'm not entirely sure what it means. It says that to make sure a loop executes properly, you need to include some code to change the value of the conditional expression?
What does that mean? Is that correct? I may be reading it wrong but when you have a basic Javascript loop like
if(contactsCount > 0) {
for (i = 0; i < contactsCount; i = i + 1){
var item = object[i],
name = item.name,
email = item.email;
target.innerHTML += '<p>' + name + '!</p>;
}
}
})();
Surely you aren't changing any values to make it work? I'm new to this so I'm kind of clueless.
...you need to include some code to change the value of the conditional expression? What does that mean?
That this is a bad idea:
var i = 0;
while (i < 10) {
doSomething(i);
}
Why? Because the loop will never end. i's value is never changed. Endless loops are a classic form of bug.
So what the book is saying is that you must provide for a way for the loop condition (i < 10) to change (e.g., by modifying i's value).
A bit of a tangent, but:
Sometimes you see loops where the condition seemingly can't change, e.g.:
while (true) {
// ...
}
If you find yourself reaching for something like that, stop yourself and try to find a better way. There are very rare use cases for the above, they look like this:
while (true) {
doThis();
doThat();
if (someCondition) {
break;
}
doAnotherThing();
}
...so in that case, the controlling condition is actually in the middle, and the one in the looping statement itself isn't really the condition. This is almost always poor practice, but in very rare situations they can be the right thing to do.
It also says that you can have other statements on the same line as the "if statement", is that right?
Yes, it is. JavaScript doesn't care about lines at all (except when it's doing a form of error-correction for you called Automatic Semicolon Insertion; then lines matter because linebreaks stand in for semicolons as part of the error-correction algorithm). All of these are valid and they all do the same thing:
// 1
if (a < b) {
alert("a is less than b");
foo();
}
// 2
if (a < b) { alert("a is less than b"); foo(); }
// 3
if (a < b)
{
alert("a is less than b");
foo();
}
// 4
if (a < b)
{ alert("a is less than b");
foo; }
Because JavaScript doesn't care about lines at all, they're a matter of style.
By far, the most common style for the above is #1.
Separately, if you have just a single statement in the control-flow statement's body, the block (the {...}) is optional. These do the same thing:
// 1
if (a < b) {
alert("a is less than b");
}
// 2
if (a < b)
alert("a is less than b");
// 3
if (a < b) alert("a is less than b");
So using {...} for a single statement in the body is also, technically, a matter of style. In practice, however, always using blocks leads to fewer bugs in your code. If you leave off the blocks, it will eventually bite you when you add a second statement and forget to add a block:
if (a < b)
alert("a is less than b");
foo();
In the above, foo() is always called, because it's not in the body of the if. That code does this:
if (a < b) {
alert("a is less than b");
}
foo();
In a for loop you should really use the (i++) shorthand but the way your doing it (i=i+1) will work fine as well.
Since I don't have your full source code here is an example...
Here is the JSFiddle demo
//JAVASCRIPT
//animals array
var animals = ['cat','dog','fish','bird','tiger'];
//loop through the animals array
for (i = 0; i < animals.length; i++){
console.log(animals[i]);
}
Is there any modern browser that raises exceptions on NaN propagation (ie multiplying or adding a number to NaN), or that can be configured to do so?
Silent NaN propagation is an awful and insidious source of bugs, and I'd love to be able to detect them early, even at a performance penalty.
Here's an example bug that use strict, jshint et al. wouldn't pick up:
object = new MyObject();
object.position.x = 0;
object.position.y = 10;
// ... lots of code
var newPosition = object.position + 1; // <- this is an error, and should
// have been object.position.x
// however it fails *silently*,
// rather than loudly
newPosition *= 2; // <- this doesn't raise any errors either.
// this code is actually ok if the
// previous line had been correct
Note: The TypeScript compiler is able to detect errors like the above, even in JS code, if type inference succeeds.
To answer the question as asked:
Is there any modern browser that raises exceptions on NaN propagation (ie multiplying or adding a number to NaN), or that can be configured to do so?
No. Javascript is a very forgiving language and doesn't care if you want to multiply Math.PI by 'potato' (hint: it's NaN). It's just one of the bad parts (or good parts, depending on your perspective) about the language that us developers have to deal with.
Addressing the bug that has you asking this question (presumably), using getters and setters on your Objects is one solid way to enforce this and also keep you from making mistakes like this.
Code below might help you.
To solve this problem fully, I think we need something like operator reload. We can reload operators like '+ - / *', and check if the operand is number, if not, then throw Error.
As a partial solution, when JavaScript does an operation like 'a + b', it will call the valueOf method which inherits from Object.prototype, we can rewrite Object.prototype.valueOf.
Object.prototype.originalValueOf = Object.prototype.valueOf;
Object.prototype.valueOf = function() {
if (typeof this !== 'number') {
throw new Error('Object is not a Number');
}
return this.originalValueOf();
}
var a = 1 + 2; // -> works
console.log(a); // -> 3
var b = {};
var c = b + 2; // -> will throw an Error
(hint: You can remove the code in production, and add it into your developing environment.)
the cleanest way to do that is having a short handy function that validates the expression's result every time
i know that's not the answer you are looking for but this is the javascript's nature and you can't change it sadly
function v(a){ if(isNaN(a)) throw "error"; return a; }
var test = v(100 * "abc");
I know this is an old thread but I think there may be a super simple answer to your question. You can either create a function for the below statement or add it inline.
JavaScript has some unique behaviors for certain values. One of these unique behaviors revolves around the not-a-number value or NaN. The value of NaN will not compare equal to any other value including NaN itself. For this reason the following statement:
if(x != x) {
throw "Value is NaN!";
}
will hold true if and only if the value of x is NaN.
I think this is a situation where getter and setter comes in handy.
Following is a psuedo code example just to give you an idea.
//Inside your Object class code.
function getPosition() {
//You don't want the property "position" to be NaN, right?
if(isNaN(this.position))
throws "NaN is not a correct numerical value!";
return this.position;
}
//Somewhere in your code
var newPosition = object.getPosition() + 1; //raises an exception.
I think this is better than implementing fake operator overloading and make things more complicated.
I hope it is ok that I am posting this question here even though I have also posted it on other sites. If I have failed to follow proper protocols, I apologize and please let me know right away so I may remove the post and learn my lessons.
I've been a front end developer for over a year now. I went to school to learn web development, and I consider myself a somewhat capable coder when it comes to simple JavaScript stuff.
But when it comes to writing any type of Fibonacci function I cannot do it. It is as if I have a piece missing from my brain that would understand how to deal with this simple sequence of numbers.
Here is a piece of a working code that I'm pretty sure I got from a John Resig book or somewhere online:
fibonacci = (function () {
var cache = {};
return function (n) {
var cached = cache[n];
if (cached) return cached;
if (n <= 1) return n;
console.log(n);
return (cache[n] = fibonacci(n - 2) + fibonacci(n - 1));
};
}());
When I call this function with 10 as the argument, I get this sequence: 10,8,6,4,2,3,5,7,9
Here's what I understand:
fibonnaci is assigned an immediately invoked function expression (or self executing blah blah blah), to which a cache is initiated with whatever argument was passed.
If the argument was already in the cache, we just return it and live our lives in everlasting peace.
If the argument is 1 or less, that is also the end of the function, everlasting peace ensues once more.
But if neither of these conditions exist, then the function returns this statement that makes me feel as if I am just a monkey in a human suit.
What I'd like to do is generate the first 10 fibonnaci numbers in the correct sequence, because if I can do that, then I'll feel like I at least understand it.
So when the first two conditions fail, the code creates a new cache variable and sets it equal to the result of the fibonacci function with whatever argument was passed minus 2, and then it adds the result minus 1.... now for my questions
Question 1: How does the function know what fibonacci(n-2) is if fibonacci(n) has never been computed?
Question 2: Are recursive functions linear, or what order do they follow?
Question 3: If I can't understand this, do I have any hope of becoming a programmer?
Thank you for your time.
After getting past this block, I changed the function a bit to see if I could hold on to the result in a variable and output it, just to see what happens, and I got some really unexpected results.
Here's the change:
fibonacci = (function () {
var cache = {};
return function (n) {
var cached = cache[n];
if (cached) {
console.log(cached);
return cached;
}
if (n <= 1) {
console.log(n);
return n;
}
console.log(n);
var result = (cache[n] = fibonacci(n - 2) + fibonacci(n - 1));
console.log(result);
return result;
};
}());
Here's the resulting pattern:
10,8,6,4,2,0,1,1,3,1,1,2,3,5,2,3,5,8,7,5,8,13,21,9,13,21,34,55
Any help with why this happens?
Well, let's start with what you understand (or say you understand):
fibonnaci is assigned an immediately invoked function expression (or self executing blah blah blah), to which a cache is initiated with whatever argument was passed.
Not quite: fibonnaci is assigned the return value of an IIFE. There's a difference. Inside the IIFE, we se a return function(n) statement. The IIFE is, as it's name suggests, invoked immediatly. the function is created, executed and, once returned, is not being referenced (explicitly) anywhere. The function is returned, is assigned to the variable fibonacci.
This IIFE does create an object literal, called cache. This object resides in the scope of the IIFE, but because of JS's scope scanning(this answer links to others... all of them together explain how JS resolves names to their values), this object is still accessible to the returned function, now assigned to fibonaci.
If the argument was already in the cache, we just return it and live our lives in everlasting peace. If the argument is 1 or less, that is also the end of the function, everlasting peace ensues once more. But [...]
Well, now cache is not created over and over again on each function call (the IIFE is only called once, and that's where cache is created). If the returned function (fibonnaci) changes it, that change to the object will persist in memory. Closure vars, for that is what cache is can be used to hold state between function calls. All the other things you say (n <= 1) is standard recursive function stuff... it's the condition that prevents infinite recursion.
But if neither of these conditions exist, then the function returns this statement that makes me feel as if I am just a monkey in a human suit.
Well, this is actually the fun part. This is where the actual magic happens.
As I've explained, fibonnaci does not reference the IIFE, but rather, it references teh returned function:
function(n)
{
var cached = cache[n];
if (cached)
{
return cached;
}
if (n <= 1)
{
return n;
}
return (cache[n] = (fibonacci(n-2) + fibonnaci(n-1)));
}
This means, that every occurance of fibonacci can be replaced with the function body. When calling fibonnaci(10), the last (return) statement should be read as:
return (cahce[n] = fibonacci(8) + fibonnaci(9));
Now, as yousee, fibonacci(8) and fibonnaci(9) are called, in the return value. These expression can be written in full, too:
return (cache[10] = (fibonnaci(6) + fibonacci(7)) + (fibonacci(7) + fibonacci(8)));
//which is, actually:
return (cache[10 = ( retrun (cache[6] = fibonacci(4) + fibonacci(5))
//since fibonacci(6) cached both fibonacci(5) & fibonacci(6)
+ return (cache[7] = cache[5] + cache[6])
+ return cache[7] + return (cache[8] = cache[6] + cache[7]
That's how this cache function actually ties in...
We can repeat this until we call fibonnacci(1) or fibonacci(0), because in that case n<=1, and will be returned without any more recursive calls.
Also note that, in writing fibonnaci(9) in full, this actually breaks down into fibonacci(7) + fibonacci(8), both these calls have been made before, and that's why there results were cached. If you don't cache the results of each call, you'll waste time calculating the same thing twice...
BTW: this code is very much "condesed", and works because the specs say that an assignment expression (cache[n] = ...) evaluates to the assigned value, you're returning cache[n], essentially.
Great questions. Thinking in recursive terms is tricky. If you try to grasp all the process you probably will fail miserably. I remembered to be frustrated as you are for not understanding the recursive solution to the Hanoi towers problem. I tried to trace on paper the sequence of steps but it was not of any help to understand the magic of what was going on.
What it worked for me was to think that the recursive function is a kind of "oracle" that knows the return value of the function fib(i) for any value of i < n. If the oracle knows fib(n-1) and fib(n-2), then it just has to give the instructions to calculate fib(n) from these known values. As a consequence we can say that the oracle, this function, also knows the value of fib(n).
A warning: there is a tricky part in all recursive functions, we need at least one not recursive value known at start the process, otherwise we will have an infinite recursion. In fibonacci example, these values are: fib(0) = 0 and fib(1) = 1
Your example is a bit more complex than that, as is using memoization, a technique to store the values of fib(n) in a cache to avoid recalculating them. In this case, this cache is an sparse array (array with "holes") that stores in its position i the value of fib(i) the first time it is calculated. This is a way to avoid repeating a costly computation the next time the same value of fib(i) is requested.
Aswering your questions:
fib(n-2) doesn't need to know the value of fib(n) to be calculated, what it needs are the values of fib(n-3) and fib(n-4). The only thing to do is to invoke them in ordert to ask the "oracle" their values.
It depends, there are linear recursive functions and tree shaped recursive functions, depending of how many other values they use. In this case you have a tree shaped invocation order. (Actually memoization makes it more complex and I would represent it as as a directed acyclical graph instead of a tree, but it is not relevant for the discussion).
Keep thinking on it, one day you will have an "aha" moment and then recursive functions will become evident to you.
If you still want to trace the execution of this function maybe it would help to refactor your calculation to an equivalent way as it makes more evident the order of execution:
// var result = (cache[n] = fibonacci(n - 2) + fibonacci(n - 1));
var fib2 = fibonacci(n - 2);
var fib1 = fibonacci(n - 1);
var result = fib2 + fib1;
cache[n] = result;
I know the question is a bit old, and the answers are helpful. I was doing this exercise in GoLang, and thought how I would write in Javascript, and use this answer to refresh my mind as well. I see your code has a cache variable to store the value of the fib(n-2) + fib(n-1) iteration. If you're doing recursive, you don't need a variable to store the result, because each time the function is called it returns a number, and these numbers are added up to the first function call.
function fib(n) {
if (n<=1) return n;
return fib(n - 1) + fib(n - 2);
}
To see why you don't need the cache variable is go through each function call, and start calculate the values once n equal 1 or 0.
for example:
iteration 1)
fib(3) {
return fib(3-1) + f(3-2)
}
---------------------------
iteration 2)
fib(3-1) {
return fib(2 - 1) + fib(2-2)
}
iteration 3)
fib(3-2) {
return 1
}
---------------------------
iteration 4)
fib(2-1) {
return 1
}
iteration 5)
fib(2-2) {
return 0
}
----------------------
if you calculate it the return value backward from iteration 5)
5) 0
4) 1
3) 1
2) 1 <== 4) + 5) = 1 + 0
1) 2 <== 2) + 3) = 1 + 1
so fib(3) is 2
So I'm trying out the Google Closure Compiler and I've noticed that it switches all my equality parameters so that the variables are always on the right side of the comparison.
So now instead of typeof XMLHttpRequest=="undefined" I have "undefined"==typeof XMLHttpRequest and I have if(null!==a) instead of if(a!==null), just as some examples.
I know they accomplish the same thing, but it's just not the style I'm used to. Is there some sort of benefit that you get for having these switched? I can't see how there would be.
Can someone explain to me why the Closure Compiler decides to do this? Is it just a preference of whoever wrote that part of Closure?
Edit: To clarify, people are telling me why it might be considered good coding practice. That's fine, but this is after compilation. Is there a performance benefit or is the Closure Compiler just trying to prove a point?
Commonly done in languages like C / C++ so you can't accidently do
if (a = null) {
// sets a to null and everyone is happy.
// but probably meant to check if a is null or not.
// via (a == null)
}
if (null = a) {
// won't compile
}
The compiler switches the order for a very simple reason: it compresses better with gzip. The compiler doesn't care a wit about improving comprehension or making it easier to edit. By switching the order common comparisons such as "if (x == null) ... if (y == null) ..." become "if (null == x) ... if (null == y) ..." Gzip finds "if (null ==" and is able to replace it with a single token. It isn't a big improvement, but it adds up in a large code base.
Yes, you can't assign to a constant, and == is easy to mistype (sometimes you may forget one, and use =).
For example, what's the difference between...
if (a == 1) { }
...and...
if (a = 1) { }
? The second one will always evaluate to true, not matter what the value of a.
If you flip the LHS and RHS, you can see the immediate benefit...
if (1 == a) { }
...will work as expected and...
if (1 = a) { }
...will fail, as you can't assign to a constant.
The reason I know is is done to prevent
if (x = 5) { }
If you reverse it to
if (5 = x) { }
You would get a compiler error.
But if you write it as
if (5 == x) { }
It will compile fine.
My brain parses
if( x < y )
slightly faster than
if( y > x )
probably because real axis is always oriented from left to right, thus making condition easier to visualize.
However, in java it is more practical to write
if( "string".equals(x) ) {...
as opposed to "more natural"
if( x.equals("string") ) {...
to eliminate any opportunity for NPE.
Just a cheap replacement of static analysis of particular case of common mistake/
I've put together a little range function in JS. I've tested it in Chrome 19, FF, and IE (7-9) and it's working well. The question I have has to do with the while statement.
function range(from,to,step)
{
'use strict';
var sCode,eCode,result;
result = [];
step = (!step || isNaN(step) || step === 0 ? 1 : step);
sCode = (''+from).charCodeAt(0);
eCode = (''+to).charCodeAt(0);
step *= (sCode > eCode && step > 0 ? -1 : 1);
do
{
if (String.fromCharCode(sCode))
{
result.push(String.fromCharCode(sCode));
}
}while((step > 0 && eCode >= (sCode+=step)) || (step < 0 && eCode <= (sCode+=step)));
return result;
}
I remember reading a question here a while back on how JS handles Control flow constructs and logical operators. I think it had something to do with checking if an object had a certain method, and if so, using it's return value (if (event.returnValue && e.returnValue === true) kind of stuff).I can't seem to find that question any more, here's what I wanted to know:
while((step > 0 && eCode >= (sCode+=step)) || (step < 0 && eCode <= (sCode+=step)));
Since the function behaves as I want it to, I think I'm right in saying that, if step < 0 is false, && eCode >= (sCode+=step) will be ignored, leaving the value of sCode unchanged. When the step check is true, sCode will be in/decremented. I've put this assignment in brackets, to make sure that the newly assigned value of sCode will be compared to eCode. Again, I assume that the brackets will give priority to the assignment over the logical operator.
Is this true for ALL browsers, or is it browser specific to some extent? is there a chance that this function will increment (or decrement) the value of sCode twice in some browsers?In this case, it's not that important (it's an easy fix to prevent any issues). But I want to know if this behaviour is inherent to JavaScript itself, or to the browser implementation.
Thanks for reading this far down. If you don't mind
A couple of other things (not important, but just wondering):
what is the max charCode in JavaScript? A quick look on google didn't tell me, and testing in the JS console lead me to believe this was 5999999999989759 which seems almost incredible, but then again I might need to brush up on my Chinese.
When from is undefined, the (jslint approved) approach from.toString().charCodeAt(0); fails, because obviously, undefined had no toString method, why the, does (''+from).charCodeAt(0); return U all the same? I thought it implicitly called the toString method?
I think I'm right in saying that, if step < 0 is false, && eCode >=
(sCode+=step) will be ignored, leaving the value of sCode unchanged
Correct. If the first operand evaluates to false, the second operand will not be evaluated.
After when the step check is true, sCode will be in/decremented. I've
but this assignment in brackets, to be sure that the newly assigned
value of sCode will be compared to eCode. Again, I assume that the
brackets will give priority to the assignment over the logical
operator.
Correct again, but the parentheses around the assignment are required, since assignment has a lower precedence than a comparison.
Is this true for ALL browsers?
Yes. I would be incredibly suprised if you find one that doesn't behave this way.
When from is undefined, the (jslint approved) approach
from.toString().charCodeAt(0); fails, because obviously, undefined had
no toString method, why the, does (''+from).charCodeAt(0); return U
all the same?
Because it concatenates the value of from with the empty string. The value of from is undefined, which is coerced to a string, and you end up with the string "undefined", and the character at index 0 of that string is "u".
The behavior of operators is consistent for all correct implementations of ECMAScript. I'm not aware of any browser implementation that deviates from what you've described.
ECMAScript is defined by standard. http://ecmascript.org/
And yes, the parentheses will define associativity of the operators..
MDN Operator Precedence