Summary
Type Conversion
1. Primitive -> Number
2. any -> bool
3. primitive -> string
4. object -> primitive
Operation
1. Arithmatic Operator: + - * / % ++ --
2. Comparison Operators > < >= <= == != === !==
1. > < >= <=
2. ===
3. ==
4. != !==
3. Logical Operators ! && || ?:
Expression
Application
Summary
1. type conversion
2. arithmetic operation
3. expression
Type Conversion
1. Primitive -> Number
1. true: 1
2. false: 0
3. null: 0
4. undefined: NaN
5. string
empty string, string containing space (e.g., '', ' ', '\n', '\r', '\t'): 0
number string is number, else NaN.
2. any -> bool
1. null: false
2. undefined: false
3. number:
0: false
NaN: false
other: true
4. string:
only empty string (''): false
other: true
5. object: true
3. primitive -> string
1. null: 'null'
2. undefined: 'undefined'
3. number: 'number'
4. boolean:
true: 'true'
false: 'false'
4. object -> primitive
Step 1: call [[Link]] if available in an object. Return primitive. Else, throw error.
we can override [[Link]]
const a = {
[[Link]]() {
[Link]('toPrimitive');
return 1; // return primitive number 1 (change this to 'this', an error is thrown)
}
}
if (a == 1) {
[Link]('nice');
}
// toPrimitive
// nice
Step 2: call [Link] : every object provide this method.
we can override [Link]
const a = {
valueOf() {
[Link]('valueOf');
return 1;
},
toString() {
[Link]('toString');
return 1;
}
}
if (a == 1 && a == 2 && a == 3) {
[Link]('Nice');
}
/*
valueOf
valueOf
*/
Step 3: If still obj, call [Link]
we can override [Link]
Step 4: If still obj, throw error
const a = {
valueOf() {
[Link]('valueOf');
return this;
},
toString() {
[Link]('toString');
return 1;
}
}
if (a == 1 && a == 2 && a == 3) {
[Link]('Nice');
}
/*
valueOf
toString
valueOf
toString
*/
Note: changing valueOf or toString of an object might alter the object behavior.
Operation
1. Arithmatic Operator: + - * / % ++ --
Step 1: convert to primitive type
Step 2: check if there's special case
1. convert to number type and perform operation.
2. special case: x + y where x or y is a string, convert to string and concatenate.
3. special case: compute** NaN with other type get NaN.
/* Example 1
* Step 1: both are primitive.
* Step 2: No special case, then convert to number.
* null --> 0
* undefined --> NaN
*/
[Link](null + undefined); // NaN
/*Example 2
* Step 1: Not primitive, convert to primitive
* [Link]([].valueof() + {}.valueof();
* [Link]([].toString() + {}.toString())
* [Link]('' + '[object Object]')
* Step 2: it's special case, string concatenation.
*/
[Link]([] + {}); // '[object Object]'
[Link]({} + []); // '[object Object]'
{} + []; // 0 - in console, the first {} is interpreted as empty code block rather than an objec
Note:{} in the beginning of the statement is interpreted as code block. quirk
2. Comparison Operators > < >= <= == != === !==
1. > < >= <=
Step 1: convert to convert to primitive type
Step 2:
1. convert to number type and compare.
2. special case: both are strings, compare ASCII value of each characters.
3. special case: either / both are NaN, must be false.
2. ===
1. type and value must be same.
2. special case: either / both are NaN, must be false.
3. ==
1. both are same type, compare values.
2. both are primitive type, convert to number and compare.
3. one is primitive, another is object, convert object to primitve and compare.
4. special case: undefined and null can only compare with themselves or with each other, otherwise
return false.
5. special case: either / both are NaN, must be false.
4. != !==
negate == or ===
/* Example 1
* [Link](0 > NaN);
*/
[Link](null > undefined);
3. Logical Operators ! && || ?:
convert to boolean
1. x && y
if x is falsy, return x
if x is truthy, return y
2. x || y
if x is falsy, return y
if x is truthy, return x
Expression
Data:
1. literal:
1;
'a';
[1, 2, 3];
2. variable:
let a = 123;
3. expression: must have return value
1 + 2;
a * 2;
a && b;
[a + b, a - b];
arr[arr[2]];
[1,2,3][a];
1 || 2
1 && a;
Application
1. Default
var limit;
// verbose
if (limit === null || limit === undefined) {
limit = 10;
}
// Optimised
limit = limit || 10;
2. Safe access of property value
var user = {
name: 'deng',
addr: {
provine: 'a',
city: 'b',
},
};
/*
Potential Issues:
user might be null.
[Link] might be null.
city might be null.
*/
if ([Link]) {
//...
}
// Optimised
if (user && [Link]) {
[Link]([Link]);
}
// Further Optimised
[Link](user && [Link] && [Link]);
3. early return
var isFound = false;
if (isFound === true) {
[Link]('a');
} else {
[Link]('b');
}
// Optimised
// if (data) {...}
if (isFound) {
[Link]('a');
} else {
[Link]('b');
}
4. null and object
var user = null;
if (user === null) {
[Link]('please log in');
}
// Optimised
if (!user) {
[Link]('please log in');
}
//
5. Conversion
// Number
var page = '10';
page = Number(page);
[Link](page, typeof page);
// Optimised
page = +page
// Boolean
var x = 'aaa';
y = Boolean(x);
[Link](y);
// Optimised
y = !!x;
[Link](y);