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:
inop & optional chaining syntax?.(checknull/undefined) - key iterate:
for..inloop & 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
newop (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:
undefinedvalues (""intoString()) - manually decrease: elem lost — clear arr
arr.length = 0
- manually increase:
delete arr[i]: value =>undefined(lengthkeep 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:
...arrin 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 ..
thisin 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
thisin method ..1
2xxx = () => {..} // field store in obj itself ("this" = obj)
this.xxx = this.xxx.bind(this); // bind existing method in constructor - access
staticoutside F:F.xxx(Fasthis) .., ..- 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 createthisby parent-con (in regular fn, an empty obj created forthis) .. - method.
[[HomeObject]]= their class/obj .. (bound forever ..) &superfind parent methods in[[HomeObject]].[[Prototype]].. - so method with
supernot free (it uses[[HomeObject]]) .. superonly 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):messagee.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 ..