I am reading the source code of Underscore.js, then something confused me:
// Its code, check the passed-in parameter obj
_.isObject = function(obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
};
I am confused about the operator order of expression.
I think the operator precedence in
return type === 'function' || type === 'object' && !!obj;
will be from left
to right
; I mean equal to :
return (type === 'function' ) || ( type === 'object' && !!obj);
if type
equal function
return true
; else operate type === 'object' && !!obj
; if type
equal object
return !!obj
,same as Boolean(obj)
; else return false
;
I made some examples:
var a = alert(1) || alert(2) && alert(3);
alert(a); //result : 1, 2 undefined;
var a = alert(1) || alert(2) && 0;
alert(a); //result : 1, 2 undefined;
what confused me:
Why
!!obj
should exist? if we delete!!obj
, code run as well.the operator order of this code? I know
&&
operator are higher than||
, so I guess!!obj
effect when obj is null, but when I practice that is no what I want;
I am reading the source code of Underscore.js, then something confused me:
// Its code, check the passed-in parameter obj
_.isObject = function(obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
};
I am confused about the operator order of expression.
I think the operator precedence in
return type === 'function' || type === 'object' && !!obj;
will be from left
to right
; I mean equal to :
return (type === 'function' ) || ( type === 'object' && !!obj);
if type
equal function
return true
; else operate type === 'object' && !!obj
; if type
equal object
return !!obj
,same as Boolean(obj)
; else return false
;
I made some examples:
var a = alert(1) || alert(2) && alert(3);
alert(a); //result : 1, 2 undefined;
var a = alert(1) || alert(2) && 0;
alert(a); //result : 1, 2 undefined;
what confused me:
Why
!!obj
should exist? if we delete!!obj
, code run as well.the operator order of this code? I know
&&
operator are higher than||
, so I guess!!obj
effect when obj is null, but when I practice that is no what I want;
- developer.mozilla/en-US/docs/Web/JavaScript/Reference/… – mplungjan Commented Dec 2, 2016 at 8:57
-
1
Question is, since
null
is an object in Javascript, why would they want their_.isObject
method to returnfalse
onnull
? – connexo Commented Dec 2, 2016 at 9:11 -
2
@connexo well, because in the vast majority of cases, you want to check if what you get is an object with a value, rather than an object representing the absence of a value. Besides, were to actually make that argument for real (I am not sure if you're just playing devil's advocate here), then I'd point out that
null instanceof Object// false
while both{}
andfunction(){}
will returntrue
for that. Thus, theisObject
function is entirely consistent with those. Which, again, happens to be the most mon use-case for such a check. – VLAZ Commented Dec 2, 2016 at 11:48
4 Answers
Reset to default 5They want to return false
if the object is null
. Usually when we need to know if something is an object, null
is not what we're looking for. That's because trying to access null
's properties (null[propName]
for example) would throw an error.
console.log(typeof null);
The order of execution for the expression type === 'function' || type === 'object' && !!obj;
is from left to right:
type === 'function'
- if this istrue
the expression will returntrue
without puting the resttype === 'object'
- if this isfalse
the expression will returnfalse
without puting the last part!!obj
-null
would returnfalse
, any other object would returntrue
The snippet demonstrates the flow:
step(false, 1) || step(true, 2) && step(true, 3)
function step(ret, step) {
console.log(step);
return ret;
}
Using
!!
we can cast values to booleans - So truthy values would be converted to true, for example!!{} === true
, and falsy ones to false, for example!!null === false
.
Firstly, the expression is not read left to right, &&
has a slightly higher precedence than ||
, so it can be written either way -- a && b || c
is identical to c || a && b
. Operator precedence determines where parenthises should go in the expression, so a && b || c
would be (a && b) || c
. It's only within expressions where every operator has the same precedence that the operators are evaluated from left to right.
Regarding you're actual question -- in javascript, typeof null === "object"
, so the && !!obj
part of the expression is to guard against null
values evaluating to true.
The last
!!obj
forces the return value to a boolean value and yes, it is necessary because of typeof null
is object
.
Just Reference to MDN's Operator Precedence.
https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
Precendence for &&
is higher than ||
&&
first