JavaScript basics
Var, Data types & Ops
Var
let
,const
: block scope .. — the old “var” & IIFE
Data types
Number
- int/float &
Infinity
,-Infinity
,NaN
.. - auto type convert: unary
+
, math-op/fn &Number(value)
- tasks: Why 6.35.toFixed(1) == 6.3?, random int from min to max
String
- quotes &
...${...}
.., special chars:\n
,\
.. - auto type convert: in output e.g.
alert(..)
,toString()
: obj as key, JSON.stringify() &String(..)
.. - substr
str.slice()
, str comparestr.localeCompare(str2)
,str.repeat(n)
, charCodeString.fromCodePoint(code)
&str.codePointAt(i)
(in generate pwd ..) .. - task: Truncate text
Bool
- 6 falsy values ..
- auto type convert: logical op
!!
, compareson &Boolean(..)
null & undefined
null
: value unknown;undefined
: init val for unassigned-var & default fn-return- Nullish coalescing op
??
Ops
Function
Fn creation ..
- fn dec: block-level (if strict), def-hoisting (start with
function
, require a name & cannot be called immediately ..) - fn-expr: easy dynamic def
- arrow-fn (see obj)
new Function([...params]: ...str, body: str)
: create fn dynamically at run time (golbal scope) .. —eval(code: str)
..
Fn is obj
Fn: a callable action (instead of data ..) obj ..
- fn-def: store the fn-obj in same named var, call by
fnName(...args)
— callback & anonymous .. - Fn built-in props:
name
(str, “” for anonymous),length
(param #, rest param not count) - custom prop/helper method:
fnName.xxx = ..
- tasks: Set and decrease for counter, Sum with an arbitrary amount of brackets
Closure
- block scope & Lexical Environment (EnvRecord & outer-ref, created on run time) …
- LE var/fn pre-populate & var “dead zone” ..
- access var through LE chain (inner-outer) .. & updated on the LE it lives ..
Closure: a fn that remembers its outer vars and can access them by e.g. return a fn (or as obj prop) ..
- run outerFn: new outerFn.LE & nestedFn created,
nestedFn.[[Env..]] = outerFn.LE
(set once & forever) - run nestedFn: new nestedFn.LE created &
nestedFn.LE -> outerFn.LE
(ref value taken from [[Env..]]) - task: Counter object, Sum with closures, Filter through function, Sort by field, Army of functions
Obj, Arrow Fn, Con-Fn
obj — str/symbol: any type
- key can be reserved word, non-str/symbol key ==> toString ..
syntax
- key existence test:
in
op & optional chaining syntax?.
(checknull/undefined
) - key iterate:
for..in
loop & prop order .. - value access:
.
vsobj["prop"]
.. - prop add/set:
obj.prop = xxx
, delete:delete obj.prop
.. - computed prop, prop value shorthand ..
obj deep cloning: for..in
& typeof
..
tasks Check for emptiness
Methods & “this”
method def: fn-expr shorthand || copy from fn ..
this
eval at run-time — losing “this” problem
- call fn with obj (“this” in methods):
this=obj
.. - call fn without obj (as fn itself) ..
- tasks: Using “this” in object literal, calculator, Chaining
- losing this problem & reference type, task: Explain the value of “this”
bind “this”
- fn binding:
fn.bind(context, [...startingArgs])
this=context
(bound hard-fixed), partial .., ..- tasks: Bound fn in method, re-bound ignored, Fn prop lost af bind, method bind context in callbacks, Partial & method
- call forwarding:
fn.apply(context, args: arrLike)
(prefer) &fn.call(context, ...args);
- fn-borrowing:
[].join.call(arguments);
in fn-body
Obj & Fn
Arrow fn
(...args) => expr || { ...body } || (obj-litiral)
..
F: Constructor fn
- set props & methods
this.xxx = ...
- call by
new
op (execute “internal algorithm”)- return this || another obj (prim-return ignored)
- Constructor mode test:
new.target
- singleton obj
new function() { ... }
Built-in Data Structure
Array
- value indexing:
arr[i]
, value iter:for..of
||arr.forEach()
arr.length
= greatest index + 1, init as item #, writable- manually increase:
undefined
values (""
intoString()
) - manually decrease: elem lost — clear arr
arr.length = 0
- manually increase:
delete arr[i]
: value =>undefined
(length
keep same) ..arr.toString()
=>_,_,_...
- Object.keys/values/entries(obj) => arr (enum & non-symbol key)
- task: Sum the props
Methods ..
splice(..)
: […rmed-elems]filter(fn)
: […matchedItems],find(fn)
,indexOf()
,includes()
map(fn)
&reduce(..)
,sort(..)
&reverse()
arr.join(glue=',')
&str.split(delim)
(('')
: char[])Array.isArray(value)
Iterable & array-like
- iterable (e.g. arr & str) can be used in
for..of
.. - array-like: obj with numeric index & length ..
- str both iter & arr-like .. —
str[i]
&str.length
- iter/arr-like => array:
Array.from(obj, ..)
...
: Spread syntax & Rest param
- Spread syntax:
...iter
: item list (use for..of internally)- copy/merge/convert by
[...iter]
/{...obj}
- copy/merge/convert by
- Rest params:
...arr
in fn-def
Destructuring assignment syntax
- Copying iter-items into vars:
let [...vars]/{...obj-props} = arr/obj
(keep origin unmodified) - easy swap:
[guest, admin] = [admin, guest];
- nested desructing : same structure (no var for the group one)
- Smart fn params: pass obj as fn param
- obj destcructing to existing var:
(
{…})
({} in main code flow as code block) ..
tasks
- A maximal subarray
- Filter range “in place”
- Sort in decreasing order
- Create an extendable calculator
- Sort users by age
- Shuffle an array
- Filter unique array members:
Array.from(new Set(arr))
- Create keyed object from array
JSON
- Send data:
JSON.stringify(obj, ..)
&obj.toJSON()
: formatted str (aka serialized obj) - Get data:
JSON.parse(str, ..)
: obj
Prototypal inheritance
[[Prototype]] & prototype
[[Prototype]]
: null || obj (aka prototype) .., accessor methods & fully obj-clone ..- the deprecated
__proto__
prop .., reside inObject.prototype
.. (why depr & “Very plain / pure dict” obj ..)
Prototypal inheritance: prop not exist in the obj -> find from proto (follow [[Prototype]]
ref chain) ..
- proto only for reading prop, write/delete data prop act on the obj (write may call setter in proto) ..
- proto search opt ..
this
in proto method: ref to obj bf.
(method shared but obj state not) ..- inherited prop in
for..in
(if enum) but not inObject.keys/values()
, diff byobj.hasOwnProperty(key)
.. - task: add toString() to the “very plain” obj
F.protoype: a “normal” prop of con-fn F, set [[Proto..]]
for obj from F when new F()
let obj = new F()
: setobj.[[Prototype]] = F.prototype
({constructor: F}
by default)- so
obj.constructor === F
&let obj2 = new obj.constructor()
- re-assign F.protoype to another obj: prev created obj.[[Prototype]] not affect
- native F.prototypes
- Check prototype chain by
console.dir(obj)
.. - task: Add decorating “defer()” to fns, the diff btw calls
Class
1 | class F { |
- bind
this
in method ..1
2xxx = () => {..} // field store in obj itself ("this" = obj)
this.xxx = this.xxx.bind(this); // bind existing method in constructor - access
static
outside F:F.xxx
(F
asthis
) .., ..- return obj in static method by
new this(..)
(factory method)
- return obj in static method by
- Class Encapsulation ..
- protected:
_xxx
(convention) —proxy
.. - private:
#xxx
(proposal, cannot access bythis['#xxx']
) - read-only prop: only getter no setter (set value on con)
- protected:
- task: class Clock
Class vs fn
typeof F
: "function"
..
class F { .. }
: F (con-fn) & F.prototype ..1
2
3
4
5
6F: {
constructor code,
...statics,
[[Prototype]]: ParentF || Function.prototype
}1
2
3
4
5
6F.prototype: {
...methods, // non-enum
constructor: F,
[Prototype]]: ParentF.prototype || Object.prototype
}new F()
: obj1
2
3
4obj: {
...fields,
[[Prototype]]: F.prototype // access to non-static methods
}- class & fn diffs ..
Class inheritance
extends
set 2 proto refs: ..
F1.[[Prototype]] = F2
(con-fn inheritance, for statics)F1.prototype.[[Prototype]] = F2.protptype
(for methods)
Member overriding
- override con/method:
super(..)
&super.method(..)
..- default child-con:
super(...args)
.. - call
super(..)
in child-con bf usingthis
.. (why?)- when
new
: child-con createthis
by parent-con (in regular fn, an empty obj created forthis
) .. - method.
[[HomeObject]]
= their class/obj .. (bound forever ..) &super
find parent methods in[[HomeObject]].[[Prototype]]
.. - so method with
super
not free (it uses[[HomeObject]]
) .. super
only work formethod()
, notmethod: function() { .. }
..
- when
- default child-con:
- override field:
field = ..
(parent-con use own field value, not overriden one) .. - task: Extended clock, Class extends Object?
Extending built-in classes ..
Class Type Checking ..
obj instanceof F
—F[Symbol.hasInstance](obj)
&F.prototype.isPrototypeOf(obj)
Object.prototype.toString
:[object xxx]
(xxx: value ofobj[Symbol.toStringTag]
)
Mixin
A class / obj contains methods for other classes without inheritance
- imp by copying method into prototype
Object.assign(F.prototype, mixin)
(prevent overwrite) - EventMixin example
Error handling
Error obj: new Error/Syntax*/Reference*/Type*(msg)
..
- props:
name
(F):message
e.g. “Ref..Error: xxx is not defined” in alert ..
try..catch..finally
: sync & run-time err / exception ..
- throw err (in try || rethrow in catch):
throw
- checking err:
instanceof
.. - Global handler:
window.onerror
..
custom err/ extending err: ValidationError
.. & PropertyRequiredError
example ..
- set name:
this.name = this.constructor.name;
- wrapping-exception pattern: catch syntax & validation errs and throws ReadError ..