Oddities about JavaScript(smashingmagazine.com)
smashingmagazine.com
Oddities about JavaScript
http://www.smashingmagazine.com/2011/05/30/10-oddities-and-secrets-about-javascript/
9 comments
That NaN (not a number) doesn't compare equal to itself is not, in my opinion, a JavaScript oddity. NaN behaves like that according to the IEEE 754, and Wikipedia suggests that using the fact that x == x returns false is a way to test if x is NaN (http://en.wikipedia.org/wiki/NaN).
Nothing odd about it, it's the good old math at work.
Is (3 / 0) == (4 / 0)?
Is even (3 / 0) == (3 / 0)?
EDIT:
also, see [1] on what becomes when dividing both sides of equation by zero and assuming equality still holds. Essentially, both sides become NaNs and everything is possible -- up to and including 1 == 2. Now that'd would be odd, should it happen in your program.
[1] http://en.wikipedia.org/wiki/Invalid_proof#All_numbers_equal...
Is (3 / 0) == (4 / 0)?
Is even (3 / 0) == (3 / 0)?
EDIT:
also, see [1] on what becomes when dividing both sides of equation by zero and assuming equality still holds. Essentially, both sides become NaNs and everything is possible -- up to and including 1 == 2. Now that'd would be odd, should it happen in your program.
[1] http://en.wikipedia.org/wiki/Invalid_proof#All_numbers_equal...
The problem with this line of logic is that == is not equality. Two things being equal means they are actually the same thing and there aren't two things there at all, just one thing expressed two different ways. == is a binary relation [1]. In the context of that binary relation, if you made NaN == NaN it wouldn't really affect anything mathematically, because you already can't equationally reason on the basis of that binary relation, so there is no equational reasoning to become corrupted by accepting a contradiction.
[1]: http://en.wikipedia.org/wiki/Binary_relation
[1]: http://en.wikipedia.org/wiki/Binary_relation
> (...)there aren't two things there at all, just one thing expressed two different ways (...)
I have to respectully disagree with you :-)
Consider for a moment ``3 + 0''. That expression (those three tokens) denote something we can talk and reason about. Now the important point: not because of some inherent property of the notation itself, but because we, the people, agreed what we mean by that expression.
Contrast that with expression ``3 / 0'' -- which does not denote anything. Maybe, just maybe, there is something usefull that stems from division by zero, but! so far, we have not agreed upon what would be denoted by division by zero. We haven't agreed upon anything this expression would mean. It denotes no single thing, and neither a (nonempty) set of things. Of course, we have to somehow describe the fact of ``having nothing to say'' -- we use `NaN' -- but that's not a number symbol, that's a meta-symbol. Means, ``nothing to see there, my dear CPU, please move along''.
Note also, how in SQL, the following does not hold true: NULL = NULL. In SQL, `NULL' doesn't stand for something, but for no thing at all. And whaddya know, division by zero yields NULL in SQL.
* * *
As for the equality itself (as opposed to assignment), so far we, the programmers, have only one common use for it -- checking whether data from some source ``equals'' data from another source. There are three common ways of doing that:
0) pointer equality. Fastest, simpliest, but won't suffice in some programming languages. Thing is, one kind of languages keep just single copy of all the same values (say, every variable that holds string "foobar" points to the same memory cell), but others do not, and here you need one of the two following ways.
1) value equality (== in JS): whether the two expressions ``evaluate'' to the same value. This has two downsides: is generally slower (the overhead of runtime evaluation), and often is governed by twisted rules reagarding type coercion. For example, in PHP, the following holds: 0 == "1". Fun fact to know and tell: those twisted rules stem from the language creators' desire to make programming easier.
2) type-and-value equality (=== in JS): this straightens some ofthe twisted rules of 1), due to comparing data types first (instead of prerforming type coercion), but otherwise does the same thing: compares value. May often be faster and also simplier to grasp, but also may blow up when you mix up data with different types. Which nb. is easy to overlook when data comes from data sources having different semantics or idioms.
To put 1) and 2) in another way, those operations compare two values by their properties. Yet the NaN doesn't have properties to speak of, because it is not a value in the first palce. The operation of comparing is thus not well defined for NaN. Oops? :-)
I have to respectully disagree with you :-)
Consider for a moment ``3 + 0''. That expression (those three tokens) denote something we can talk and reason about. Now the important point: not because of some inherent property of the notation itself, but because we, the people, agreed what we mean by that expression.
Contrast that with expression ``3 / 0'' -- which does not denote anything. Maybe, just maybe, there is something usefull that stems from division by zero, but! so far, we have not agreed upon what would be denoted by division by zero. We haven't agreed upon anything this expression would mean. It denotes no single thing, and neither a (nonempty) set of things. Of course, we have to somehow describe the fact of ``having nothing to say'' -- we use `NaN' -- but that's not a number symbol, that's a meta-symbol. Means, ``nothing to see there, my dear CPU, please move along''.
Note also, how in SQL, the following does not hold true: NULL = NULL. In SQL, `NULL' doesn't stand for something, but for no thing at all. And whaddya know, division by zero yields NULL in SQL.
* * *
As for the equality itself (as opposed to assignment), so far we, the programmers, have only one common use for it -- checking whether data from some source ``equals'' data from another source. There are three common ways of doing that:
0) pointer equality. Fastest, simpliest, but won't suffice in some programming languages. Thing is, one kind of languages keep just single copy of all the same values (say, every variable that holds string "foobar" points to the same memory cell), but others do not, and here you need one of the two following ways.
1) value equality (== in JS): whether the two expressions ``evaluate'' to the same value. This has two downsides: is generally slower (the overhead of runtime evaluation), and often is governed by twisted rules reagarding type coercion. For example, in PHP, the following holds: 0 == "1". Fun fact to know and tell: those twisted rules stem from the language creators' desire to make programming easier.
2) type-and-value equality (=== in JS): this straightens some ofthe twisted rules of 1), due to comparing data types first (instead of prerforming type coercion), but otherwise does the same thing: compares value. May often be faster and also simplier to grasp, but also may blow up when you mix up data with different types. Which nb. is easy to overlook when data comes from data sources having different semantics or idioms.
To put 1) and 2) in another way, those operations compare two values by their properties. Yet the NaN doesn't have properties to speak of, because it is not a value in the first palce. The operation of comparing is thus not well defined for NaN. Oops? :-)
"I have to respectully disagree with you :-)"
You said this, but you never seemed to get around to an actual point of disagreement that I could see.
I'm not sure you realized that I was talking about math equality. In math, there is no distinct "3" vs. "3 + 0". We can indeed talk about how they are different tokens but there's no second "3". There's just the one in conventional systems that most people have heard of, expressable in a countably infinite number of ways (without getting crazy).s
(Yes, I know some of the other ones. That's why I said "conventional systems", after all.)
Math equality not being the same as programmer equality was my entire point. Thanks for elaborating on that theme, I guess? And given that it isn't the same thing, we aren't particularly constrained in how we use our programmer equality except by practical considerations. If we want NaN to == NaN and not === NaN, it's just a matter of making the programming runtime do it. Or vice versa. Or we can simply crash, which actually given how frequently people actually want NaN in Javascript is probably actually the choice I would choose. We aren't constrained by how continuous mathematicians of a certain school think our numbers work, because as programmers we never work with those numbers. We have completely different things going on. Actually if you operate on the assumption that your computer numbers are like mathematician numbers you will be in for nothing but pain on both sides.
You said this, but you never seemed to get around to an actual point of disagreement that I could see.
I'm not sure you realized that I was talking about math equality. In math, there is no distinct "3" vs. "3 + 0". We can indeed talk about how they are different tokens but there's no second "3". There's just the one in conventional systems that most people have heard of, expressable in a countably infinite number of ways (without getting crazy).s
(Yes, I know some of the other ones. That's why I said "conventional systems", after all.)
Math equality not being the same as programmer equality was my entire point. Thanks for elaborating on that theme, I guess? And given that it isn't the same thing, we aren't particularly constrained in how we use our programmer equality except by practical considerations. If we want NaN to == NaN and not === NaN, it's just a matter of making the programming runtime do it. Or vice versa. Or we can simply crash, which actually given how frequently people actually want NaN in Javascript is probably actually the choice I would choose. We aren't constrained by how continuous mathematicians of a certain school think our numbers work, because as programmers we never work with those numbers. We have completely different things going on. Actually if you operate on the assumption that your computer numbers are like mathematician numbers you will be in for nothing but pain on both sides.
[deleted]
Section 7 is so completely wrong:
var someVar = 'hello';
setTimeout((function() { alert(someVar); })(someVar), 1000);
var someVar = 'goodbye';
This won't do what he thinks it's going to do. Instead of alerting 'hello' after 1 second (after the value has been changed to 'goodbye') it alerts 'hello' immediately and does nothing after 1 second. Perhaps he meant something like: var someVar = 'hello';
setTimeout(
(function(innerVar) {
return function() { alert(innerVar); };
})(someVar),
1000
);
var someVar = 'goodbye';
This should alert 'hello' after 1 second even though someVar has by then been overwritten.@stanleydrew - I changed this code late last night after I realised my mistake here. Of course I had meant to return a function from the SEF, which the code in the article now does. Apologies for the oversight.
((EDIT: was irrelevant, as pointed out by stanleydrew in the post below. Thanks!))
That's the example of what doesn't work from the beginning of section 7. That will alert 'goodbye' after one second. I'm calling out his "fixed" code, which is supposed to alert 'hello' after one second.
Please don’t vote for this article, it’s full of half-truths and misconceptions.
You can not “fake” scope. When you call `call` on a function and pass an object as an argument, you are calling the function as a method of that object. This has nothing to do with a function’s scope.
You can not “fake” scope. When you call `call` on a function and pass an object as an argument, you are calling the function as a method of that object. This has nothing to do with a function’s scope.
Please:
Vote for articles you feel contribute to HN, either directly or through their discussion (a vote for a post does not necessarily imply agreement, it implies "This is worth reading.")
Please:
Point out half-truths and misconceptions.
Please don't:
Ask other people to vote for or against a post or comment.
Vote for articles you feel contribute to HN, either directly or through their discussion (a vote for a post does not necessarily imply agreement, it implies "This is worth reading.")
Please:
Point out half-truths and misconceptions.
Please don't:
Ask other people to vote for or against a post or comment.
The statement "Null is an Object" is probably more confusing than enlightening. I would prefer to say that typeof(null) non-intuitively returns the string "object".
The ECMA standard supports your story. The `null' is the only instance of type `Null'. A Null instance does not have any properties; in particular, doesn't have the `constructor' property all actual object do.
What alert() does is an implicit conversion to string, and that is surprisingly defined to say "object" in ECMA standard. Could be matter of backward compatibility...
What alert() does is an implicit conversion to string, and that is surprisingly defined to say "object" in ECMA standard. Could be matter of backward compatibility...
It actually makes some kind of sense in a dark, twisted way. If you think of it in terms of the Java type system, then the type of null is arguably Object.
> 9. 0.1 + 0.2 !== 0.3
You get this in most other programing languages too.
> 8. Firefox Reads and Returns Colors in RGB, Not Hex
The title says JavaScript, this is the DOM.
> 7. Functions Can Execute Themselves
Why is this so odd? I feel the author is too biased towards other languages. Also his example totally misses to point of closures.
> 6. You Can Fake Scope
No you can't fake scope, you override it. Why is this so odd? Again the author is not looking at it correctly, this is natural if you use it correctly.
Most of this article seems to come from someone who didn't really use JavaScript a lot, hence there is a lot of bias and prejudice. All you need to do is tell yourself that classical OOP is not the only way to code, and you will see that most of those things are really good stuff and not oddities.
You get this in most other programing languages too.
> 8. Firefox Reads and Returns Colors in RGB, Not Hex
The title says JavaScript, this is the DOM.
> 7. Functions Can Execute Themselves
Why is this so odd? I feel the author is too biased towards other languages. Also his example totally misses to point of closures.
> 6. You Can Fake Scope
No you can't fake scope, you override it. Why is this so odd? Again the author is not looking at it correctly, this is natural if you use it correctly.
Most of this article seems to come from someone who didn't really use JavaScript a lot, hence there is a lot of bias and prejudice. All you need to do is tell yourself that classical OOP is not the only way to code, and you will see that most of those things are really good stuff and not oddities.
My favorite oddity in JavaScript: Arrays are actually indexed by strings. arr[17] is just syntactic sugar for arr["17"].
Arrays in JavaScript are merely objects with some extra bits tacked on to make them appear "array-like". Underneath they are still a collection of key/values like all other JS objects.
But the "oddity" is that unlike many languages there are only string keys. Many languages implement the array type as a map but still distinguish between a[17] and a["17"].
Maybe I'm missing the point. I don't see how that is an oddity as all objects in JavaScript only allow string keys.
edit: JavaScript arrays are odd in general since they are just objects designed to look like "true" arrays. I guess I'm so used to that now that nothing about them feels "odd" anymore.
edit: JavaScript arrays are odd in general since they are just objects designed to look like "true" arrays. I guess I'm so used to that now that nothing about them feels "odd" anymore.
This article smacks of being written by someone who came to javscript from the design world, as opposed to coming to javascript as a programmer.
Javascript has automatic semicolon insertion. This function:
function a() {
return
true;
}
return undefined.This Python
def a():
return
False;
returns None.That's because in Python the line break is the statement terminator.
Python and JavaScript both accept semicolons or line breaks to terminate statements. JavaScript's syntax problems are a bit more subtle than just that.
Same in ruby
def foo
return
true
end
returns "nil"I don't like referring to this as "automatic semicolon insertion". The behavior you're referring to here is really about line termination/continuation.
Javascript just happens to make assumptions with certain kinds of ambiguities, but then, all programming languages do.
var a =
42
is only parseable one way because assignment requires an argument.Javascript just happens to make assumptions with certain kinds of ambiguities, but then, all programming languages do.
Actually that is the name that appears in the ECMAScript official language specification:
http://bclary.com/2004/11/07/#a-7.9.1
http://bclary.com/2004/11/07/#a-7.9.1
that just makes me a bit depressed then :)
Thanks for the reference. I still think this is a general issue, and calling it semicolon insertion confuses the issue :\
Thanks for the reference. I still think this is a general issue, and calling it semicolon insertion confuses the issue :\
Well, it is the combination of semicolon-insertion and restricted productions.
wow this article is full of errors