Give the following snippet
function countZeroes(array) {
function counter(total, element) {
return total + (element === 0 ? 1 : 0);
}
return reduce(counter, 0, array);
}
What does the === do?
Is reduce a built in function? What does it do?
Please explain the steps of this program.
It is the strict equality operator.
It compares two values and checks to see if they are identical according to the Strict Equality Comparison Algorithm.
This is opposed to ==, which will attempt to coerce one or both of the values being compared if they are of different types. That one uses the Absract Equality Comparison Algorithm.
The rules for the Abstract algorithm can be tricky. You're better off using === unless you have special need for ==.
From the MDC docs
The standard equality operators (== and !=) compare two operands without regard to their type. The strict equality operators (=== and !==) perform equality comparisons on operands of the same type. Use strict equality operators if the operands must be of a specific type as well as value or if the exact type of the operands is important. Otherwise, use the standard equality operators, which allow you to compare the identity of two operands even if they are not of the same type.
With regard to the code, this part:
(element === 0 ? 1 : 0)
...basically says if the value of element is exactly equal to 0, then use 1, otherwise use 0.
So to take that entire line:
return total + (element === 0 ? 1 : 0);
...the return value of the function will be total + 1 if element equals 0, otherwise the return value will be total + 0.
You could rewrite the code using an if-else statement:
if( element === 0 ) {
return total + 1;
} else {
return total + 0;
}
=== is the same as == except it doesn't cast variables
0 == '0' -> true
0 === '0' -> false
reduce isn't a built in function, but what it certainly does is run counter on each element of the array.
so for each element of the array the element is checked to be 0 and if it is the total is incremented.
=== is the identity operator, it's like ==, but does not perform type conversion.
this function appears to count the number of zeros in an array and return the count.
I assume that reduce() acts like Array.prototype.reduce
=== is strictly equal, both sides have to be of the same type and be equal. This is used to avoid the comparison of 2 unequal types (usually boolean false and a number 0)
The "===" is means "exactly equals", as in the value is the same, as is the type. So ...
var x = 5;
if (x === 5) {
alert("This will happen");
} else {
alert ("This won't");
}
It's rarely used.
The reduce function is likely the Array.prototype.reduce() method, which is used to apply a function to values in an array sequentially (sort-of). So, in this usage it is applying the 'counter' function to everything in the array, which will count the # of zeros in the array and return that.
Its a very good question and generally developer coming from other languages always have difficulty understanding the importance of using === as compare to ==
1. 5 == '5' //true why? Because it do
type conversion whereas in case with
=== 5 === '5'//false because '5' is a string as compare to number 5.
2. '\t\r\n' == 0 //true this lack of transitivity is alarming and cause
lot of errors.
3. Use JsLint ...it will help writing better JS code keep your code safe
from this kind of issues.
4. Moreover their is a performance penalty for using == when you are
comparing number with a string.
In my test it turns out that there is
little practical performance
difference between == and ===. While
the strict operator is marginally
faster (roughly 10%) in most browsers
when combined with explicit type
conversion, such as a === +b, the
only real performance gains will come
from avoiding type conversion
entirely. Converting a string to an
integer for comparison with another
integer is significantly slower (up
to 10x) than simple comparing two
integers. You should never allow
integers to be stored as strings
internally, as the type conversion
will incur a performance penalty.
While that was the basic takeaway from the numbers, I did find one interesting outlier when testing with Firefox. In Firefox, the comparison a === +b is about 20x slower than the equivalent a == b when a is an integer and b is a string integer. This result seems suspicious to me, and nothing similar occurred in any other browser. Oddly, when the Firebug script debugger is turned on, this result changes, and a === +b becomes about 10% faster than the other. I'm not sure what to make of this result, but it does serve as a reminder that integers should always be stored in numbers, not in strings.
see other answer about ===.
reduce it built in JS function which uses like "foreach", its moving on every elemnt in the array.
it start with the inital value, which in your case its zero, and then call to counter() and on the first element.
it check it, and return total(which is zero)+ 1 if the element is 0, after the returned value will be the "total" for the 2nd element in the array and so on....
in conclusion: the reduce call to counter on every element of the array,doing the test and adding its value to the (n-1)st element's returned value;
=== is a strict equality comparison. The == operator in JavaScript does type coercion, which often has surprising results, like how ' ' == false. So most JavaScript developers use === where possible.
Hard to tell about reduce(). That is not a built-in global function in JavaScript, but it likely refers to the reduce() method on JavaScript arrays. The reduce() method executes counter() once for every element in the array, and each time it calls counter(), it replaces total with the returned value from the counter() call. So the given function counts the number of elements that are strictly equal to zero in array.
Related
EDIT This question has been answered, but I've chosen to clarify it for future readers.
I've studied the explanations given about the logical operator !(parameter) and the inequality operator !==. They do not though clarify in what way they differ from each other. Let's look at an example.
!($.inArray(latlng, markers) == -1)
and
$.inArray(latlng, markers) !== -1
What is the difference between theese two expressions and are there any performance issues with either of the solutions making the other more preferable?
In your case there is no difference [due to aforementioned De Morgan's law], so stick to what is more readable to you.
Worth adding:
Comparison operators are binary operators -> have a arity value of 2, because they compare two things.
On the other hand, the negation operator (!) has arity one, because it negates its only argument to its boolean counterpart -> its image is thus [true, false].
This is why you may encounter !!foo in your programmer's life as a way to coerce foo to a boolean.
There really isn't a whole lot of difference, just the order that the logic operates. The first statement checks if they are equal and then gives you the opposite result. The second checks to see if they are different by comparing the values to see if they are the same and returning false if they are.
In effect, they are the same. There is actually something called DeMorgan's Law that governs the equality between comparison and logical operators (i.e. stating that they are equivalent and can be exchanged for others that have the same result in a different structure)
Comparison: take two values and compare them. We could ask various questions, for example:
are these two values "the same", we use == for that
is this value bigger than that value, >
is this value bigger than or equal to that, >=
The result of each of this is a boolean value. So we could write:
boolean areTheyEqual = ( x == y );
So aretheyEqual would be "true" if x was equal to y. Now suppose you wanted a variable "areTheyDifferent". We could get that in two ways, either using the "not" operator, which works on a boolean value:
boolean areTheyDifferent = ! areTheyEqual;
or we could use the "notEqual" comparison
boolean areTheyDifferent = ( x != y );
So the ! operator takes a boolean value and "inverts" it. You need to read the
!=
as a single comparison operator, just like >= is a single operator
Comparison operators are used in logical statements to determine equality or difference between variables or values. eg x!=y
Logical operators are used to determine the logic between variables or values.
eg !(x==y)
I'd like to know whether String.replace() actually found a match and performed a substitution. Since String.replace() returns the resulting string rather than the number of substitutions performed, it seems that I would have to compare the original with the result.
The question is, should I use === or == for that comparison?
As far as I can tell, neither the Mozilla documentation nor the ECMAScript 5.1 Standard specifies that the string that is returned must be the same object as the string that was passed in, if no match occurred.
On the other hand, it would seem stupid for any implementation of JavaScript to return a copy of an unchanged string.
In concrete terms, what happens with
var s = 'abc';
var t = s.replace(/d/, 'D');
console.log(s === t); // I expect true, but am not sure
Is it
Guaranteed to print true? If so, where is that behaviour documented?
Undefined and unreliable behaviour (i.e., I should test s == t instead, or do something clever with a replacement callback closure)?
Undefined behaviour that in practice returns true on every JavaScript implementation?
Edit
#cookiemonster asks:
So it seems that you're not really wondering if the result is guaranteed, but more whether an implementation is optimized to perform an identity comparison internally. Is that right?
Actually, I did screw up the question, and it ended up being an X-Y problem. What I really want to know is, how can I check whether any substitution occurred (the actual number of substitutions doesn't matter — one or more times are all the same)? And do so efficiently, without doing a separate .match() or a character-by-character comparison. And be certain that the result is guaranteed by the language specification.
=== won't work with a String object:
a = new String("foo")
a.replace(/XXX/, "") == a
> true
a.replace(/XXX/, "") === a
> false
or any object that has a custom toString method:
b = { toString: function() { return "foo" }}
"foo".replace(/XXX/, "") == b
> true
"foo".replace(/XXX/, "") === b
> false
Most of the time, this is a non-issue, but "praemonitus, praemunitus" as they say.
To answer your update: as seen here, at least V8 is optimized to return the subject itself if no replacements can be made:
int32_t* current_match = global_cache.FetchNext();
if (current_match == NULL) {
if (global_cache.HasException()) return isolate->heap()->exception();
return *subject; <-------
and, although the standard only requires two strings to look the same to be strict equal (===), I'm absolutely positive that every JS engine out there is smart enough to avoid strcmp on equal pointers.
It makes no difference.
Why? Because String.replace operates on strings, and returns a string. Also, strings are primitives, not objects.
You already know that you have two strings. == and === are therefore identical for this purpose. I'd even go so far as to say that === is superfluous.
The replace method on the String class always returns a string, so === is just as safe to use and reliable as == since no type coercion will happen. Secondly, if no substitution occurred, the === test will return true since they contain the same characters.
Given your example...
"Is it Guaranteed to print true? If so, where is that behaviour documented?"
Yes, it is. It's documented in the respective equality comparison algorithms used by == and ===.
Abstract Equality Comparison Algorithm
Strict Equality Comparison Algorithm
"Is it Undefined and unreliable behaviour (i.e., I should test s == t instead, or do something clever with a replacement callback closure)?"
No, it's well defined behavior. See above. The == and === operators will behave identically.
"Is it Undefined behaviour that in practice returns true on every JavaScript implementation?"
As long an implementation is following the specification, it will return true.
The following comparisons all return false in javascript:
[]===[]
[]==[]
{}==={}
{}=={}
[0]===[0]
[0]==[0]
However the following return true:
[0]=='0'
[0]==0
[]==false //(and all other == that were exampled above)
What is the reason for this? Especially the difference between [0]!=[0] and [0]==0
Fiddle: http://jsfiddle.net/vnBVj/
This is due to the confusing rules, how javascript does type coercion. You can read about this in §11.9.3 of the EcmaScript 5 spec.
Two Objects (which Arrays are too) are never equal, thus all your comparisons in the first block yield false (§11.9.3.1.c.vi)
The second block is more difficult:
First thing to know is, that == uses type coercion to compare the operands.
When a comparison has a Boolean involved, this one is first coerced to a number.
[]==false
[]==0
after that Objects are coerced to their primitive values by calling Object.prototype.toString
"" == 0
Then the string is coereced to to a number ("" becomes 0)
0 == 0
yielding true. By applying the same rules, you can see why your other examples also yield true.
Note that === never causes type coercion, but checks for correct types first and yields false if they are not equal! Only if the types are equal, it compares the actual values. So this method of comparison is far more reliable than ==.
All the example to result in false can easily be explained by the fact, that in case you are comparing objects (and arrays are special objects), JavaScript will compare object references. As you are creating new objects with all those comparisons, all will point to different objects, hence the result will be false.
As for [0]=='0': As soon as one operand is a string, the other one gets converted to string as well. The string conversion of [0] is '0', thus the result is true.
The same goes for one operand being a number or a boolean, which explains the last two comparisons' results.
For more information have a look at the respective MDN page.
Citing the important part:
Equal (==)
If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible. If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.
When you use litteral array/object initialisation, even if it is empty, you create a new object and it's reference is returned. So when you compare them, you compare the value of the reference of the objects you created.
Your other examples return true because you're comparing different types of variables, so, the objects/arrays are transtyped to be comparable with them.
While it's clear how using the === operator for e.g. numbers is useful (0, null and undefined all being falsy values, which can lead to confusion), I'm not sure if there are benefits to using === for string comparisons.
Some of my team mates use this operator for all comparisons, but does it really make sense? Is there at least some minor performance impact?
If you know the types are the same, then there's no difference in the algorithm between == and ===.
That said, when I see ==, I assume that I'm using it for its type coercion, which makes me stop and analyze the code.
When I see === I know that there's no coercion intended, so I don't need to give it a second thought.
In other words, I only use == if I intend for there to be some sort of type coercion.
It is considered good practice to always use === for comparisons in JavaScript. Since JavaScript is a dynamic language, it is possible that what you think are two strings could be variables with different types.
Consider the following:
var a = "2", b = 2;
a == b // true
a === b // false
The only way to guarantee a false result in this case would be to use === when comparing the two values.
I recently discovered that 2 == [2] in JavaScript. As it turns out, this quirk has a couple of interesting consequences:
var a = [0, 1, 2, 3];
a[[2]] === a[2]; // this is true
Similarly, the following works:
var a = { "abc" : 1 };
a[["abc"]] === a["abc"]; // this is also true
Even stranger still, this works as well:
[[[[[[[2]]]]]]] == 2; // this is true too! WTF?
These behaviors seem consistent across all browsers.
Any idea why this is a language feature?
Here are more insane consequences of this "feature":
[0] == false // true
if ([0]) { /* executes */ } // [0] is both true and false!
var a = [0];
a == a // true
a == !a // also true, WTF?
You can look up the comparison algorithm in the ECMA-spec (relevant sections of ECMA-262, 3rd edition for your problem: 11.9.3, 9.1, 8.6.2.6).
If you translate the involved abstract algorithms back to JS, what happens when evaluating 2 == [2] is basically this:
2 === Number([2].valueOf().toString())
where valueOf() for arrays returns the array itself and the string-representation of a one-element array is the string representation of the single element.
This also explains the third example as [[[[[[[2]]]]]]].toString() is still just the string 2.
As you can see, there's quite a lot of behind-the-scene magic involved, which is why I generally only use the strict equality operator ===.
The first and second example are easier to follow as property names are always strings, so
a[[2]]
is equivalent to
a[[2].toString()]
which is just
a["2"]
Keep in mind that even numeric keys are treated as property names (ie strings) before any array-magic happens.
It is because of the implicit type conversion of == operator.
[2] is converted to Number is 2 when compared with a Number. Try the unary + operator on [2].
> +[2]
2
var a = [0, 1, 2, 3];
a[[2]] === a[2]; // this is true
On the right side of the equation, we have the a[2], which returns a number type with value 2. On the left, we are first creating a new array with a single object of 2. Then we are calling a[(array is in here)]. I am not sure if this evaluates to a string or a number. 2, or "2". Lets take the string case first. I believe a["2"] would create a new variable and return null. null !== 2. So lets assume it is actually implicitly converting to a number. a[2] would return 2. 2 and 2 match in type (so === works) and value. I think it is implicitly converting the array to a number because a[value] expects a string or number. It looks like number takes higher precedence.
On a side note, I wonder who determines that precedence. Is because [2] has a number as it's first item, so it converts to a number? Or is it that when passing an array into a[array] it tries to turn the array into a number first, then string. Who knows?
var a = { "abc" : 1 };
a[["abc"]] === a["abc"];
In this example, you are creating an object called a with a member called abc. The right side of the equation is pretty simple; it is equivalent to a.abc. This returns 1. The left side first creates a literal array of ["abc"]. You then search for a variable on the a object by passing in the newly created array. Since this expects a string, it converts the array into a string. This now evaluates to a["abc"], which equals 1. 1 and 1 are the same type (which is why === works) and equal value.
[[[[[[[2]]]]]]] == 2;
This is just an implicit conversion. === wouldn't work in this situation because there is a type mismatch.
For the == case, this is why Doug Crockford recommends always using ===. It doesn't do any implicit type conversion.
For the examples with ===, the implicit type conversion is done before the equality operator is called.
[0] == false // true
if ([0]) { /* executes */ } // [0] is both true and false!
That's interesting, it's not that [0] is both true and false, actually
[0] == true // false
It is javascript's funny way of processing if() operator.
A array of one item can be treated as the item itself.
This is due to duck typing. Since "2" == 2 == [2] and possibly more.
To add a little detail to the other answers... when comparing an Array to a Number, Javascript will convert the Array with parseFloat(array). You can try it yourself in the console (eg Firebug or Web Inspector) to see what different Array values get converted to.
parseFloat([2]); // 2
parseFloat([2, 3]); // 2
parseFloat(['', 2]); // NaN
For Arrays, parseFloat performs the operation on the Array's first member, and discards the rest.
Edit: Per Christoph's details, it may be that it is using the longer form internally, but the results are consistently identical to parseFloat, so you can always use parseFloat(array) as shorthand to know for sure how it will be converted.
You are comparing 2 objects in every case.. Dont use ==, if you are thinking of comparison, you are having === in mind and not ==. == can often give insane effects. Look for the good parts in the language :)
Explanation for the EDIT section of the question:
1st Example
[0] == false // true
if ([0]) { /* executes */ } // [0] is both true and false!
First typecast [0] to a primitive value as per Christoph's answer above we have "0" ([0].valueOf().toString())
"0" == false
Now, typecast Boolean(false) to Number and then String("0") to Number
Number("0") == Number(false)
or 0 == 0
so, [0] == false // true
As for if statement, if there is not an explicit comparison in the if condition itself, the condition evaluates for truthy values.
There are only 6 falsy values: false, null, undefined, 0, NaN and empty string "". And anything that is not a falsy value is a truthy value.
Since [0] is not a falsy value, it is a truthy value, the if statement evaluates to true & executes the statement.
2nd Example
var a = [0];
a == a // true
a == !a // also true, WTF?
Again type casting the values to primitive,
a = a
or [0].valueOf().toString() == [0].valueOf().toString()
or "0" == "0" // true; same type, same value
a == !a
or [0].valueOf().toString() == [0].valueOf().toString()
or "0" == !"0"
or "0" == false
or Number("0") == Number(false)
or 0 = 0 // true