I wrote a function that works great for mobile, based on something I found on SO a while ago.
jQuery(document).on('touchstart', function(event) {
if ( !jQuery(event.target).closest("#peopleMenu").length) {
jQuery("#peopleMenu").fadeOut();
}
});
the part that I found was in the "if" statement that took me a bit to wrap my head around.
It is saying that if the target touch event is on #peopleMenu , it will stay open, or close if touched off. The if statement boils down to :
if (!1) {
//false - understand this.
}
if (!0) {
//true - hmmm.
}
My question is basically is this a common programming paradigm, a strange js feature, or is it just trickier than it needs to be? Thanks.
This is common in many languages. Everything in JavaScript has an inherent Boolean value, generally known as either truthy or falsy.(e.g. 0 or an empty string). So in this case, if the length comes back as 0, the if statement is false. Here is a great writeup on this topic as it relates to Javascript if you care to know more: Truthy/Falsy
It is common, it mean if you touch something else than #peopleMenu or its childrens, do something.
0 is a falsy value while every other integer are truthy.
Using bang (!) reverse the value, !true == false and !false == true.
The .length property of jQuery is the way to know how many element are selected. 0 mean none.
Related
A falsy value is a value that translates to false when evaluated in a Boolean context.
https://developer.mozilla.org/en-US/docs/Glossary/Falsy
Exactly the following values are falsy in Javascript: false, 0, "", null, undefined, and NaN.
Now I am seeing this weird behavior: only the falsy values false, 0, and "" are equal to each other, but not equal to the other falsy values.
In addition null and undefined are not equal to any falsy values other than themselves.
And last but not least, NaN isn't equal to any falsy value, not even to itself!
Yet all of them evaluate to false in a Boolean expression like if (value) { ... }
What's the benefit or use case of this seemingly inconsistent behavior?
Note: By "equal" I mean (lax) equality defined by the == operator, rather than strict idendity defined by the === operator.
Why are falsy values not equal to each other in JavaScript?
Because there's a difference between two values that coerce to the same value when used as a boolean, and those two values being equal to one another.
What's the benefit or use case of this seemingly inconsistent behavior?
There we get into largely subjective territory, which isn't really on-topic for SO. Let's just say that JavaScript's loose equality rules have long been the subject of debate and confusion. One has to remember that they were created by Brendan Eich during those mad 10 days in May 1995 in which he created JavaScript, it's no great surprise there are some "clangers" in there. And remember his task was to create a tolerant, forgiving language for non-programmers to program in. Hence automatic semicolon conversion, loose equality, and so on. This was a language that was meant to let you grab a value from an input and treat it like a number, even though the value of an input is always a string. Whether these rules achieved that goal is a matter of opinion (and I'm not advancing one here either way :-) ).
Most of the "weirdness" comes about as a by-product of rules that mostly seem reasonable (with, again, a couple of clangers). Let's consider the thing about "" == 0 being true:
The rule for == is the abstract equality comparison algorithm, which says that if the first operand (x) is a string and the second operand (y) is a number, we return the result of ToNumber(x) == y. Leaving aside the question of whether a coercing equality operator is a good idea or not, if you're going to have one, that seems like a reasonable way to approach string == number. So we look to the ToNumber algorithm, which says that ToNumber(string) interprets the string as a number using the ToNumber Applied to the String Type algorithm, which says amongst other things that an empty string becomes 0.
So the question isn't "why is "" equal to 0", it's "why does "" coerce to the value 0 when treated as a number?" Only Eich can answer that question. :-)
There are some other fun ones in the main ToNumber algorithm, such as that undefined => NaN but null => 0. Again, only Eich can explain why he thought null should equate to 0 but undefined equate to NaN.
It's probably worth noting that he probably didn't just pick this stuff at random. He'd studied several other languages and made choices based on that knowledge. Some of those choices may look very odd to us in retrospect (implicit globals? really?), but then, most people have more than 10 days to create a language, time in which they can seek input from colleagues and the community. And again, there was that "tolerant" design criterion.
I may have strayed into some subjectiveness there. Apologies if so; I tried not to. :-)
Final note: If you find the rules arbitrary and hard to memorize, you aren't alone. One way to handle that is to ensure you do all your type coercion explicitly. But note that even if you try to do that, you're stuck with loose comparisons, because although there's a strict equality operator (===) and a strict inequality operator (!==), there are no strict versions of >, <, >=, or <=. So if you miss out an explicit coercion, your code may still seem to work if you're doing any of those other relations. I'm not advocating this (nor am I advocating against it), I've seen bugs caused both by explicit type coercion and by not having explicit type coercion. Just saying that it's one approach to the tricky rules.
It's probably related to preference. == null is very useful to determine if something is in a "not set" state, as it also checks for undefined; but does NOT return true for values like "", or 0; which will often come back from a form as valid values.
My understanding is that NaN fails all comparison checks so that it is noticed as soon as possible, so as to mean "This is not the value you were expecting." This works out if someone's type-checking block ends in an else { throw exception because I don't know what this is! }
I see no benefit to comparing false with 0, "", null, NaN, or undefined. There are no use cases, in my mind, that justify its use. If you write your code properly, this odd behavior is factored out. The reason the behavior exists in the first place is because JavaScript is loosely typed. Everything is an object. Best practice is to avoid use of the == equality operator and instead use ===.
Fundamentally, you shouldn't allow variables to be coerced into different types across the use of a program. It hinders understandability, readability, and maintainability. It's better to code Boolean operations explicitly (i.e. do this if (myVar === undefined) {...}, not if (!myVar) {...}).
To some extent the inconsistency is probably down to "Wat?!?" - see https://www.youtube.com/watch?v=FqhZZNUyVFM.
I mean, it's kind of odd that false, 0, and "" are considered equal, given they're different kinds of thing (well, I think it's odd anyway)... but I suppose this is why JS has both a strict and a lax equality operator.
And it's why tools like jshint and jslint encourage you to only use the strict === operator, so you don't fall foul of this kind of weirdness. This then forces you to test for truthiness or falsiness directly, rather than via lax equality.
Or to turn it around, if you think it's odd that falsey values aren't equal to eachother, it would be weird if this weren't the behaviour for truthy values. For example, you'd never expect "Bananas" and "Apples" to be equal.
(And, to more directly answer your question: I'd bet some weird historical reason that might get a mention in JavaScript: The Good Parts. Beyond that I don't know.)
This question already has answers here:
Using the (!!!) operator in JavaScript? [duplicate]
(5 answers)
Closed 8 years ago.
function ok(value, message) {
if (!!!value) fail(value, true, message, '==', assert.ok);
}
assert.ok = ok;
!!!value basically means not not not Boolean(value) yes?
Say if value = 9 > 1, then it would mean: not not not true.
not true = false
not not true = true
not not not true = false
My brain hurts. Why don't they just use !value instead of !!!value?
!value and !!!value both do have the same effect.
But, they intenionally use !! to convert the potential 'truthy' or 'falsy' variable value to a boolean.
So it does makes sense to use !!! when using value as a negated boolean, so developers can see that (in this case) value may only be 'truthy', e.g. a string and not true.
If in refactoring someone needs to set something to true and uses value, it may be set to a string. The !!! tells him to use !!value, if he expects value as a boolean.
The likely answer is either that they're using it to draw emphasis to the conversion or that some programmer just thought it was funny at some point -- there's absolutely no syntactical difference between !x and !!!x (or !!!!!!!!!!!!!x for that matter). After the first ! which will convert the variable to a boolean, you're just repeatedly adding the not operator to something. All that matters is whether it's negated an even or odd number of times.
That is certainly brain-pain inducing.
Normally, you would see something like the following
var error_boolean = !!(error);
This is done to force "error_boolean" to either true or false.
My guess is this is a refactor bug w/ harmless consequences. Someone probably replaced something like notValue (which was double negated here), with !value. What does annotating that line of source tell you?
Or this is simply a way to garner attention at the line, its working on us so far.
!! is Cast or Convert the variable to Boolean and the additional ! inverts it.
I think you could do this if it's easier to read var invertedBool = !Boolean("false");
I've just been looking at the _.isEqual function of Underscore.js and a section of the code goes something like this:
if (a === b) return true;
if (typeof a !== typeof b) return false;
if (a == b) return true;
I'm just wondering if there's any case where the third statement could be reached and evaluate to true?
Edit: Just to be clear, this isn't my own code I'm talking about, I'm reading the source of Underscore, in particular, this line and I was curious about why they're doing that.
I've just been browsing through the Underscore repo and came across a short discussion where someone asked the exact same thing, and it looks like it is actually unnecessary.
Following the algorithm defined by the ECMAScript Language Specification in section 11.9.6 and section 11.9.3 seems to show that no pair of values should return true in the above case.
So, in short, no, that situation is not possible.
The only situation where == and === react unexpectedly is when comparing a literal string ("123") to a constructed string (new String("123")), which would fail the first test.
However, on the second test it gets caught because the constructed string has the type object, but the literal has the type string.
Based on that, I'd say no, the third statement can never be reached, and evaluate to true.
When you use the == operator and the expressions are of different types, JavaScript will generally convert the two into the same type before comparing.
For example, this can happen with null and undefined. null == undefined is true, even though null === undefined is false. However typeof null is "object", while typeof undefined is "undefined". So, in this case you should return false on the second statement.
You can read all the details in the spec (section 11.9.3), it is very involved:
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
My initial guess was that it was to work around a broken browser implementation.
However after digging into the git logs for that file it looks like the corresponding line was in the very first underscore.js checkin. (I'm not gonna hunt in the parent documentcloud core.js repo...) You can see it at line 334 of https://github.com/documentcloud/underscore/commit/02ede85b539a89a44a71ce098f09a9553a3a6890 .
So now my guess is that its just cruft that got left in, never completely tested and never cleaned out.
It seems that the strict equality operator is preferred whenever possible - I put my code in JSLint and got the following feedback.
Code:
function log() {
console.log(arguments.length == 1 ? arguments[0] : arguments);
}
Feedback from JSLint:
Problem at line 2 character 34: Expected '===' and instead saw '=='.
I am curious to know what advantages === has over == here. Basically, .length returns a Number, and 1 is a Number as well. You can be 100% sure, so === is just a redundant extra token. Also, checking for the type whilst you know the types will always be the same has no performance advantage either.
So what's actually the reason behind using === here?
The only reason is that you don't have to think whether the comparison you are doing will involve coercion or not. If you stick to using ===, you just have one thing less to worry about.
Of course not everyone agrees. This is why you can disable specific checks in JSlint, if you are sure of what you are doing.
It's not strictly required, as you know the length function is well-tested. But what if length was a bit buggy, and there was a chance it could return false?
In this situation, both 0 and false would be evaluated as false using the == comparison. To test for false (when there is also the chance of 0 being returned), you need to also check the data type, which is where === comes in.
Well, === is supposed to be infinitesimally faster, as it can fail faster (on type mismatch), but that's deep inside the "pointless microoptimizations" territory.
Realistically, I'd advise for ===, even if you are 105% sure - I've been tripped up by my assumptions too many times ("yes, I am positive they are the ... same ... uh ..."). Unless there's a good reason to turn them off, it is better to keep sanity checks enabled in code than trust to do them in your mind.
Now I'm sure this is super easy, I have a function called "remove_deposit" which I want it to make the checkbox false if it's true. But I can't seem to get it to work..
function remove_deposit() {
if(document.getElementById('deposit').checked == true) {
document.getElementById('deposit').checked == false;
};
};
Am I at least on the right track?? lol
function remove_deposit() {
if(document.getElementById('deposit').checked == true) {
document.getElementById('deposit').checked = false;
};
};
You were doing a comparison instead of simply setting the checked attribute to false.
function remove_deposit() {
document.getElementById('deposit').checked = false
}
That's all you need. The reason why your code wasn't working was because you used two equals signs, which is a comparison operator, instead of one equals sign, which is the assignment operator.
Addendum: I removed the if statement since it doesn't really do anything useful afaict. If you did this to optimize the code, then I'd just like to point out that checking the if statement will probably be slower than just setting the checkbox to false. Also, you don't need to end every line with a semi-colon in JavaScript. You can do that if you want to put multiple commands on a single line, but otherwise it's not necessary.
Results are in.
If most of the time people running the javascript to set the checkbox to false do have the checkbox set to true, skipping the if statement is faster. Otherwise, if most of the time the checkbox is set to false, then the if statement would be faster. With a 1:1 ratio, no if statement is preferred.
The checkbox would have to be set to false at least 54% of the time for the if code to be more efficient.
http://img33.imageshack.us/img33/4260/results.png http://img33.imageshack.us/img33/4260/results.png
Side-note: If it's a checkbox, it's probably in a form, so you could also access it with the old-fashioned method document.formName.elementName instead of document.getElementById(). Because the form method doesn't need to traverse the DOM like getElementById does, I think that would be faster.
The results are in.
With 0 IDs preceding it, document.test_form.checkbox (DTFC) is slower than document.getElementById('checkbox') (GEBI). With 100 IDs preceding it, document.test_form.checkbox is still slower than document.getElementById('checkbox').
http://img8.imageshack.us/img8/6683/resultsw.png http://img8.imageshack.us/img8/6683/resultsw.png
I guess that settles it.
PS: These were all tested on Firefox using Firebug. I cannot make any claims about the efficiency of Safari's WebKit, Konqueror's KJS, IE's proprietary engine, or Google Chrome's V8. I'm guessing they should wind up somewhat similar to these, but they could be different.
You have an small error in your code sample on line 3. You've used a double equals ==
It should read:
document.getElementById('deposit').checked = false;