Reputation: 2923
I have a good grasp on the difference between undefined and null and the fact that JavaScript casts just about anything to a boolean, in particular, null to false.
My question is this: Why is the second alert triggered in both FF 9 and IE 9? (This is a small test script that is based on much more complex script. It is meant only to illustrate the issue...)
I'm expecting the . operator to take precedence and the expression to return null, which would then be cast to a boolean value of false. Adding parenthesis, !(context.isNull), makes no difference.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Test</title>
</head>
<body>
<script type="text/javascript">
var context = this;
var isNull = null;
var aFunc = function() {
alert(context.isNull);
if (!context.isNull) {
alert("Is !context.isNull really true?");
}
};
aFunc();
</script>
</body>
</html>
Upvotes: 0
Views: 376
Reputation: 2923
First, "Thank you!" to everyone who responded.
I'm deeply embarrassed. It was late Friday on a long day, and I inverted the logic in my head. It is doing exactly what it should. The problem was that the actual code was checking for something existing, and I wrote my test case backwards.
What happens is that null is cast to false, !false is true, so the "if" code is executed. My (brain dead) choice of field names obscures the problem.
The reason for
var context = this;
is that the real code sits inside a constructor. The field "context" is then "closed" when the function is created, which preserves a reference to the object being constructed. This is important when the function is attached to another object (generally as an event handler), so that the function body can access the contents of the original object. Of course, in the example, "this" refers to the global object, which doesn't serve much purpose.
Upvotes: 0
Reputation: 79830
Edit: I missed the context = this part.. As other mentioned, context = this => context = window.
Also, var isNull = null; in global scope implies => window.isNull = null.
Which will be as,
if (!context.isNull) => if (!window.isNull) =>
if (!null) => if (!false) => if(true)
if (!context.isNull) => if (!undefined) => if (!false) => if(true)
Upvotes: 0
Reputation: 526613
context.isNull
is this.isNull
is window.isNull
which is null
, which is boolean false. You're then adding !
, which inverts that, resulting in an overall true
expression, thus your if
body is evaluated.
Upvotes: 1
Reputation: 38318
When placed in a boolean context a null
value will evaluate to false
. The unary negation operator !
casts the null
to a boolean value - false
- then flips the boolean to its opposite value: true
. So !
does two things - it casts and flips.
Upvotes: 0
Reputation: 6871
isNull is a local variable. It is not a property of the object presently represented by "this" if you add this.isNull = null or context.isNull = null you will get what you are looking for.
I think he's getting a true result because context.isNull is undefined and since undefined counts as a false result inverting it
Consider that this also produces the alert:
var aFunc = function() {
alert(context.isNull);
if (!context.foo) {
alert("Is !context.isNull really true?");
}
};
Upvotes: 0
Reputation: 183301
I take that you're expecting !null
to be null
? That makes sense — that sort of three-valued logic is used in SQL — but that's not how it works in JavaScript. In JavaScript, !
forces its argument to be interpreted as boolean value, and as you know, null
, when interpreted as a boolean, becomes false
.
Upvotes: 0