notes_js
Micro-Frontend
an architectural approach for building web applications by decomposing them into smaller, independently deployable and maintainable frontend modules or components. Each sub-application repo is independent and does not share its own state during runtime.
- to decouple complex application.
- allow teams to work on different parts of an application independently
- allow to gradually replace or rewrite old part of an project, and friendly to grey deploy
- integrating third-party components or services
QianKun is built upon single-spa, listening for location
changes, and then matching and loading sub-applications accordingly. Each sub-application has its own entry file and DOM container. This approach is similar to using multiple entry files in webpack
.
Time Complexity
the growth rate of the runtime as the input size increases.
- O(1): Constant time – the execution time does not change with the input size.
- O(n): Linear time – the execution time grows linearly with the input size.
- O(log n)
Design Patterns
method chaining
a concept, one function returns the current(refer to this
in js) object and another function can use values in this
.
1 |
|
the principles of component design
- single responsibility principle. to compose complex components by smaller specialized components.
- conceals the construction of components, and only reveals the necessary information
- To ensure predictability and determinacy of components, always return the same output for a given input
- keep loose coupling, instead of tight coupling. Components should have little or no knowledge about others.
- composable. Composition is a way to combine components to create a bigger component
- reuseable
- pure or almost pure function which means no side effects and doesn’t depend on the environment or the global state, such as network or global variables.
- isolate the impure code from the pure
- straightforward to test
- a meaningful name. If a component’s usage is highly specific, its name may contain more words, like
<HeaderMenu>
<Header>
- Open Closed principle,software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification
the levels of a component based on its usage
1. Reading name and props; best
2. Consulting documentation; good
3. Exploring the code; admissible
4. Asking the author. avoid
performance optimization
- avid
reflow
andrepaint
- utilize
prefetch
andpreload
to enhance the execution order of js and prevent it from blocking HTML rendering - enable GZIP compression on the server
- minimize the number of DOM elements and keep the DOM structure as simple as possible
- lazy loading
- virtual scroll
- listen to scroll event, only render the items within the visible area of parent element according the
scrollTop
and the visible height of the parent - dynamic height
- Use the estimated height initially, and then replace the position value with the actual DOM height after rendering. Add a buffer area by rendering a few items at the top and bottom of the visible area. This provides more time to render and calculate for a smooth scrolling experience.
- listen to scroll event, only render the items within the visible area of parent element according the
browser rendering
the rendering process
- browser obtains the IP address from the domain name through
DNS(domain name system) analysis
- send a http request to that IP address
- server receives the request and responds with html content
- the browser parses html strings and create a dom tree, and then proceeds to analyzes CSS, forming CSS rule trees
- structure the rendering tree(only the nodes necessary for display)
GUI rendering thread and JS engine thread
GUI(graphical user interface) rendering thread and JS engine thread are mutual exclusive
. The rendering process pauses during the download, analysis, and execution of JS. When the browser encounters JS during the rendering process, it halts rendering to construct the rendering tree and passes control to the JS engine .
reflow and repaint
- reflow: When changes in DOM geometrical properties (like width, height, or display) affect the page layout or the position of other elements, the browser must recalculate the page’s layout.
- repaint: when the style(like color, background) of dom are changed
Ifrepaint
doesn’t affect the geometrical size of the DOM elements, thenreflow
isn’t required. However,reflow
will inevitably triggerrepaint
.
avid reflow
and repaint
as much as possible
- use
transform
instead ofpositive and top
, the former performs changes in the GPU instead ofcausing
reflow and occupying the rendering thread. - use
visibility
instead ofdisplay:none
, the former incur repaint only while the latter will change layout - instead of making multiple small changes to the DOM, try to make all necessary changes in one go.
- accessing properties like
offsetWidth
,offsetHeight
, orgetComputedStyle()
can trigger a reflow - use browser developer tools to monitor performance metrics like reflows, repaints, and rendering performance.
SVG
properties
width/height: define the size in the document
viewBox: first two number are min-x and min-y used to define the position, the other two are define the scale relative to width/height
1 | when the viewBox is same as width/height, then the dimension is 1. if it is smaller than width/height, then the dimension is larger than 1, and vice versa. |
path
M: move to
L: line to
H: a horizontal line
V: a vertical line
Z: close path, combine the start and the end
C: curve, x1 y1 x2 y2 x y, the last set x y specify where the line should end and the line start at the point where the last operation ended, the first two are control points.
1 | <svg className="selected-round-btm" viewBox="0 0 8 8" width="8" height="8" xmlns="http://www.w3.org/2000/svg"> |
S: smooth curveto
A: an arc, rx ry x-axis-rotation large-arc-flag sweep-flag x y
rx ry
radius x and radius yx-axis-rotation
large-arc-flag
determines that the arc should be greater than or less than 180 degrees.sweep-flag
determines that the drawing direction is clockwise or anticlockwise.x y
the ending point calculated with angle, while the arc starting point is at three o’clock of a circle,circle center + radius = the arc starting point
1
2
3
4
5
6
7
8
9// get the ending point with an angle
function polarToCartesian(centerX, centerY, radius, angleInDegrees) {
const angleInRadians = (angleInDegrees * Math.PI) / 180.0 // the length of the arc
const largeArcFlag = angleInDegrees <= 180 ? "0" : "1";
const x = centerX + radius * Math.cos(angleInRadians)
const y = centerY + radius * Math.sin(angleInRadians)
return [radius, radius, largeArcFlag, 0, x, y]
}a 360-degree circle can’t be done by one arc, since the end point are same with the start point. but it consist of two arcs.
"M 140 80 A 60 60 0 0 0 20 80
+60 60 0 1 0 140 80
Q: x1 y1, x y, quadratic Bézier curve, to control the slope of two sides with one point, which is the first set
T: x y, smooth quadratic Bézier curveto, auto control the slope of two sides according to the last control point
filter
in && in2, SourceGraphic | SourceAlpha | BackgroundImage | BackgroundAlpha | FillPaint | StrokePaint |
1.in
is the first input, andin2
is the second input, while the placing order is same with the layer order of PS
2.ifin
is not existed, then the value will be the previous filter input
- feBlend, to blend two layers ruled by a certain blending mode
in
in2
mode
- feComposite, to combine two input images
in
in2
operator
, compositing operations
animation
- SVG animation is not css animation, it’s part of the
SVG animation specification
, specifically within theSMIL (Synchronized Multimedia Integration Language)
animations in SVG.
it runs on the browser’scompositor thread
, reducing the load on the main JavaScript thread.
CSS
anchor position
stacking context
Special properties like z-index
will cause elements to form a stacking context 层叠上下文
, as those properties can change the render order of elements on the page if their values are set to something other than none
position, opacity, filter, transform, detailed list of such special properties
selector
1 | /* nth-of-type and nth-child, the former according to the order of a given type, while the latter according to the order of children*/ |
box module
standard box: only content is included in with / height
IE box: border / padding / content are included in with / height
box-sizing: content-box = standard
box-sizing: border-box = IE
layouts
adaptive design: multiple predefined layouts are created for different screen sizes
responsive design: use flexible grids and elements that automatically adjust and reflow based on the viewport size
物理像素:计算机硬件,真实屏幕的像素点
css像素:属于逻辑像素的一种
设备像素比(Device Pixel Ratio,DPR):物理像素与逻辑像素之比吗,比如iphone6物理像素是750 x1334,但实际逻辑像素是 375* 667,所以dpr = 2,这表示iphone6采用高清屏使用两个像素去渲染一个像素使画面更高清,iphone6 plus 甚至是dpr = 3
1px 问题:设计师的视觉稿是相对于物理像素750px,实现一个1px边框,但css逻辑像素是375px,border-width:0.5px 使用transform: scale(0.5)
% + meta
vw/vh/% + px + flex layout,响应式布局
flex + vw/v/%h布局,局部使用px
在跨设备类型的时候(pc <-> 手机 <-> 平板)使用媒体查询
rem ,响应式布局,动态设置 root 的 fontsize,子节点使用rem,和flexible不同的是可以根据pc、手机、平板的尺寸来设置比例使子节点计算方便
1 | var deviceWidth = document.documentElement.clientWidth |
flexible, self-adoption
模拟vw特性,动态的将页面宽度的1/10作为根节点的 fontsize,子节点使用rem就等于是按照页面比例计算
1 | var doc = document.documentElement |
高倍屏适配,修改了等比缩放视口的scale值,使得clientWidth变为物理像素尺寸,1物理像素等于1css像素,由原来的375=>750, media尺寸查询语句也同样需要修改
1 | var metaEL = document.querySelector('meta[name="viewport"]') |
centered and vertically aligned layout
Flex
1
2
3
4
5
6.parent {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}Grid
display: table
anddisplay: table-cell;vertical-align: middle;
1
2
3
4
5
6
7
8
9
10
11.parent {
display: table;
width: 400px;
height: 300px
}
.child {
display: table-cell;
vertical-align: middle;
text-align: center;
}position
andtransform
1
2
3
4
5
6
7
8
9
10
11.parent {
position: relative;
height: 100vh;
border: 1px solid #ccc;
}
.child {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
others
text linear-gradient
1
2
3
4
5
6{
color: transparent;
-webkit-background-clip: text;
background-clip: text;
background-image: linear-gradient(130deg,red,black);
}browsers (like chrome) can set a
minimum fontsize
which can’t be overthrow, buttransform: scale
can be a workaround1
2
3
4
5
6
7
8// set an unseen element for getting the minimum size
const minimumSize = Number.parseInt(window.getComputedStyle(document.getElementById("minimumSize"), null).getPropertyValue("font-size").replace(/px/, ""))
// generate different scales based on the minimumSize
//the app has been set to fit `window.devicePixelRatio` in this situation. so the fontsize takes rem as unit, and item * fontSize is purposed to get the original size.
const fontSizes = [1.2, 1.3, 1.4, 1.6, 2, 2.8].map((item) => {
const _s = item * fontSize < minimumSize ? item * fontSize / minimumSize : 1
return `--fontSize${item.toString().replace(/\./, "")}:${_s};`
}).join("")transform
doesn’t work on inline elementsuse
position: sticky
withflex layout
. the sticked elements may still moving when user scrolling.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15<!-- set flex's width to the sum total of all the cell widths 250vw to fix the problem -->
<div class="container" style="overflow: auto">
<div class="flex"style="display: flex">
<div class="cell" style="width: 25vw;flex-shrink: 0;background: green; position: sticky; left: 0">cell</div>
<div class="cell" style="width: 25vw;flex-shrink: 0;background: green;position: sticky; left: 25vw">cell</div>
<div class="cell" style="width: 25vw;flex-shrink: 0;background: red">cell</div>
<div class="cell" style="width: 25vw;flex-shrink: 0;background: red">cell</div>
<div class="cell" style="width: 25vw;flex-shrink: 0;background: red">cell</div>
<div class="cell" style="width: 25vw;flex-shrink: 0;background: red">cell</div>
<div class="cell" style="width: 25vw;flex-shrink: 0;background: red">cell</div>
<div class="cell" style="width: 25vw;flex-shrink: 0;background: red">cell</div>
<div class="cell" style="width: 25vw;flex-shrink: 0;background: red">cell</div>
<div class="cell" style="width: 25vw;flex-shrink: 0;background: red">cell</div>
</div>
</div>text ellipsis
text-overflow: ellipsis
only applies to single line1
2
3
4
5.single {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}multiple lines
- use
after pseudo class
to display “…” after the text - cut off the text through js
- use
attr()
1
2
3.test::before {
content: '我的内容是' attr(text) '颜色是' attr(data-color);
}1
<div class="test" data-text="TEXT" data-color="red"></div>
shape-outside
make the adjoining inline-elements around itselfpseudo-elements
, don’t work on img/select/input::before
and::after
can add elements, and clean float.::first-line
,::first-letter
,::selection
pseudo-class
:enabled
and `:disabled:checked
:nth-child(n)
,:nth-of-type(n)
element hiding
transform: scale(0,0)
will not respond to event listenersvisibility:visible
can display children whose parent is hidden byvisibility:hidden
Browsers render empty characters between inline elements as whitespace.
Storage
cookie, 4kb, can set the expire time,
httpOnly = true
means this cookie is set by server and can only be changed by serverlocalStorage sessionStorage, maximum size 5MB
1
2
3
4localStorage.setItem('chooseId',JSON.stringify(this.$route.params))
localStorage.removeItem('chooseId')
localStorage.clear()
localStorage.key(index)indexedDB no size limits, it can be used like a database
caches, an object which include
cache instance
s, eachcache instance
can viewed as a storage region. the return type of all the methods ofcaches
orcache instance
ispromise
.methods which are mounted on
caches
are used for managingcache instance
s.caches
:keys
open
delete
has
match
- differ between
has
and match: has return boolean while match give you the data
if we want to store something, then we need to use
open
to get acache instance
where is our data staycache
instance:add
addAll
keys
delete
match
matchAll
put
1
2
3
4
5
6
7
8// differ between `add` and `put`: add can `fetch` and `store` the data automatically, but also because of automatically then we can't make changes on key and value to be stored
// so fetch + put = add
cache.add(request).then(function() {
// request has been added to the cache
});
fetch(url).then(function(response) {
return cache.put(url, response);
})when use
cache with service worker
, the data we stored is the rawresponse
returned byhttp
RegExp (regular expression)
1 | var re = new RegExp(“a”, "img") |
modifier
i
ignore uppercase and lowercase of lettersg
global matching, to search from the start to the end whatever how muchm
matching on multiple lines- es6
u
turn onUnicode mode
to deal with Unicode characters - es6
y
similar withg
, but it’s match work started form the beginning of the string- it’s effect is equal to add
^
at the beginning of a regexp, so it could regarded as a complement for thatg
couldn’t add^
sticky
, new property of RegExp, to know the regexp is addedy
or not
- it’s effect is equal to add
Properties
es6
regexp.flags
, get all the modifierses6
regexp.source
, get the regexp contextregexp.lastIndex
, allow you to define and get the index from where the next match work started1
2
3
4
5const REGEX = /a/g;
REGEX.lastIndex = 2; // to define the index
const match = REGEX.exec('match a string');
match.index // 6
REGEX.lastIndex // 7, to get the index
test(), is matching or not
1 | regExp.test(str) // boolean |
search()
1 | string.search(regExp) // return an index or -1 |
replace(), es6 replaceAll
1 | string.replace(regExp, replaceText) // return the replaced string |
exec()
1 | regExp.exec(string) // return an array of information which include lastIndex, allow you to match along the last position. |
1 | // use with while |
with named capture groups(具名组匹配), you can get the data of each group which declared by ()
1 | const regExp = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/ |
match(), es6 matchAll
1 | 'For more information, see Chapter 3.4.5.1'.match( /see (chapter \d+(\.\d)*)/i) // return an array of information |
symbols
PS Safari does not support ?!=n
?<=n
?<!=n
?:n
key | usage |
---|---|
() |
Parentheses, to group regular expressions |
[] |
match any character within the brackets |
^ $ |
match from the start or the end of the string |
[^a] |
match string which no ”a“ |
{n,m} |
the display times > n and < m |
{n,} |
the display times > n |
{,m} |
the display times < m |
* |
equal to {0,} |
+ |
equal to {1,} |
? |
equal to {,1}, /.*?(\d)/, when ? is used with greed mode, it means to exclude a specific format |
| | a|b === a or b |
. |
equal to {1,} |
.* |
greedy mode |
.*? |
the regex engine will, at every step it matches text into the “.” attempt to match whatever make come after the “.*?” |
\d |
equal to [0-9] |
\D |
equal to [^0-9] |
\w |
equal to [a-zA-Z_] |
\W |
equal to [^/w] |
\s |
equal to [ \f\n\r\t\v] (换页,enter,空格,tab,垂直制表符) , matching all the empty characters |
\S |
equal to [^/s] |
/S/s |
all the characters |
(.|\n)* | to match any characters across multiple line |
?=n |
match string but don’t get, the string after which is n |
?!=n |
match string but don’t get, the string after which isn’t n |
?<=n |
(incompatible with safari) match string but don’t get, the string before which is n |
?<!=n |
match string but don’t get, the string before which isn’t n |
?:n |
match string but don’t get |
examples
to match every character except ,;
1 | /[^,;]+/ |
to match a string, stop matching until a specific format is encountered
1 | // ?(?=hello) match string but don't get |
verify float number, two standards judged by |
1 | /^(([0-9]+\.?[0-9]+)|([0-9]*))$/.test("5.") |
get an array of date number arranged by [year, month, day, hour, minute, second]
1 | new Date().toLocaleString("zh").match(/[0-9]*/g).filter((el) => el).map(el => (el.length < 2 ? "0" : "") + el) |
- extract the type in the string returned by
Object.prototype.toString.call
1 | /(?<=\[object ).*(?=])/.exec(Object.prototype.toString.call({})) |
Javascript
symbol and keyword
keyword | function |
---|---|
=~ |
按位非var num1=~25;//-26 值反一次再减一 |
6%4 |
取余, c%2 !== 0 |
~~ |
取整 ~~(6 / 4) // 1 ~~(9 / 4) // 2 |
yield next yield* |
to stop or resume a generate function, yield* 加入另一个可迭代的对象 |
es6 ?. |
optional chain, stop running when null or undefined is encountered |
es6 ?? |
null ?? 4; 4 ?? 5 the right value will be returned when the left value is null or undefined |
es6 &&= |
a &&= 1 === a && (a=1) // if a is existed then assign 1 to it |
es6 ??= |
a ??= 1 === a ?? (a=1) // if a is null or undefined then assign 1 to it |
es6 ** |
指数运算符 2 ** 3 // 8 b **= 3; // equal to b = b * b * b; |
es6 symbol |
data type: designed to prevent conflicts in property naming |
delete obj.a delete an object’s own property without affecting properties that are part of the object’s prototype chain
in: to get know whether a property or an item exists
1
2var arr = [1]; console.log(0 in arr); // true
var arr = { a: 4 }; console.log('a' in arr); // truees6
… spread syntax to expand an iterable such as an array expression or string1
2
3
4
5
6
7
8
9// express rest arguments
const bar = (...args) => args
// to concat or insert items
{ ...obj1, ...obj2 }
[...iterableObj, '4', 'five', 6]
// Applying with new operator
new Date(...[1970, 0, 1])while, the expression inside the brackets can be an assigning expression
1
2
3
4
5
6var bb = 1
while (aa = bb) { // assigning the value of bb to aa, and judge aa is false or not
console.log(aa)
bb++
if (bb === 5) bb = null // bb = null, then aa = null
}break continue return,
continue
is used to break one layer of the loop1
2
3
4
5
6
7
8for (let i = 0; i < 5; i++) {
if (i === 3) break
console.log(i) // 0 1 2
}
for (let i = 0; i < 5; i++) {
if (i === 3) continue
console.log(i) // 0 1 2 4
}es6
set similar to Array, but each item inset
is unique1
2
3const items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // the length is 5, and the repeated value aren't be counted
items.add(6) // add itemes6
map similar toset
, butkey: value
structure like anobject
. thekey
of anobject
isstring
, while thekey
of amap
can be any type.1
2
3
4
5const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content')
m.get(o)
m.size // 1es6
WeakMap && WeakSet, all the properties of the two are shallow copied(weak reference), if anobject
are referenced only byWeakSet
, then thisobject
will be deleted by Garbage-Collectionexport && import && export default
variable declaration
var
if a
var
variable is not declared in a function scope, then it is aglobal object
and is mounted onwindow
can be re-declared in a same scope
1
2
3
4
5var b = 1
var b = 1
let c = 10
let c = 20 // Identifier 'b' has already been declaredvar
variables can be used before declare,var
declaration will be raising to the first line when engine is running, even the variable is declared in a block scope1
2
3
4console.log(a) // warning
let a = 1
console.log(b) // undefined
var b = 1
let, const
let
is used to declare a variable.const
declares a constant with simultaneous assignment and declaration, and its value cannot be reassigned. For reference type data, the value maintains the memory location unchanged.no variable increase
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20if (true) {
let m = 'block scope';
const n = 'block scope 2';
var k = 'global scope';
console.log(m); // block scope
console.log(n); // block scope 2
console.log(k); // global scope
}
console.log(m); // Reference Error
console.log(n); // Reference Error
console.log(k); // global scope
function a() {
var a = 1
if (a == 1) let a = 2
}
function a() {
let a = 1
if (a == 1) var a = 2 // warning
}a variable cannot be declared with the same name as a function’s arguments.
1
2(function func(arg) { var arg })()
(function func(arg) { let arg })() // SyntaxError
es6 shorthand
1 | const a = { |
iterate
for...in...
iterate object’s key and array’s indexforEach
can’t jump out byreturn
,forEach
for...of...
iterate value and can’t be used on Object
1 | Object.keys(obj) // without Symbol |
Instance’s Properties
1 | // Object.create(null) will create an object which does not inherit from Object.prototype, so the methods of Object are inaccessible. |
Object’s Properties
es6
Object.values({})
Object.keys({})
es6
Object.assign()
, copy the properties of the arguments to the first argumentes6
Object.entries({})
Object.fromEntries([])
transform object to array and vice visa1
2
3const obj = {a: 'someString', b: 42}
Object.entries(obj) // [['a', 'someString'], ['b', 42]]
Object.fromEntries(Object.entries(obj)) // {a: 'someString', b: 42}es6
Object.is(value1, value2)
compare whether two values are same, can compare objects by comparing they reference. almost same as===
, but there has two differences:1
2
3
4
5+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // trueObject.prototype.toString.call()
get data’s typees6
Object.getOwnPropertyDescriptors
es6
Object.setPrototypeOf()
Object.getPrototypeOf()
set and get the prototype of an object
JSON
JSON.parse(string)
JSON.stringify(obj)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25JSON.stringify(object: any, replacer: (key: string, value: any) => any, space: string)
const foo = {
foundation: "Mozilla",
model: "box",
week: 45,
transport: "car",
month: 7,
obj: {
a: 2,
b:[7,8]
}
};
// if replacer is a function, replacer will be called on each value to-string process
// ps: the value of the first call is the target object
JSON.stringify(foo, (key, value) => {
console.log(key, value)
if (typeof value === "number") {
return "number"
}
return value
}) // '{"foundation":"Mozilla","model":"box","week":"number","transport":"car"}'
// if replacer is an array and all the items are string, the resulting string will only keeps the {key: value} which's key is listed in the replacer
JSON.stringify(foo, ["month", "obj", "a"]); //'{"month":7,"obj":{"a":2}}'
Array
includes(item)
,item
exists or notlastIndexOf
,indexOf
returnindex
at(index)
,index
can be negative, return item of the given index1
2
3const arr = [1, 2, 3, 4, 5];
arr.at(2) // 2
arr.at(-2) // 4forEach
no return and cannot break the loop
if anitem
is deleted during the loop, the items after it will be skippedevery
all items return true => return true, any one return false => return false and break the loopsome
any item return true => true, no one return true => falsefind
findLast
|findIndex
|findLastIndex
any item return true => return the item or index(findLast return the last one),IE 11 doesn’t supportfilter
return an array constituted by items which is returned truemap
return an array constituted by the return data of the functionreduce
reduceRight
, get an accumulation from an array, the latter is executed by the order of right to left1
[1,2,3].reduce((accumulator, currentValue, currentIndex, Array) => accumulator + currentValue)
reverse
reverse the order of an arrayjoin
fill(value, start, end)
pop
/shift
remove the first / last item of an array, and return the removed itemunshift
/push
add item to the start / end of an array, and return the current length of an arraysplice
slice
, three parameters: start index, delete count, items which need to add. return the removed itemssplice
changes the original array, whileslice
create new oneconcat
concat two or more arrays, and return a new array. the items of new array areshallow copied
sort
flat
1
2
3
4// 数组降维,递归地将数组展平到指定的深度,默认为1 const array = [1, [2, [3]]];
array.flat(); // → [1, 2, [3]]
array.flat(Infinity); // → [1, 2, 3]
[2, 3, 4].flatMap((x) => [x, x * 2]); // → [2, 4, 3, 6, 4, 8]set
has(value)
value exists or notadd(value)
return the array itselfdelete(value)
boolean, delete one itemclear()
no return, clean all items
1
2[...new Set(array)] // repeated items will be deleted
Array.from(new Set(array)) // set to array
number precision issues
JS
uses the IEEE 754 double-precision (64-bit) floating-point format
. computers use the binary (base-2) number system, which cannot precisely represent many decimal (base-10) fractions. some floating-point numbers, such as 0.1 or 0.2, will translate to infinitely repeating binary fractions.
IEEE 754 stores numbers in computer memory and allocates a 64-bit storage space(1-bit for a sign(express negative or positive), 11-bit for exponent, 52 -bit for fraction) for floating-point numbers.
1 | // decimal to binary in computer |
some workarounds in js
a tolerance for comparison
1
2const epsilon = 1e-10;
console.log(Math.abs((0.1 + 0.2) - 0.3) < epsilon);string conversion
scale numbers to integers to avoid fractions.
scope
scope types
global scope
- defined at the external of the outmost function
- declared without
var
,let
andconst
- belonging to
window
ES6 Module scope
1
2
3
4
5
6
7// lib.js
var a = "a";
export var b = "b";
// main.js
import {b} from "lib";
console.log(a); // error
console.log(b); // "b"function or local scope, a variable is declared within a function, so it can’t be accessed from the outside.
block scope,
if / switch / while / for
create a block scope. a variable which is defined bylet / const
is stay in block scopestatic scope, when looking a variable, the engine will go to the scope in which the variable was created
1
2
3
4
5
6
7var x = 10
function fn() { console.log(x); }
function show(f) {
var x = 20;
fn() //10
}
show(fn);nested scope, a scope can be nested inside another scope.
scope chain
when the JS engine try to find a variable, first it will seek in the current scope, if there is no result then it will go to the parent’s scope. finding layer by layer, that is scope chain
.
1 | var a = 100 |
Memory Management
life cycle
Allocate the memory
JS automatically allocate memory whenever a value is declared
function is considered as an object
arguments needs memory allocation
1
2
3const s = "azerty";
// [0,3] range needs stored
const s2 = s.substr(0, 3);
Use the allocated memory (read, write)
- reading and writing in allocated memory
Release the allocated memory
- Garbage-Collection
Garbage-Collection
an object has a reference to its prototype
(implicit reference 隐式引用
) and to its properties values (explicit reference 显示引用
).
Reference-counting Garbage-Collection
引用计数垃圾收集
An object is said to be
garbage
, if there are zero references pointing to it.circular references
easily results inmemory leak
. two objects are reference to each other in a function scope. They will go out of the function scope after the function call has completed. they are useless after the function is called, but they will not be consideredgarbage
since they still have at least one reference.1
2
3
4
5
6
7
8function f() {
const x = {};
const y = {};
x.a = y; // x references y
y.a = x; // y references x
return
}
f()
mark and sweep algorithm
- 标记-清除算法
- An object is said to be
garbage
, if an object is unreachable. the garbage collector starts from the root which is the global object in js, and inspects all the children recursively. Starting from the roots, the garbage collector will find all reachable objects and mark them as active. Any memory not marked as active can now be considered garbage. - with this algorithm,
circular references
is no longer a problem since the objects is unreachable after the function is completely.
weakly reference
if an object is only held by weakly reference, then the object will be considered as unreachable.
The keys of WeakMap
and WeakSet
can be garbage-collected (for WeakMap
objects, the values would then be eligible for Garbage-Collection as well) as long as nothing else in the program is referencing the key
FinalizationRegistry
listen to the garbage-collect event
1 | const registry = new FinalizationRegistry(heldValue => { |
memory leak
Out of DOM references. a DOM node that was once kept in an object, even after it’s removed from the DOM tree, still persists in that object.
timers or callbacks. Most of libraries provide observers and other facilities that take callbacks.
accidental global variables. cause
mark and sweep algorithm
, a variable which is mounted onwindow
orthis
will not be consideredgarbage
- add ‘use strict’ can prevent this issue
1
2
3
4
5function foo() {
this.variable = "potential accidental global";
}
// Foo called on its own, this points to the global object (window)
foo();closure.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// seems fixed in the newly v8
var theThing = null;
var replaceThing = function () { // shared scope, shared with `unused` and `someMethod`. `unused` is never used, `someMethod` can be used through `theThing`. And as `someMethod` shares the closure scope with `unused`, even though `unused` is never used, its reference to `originalThing` forces it to stay active.
var originalThing = theThing; // holds the previous value of `theThing`
var unused = function () { // holds `originalThing`
if (originalThing)
console.log("hi");
};
theThing = {
longStr: new Array(1000000).join('*'),
someMethod: function () {
console.log(someMessage);
}
};
};
setInterval(replaceThing, 1000);
closure
closure is a combination created by binding a function to the lexical environment
. it allows you to access the outside scope from the inner of a function.
advantages
data privacy
. it means that you can’t access the data of the inner scope from the outside.privileged methods
. the methods exposed by the function are privileged because they can access data in both the inner scope and the outer scope.stateful function
. a state is a snapshot of the current environment, every change will take a picture of the current environment.1
2
3
4
5
6
7
8
9var func = () => {
let a = 3
return (b) => {
a = ++ a
return b * a
}
}
let closure = func()
closure(4) // 16partial application
refers to the process of fixing a number of arguments to a function, producing another function that takes fewer arguments than the original function. it takes advantage of closure scope in order to fix arguments.1
2
3
4
5const partialApply = (fn, ...fixedArgs) => {
return function (...remainingArgs) {
return fn.apply(this, fixedArgs.concat(remainingArgs))
}
}Function Factories
, to generate functions with pre-configured behavior or to create multiple functions with similar functionality. like debounce functionMemoization
, to cache the results of expensive function calls
Stale closure
a stale closure captures a variable whose value is outdated
createIncrement
function returns two functions,increment
andlog
. The former responsible for value increasing. the latter logs aconst
, whose value is fixed since it defined, then every time call thelog
fun, it getsmessage
which has a outdated value.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function createIncrement(incBy) {
let value = 0;
function increment() {
value += incBy;
console.log(value);
}
const message = `Current value is ${value}`;
function log() {
console.log(message);
}
return [increment, log];
}
const [increment, log] = createIncrement(1);
increment(); // 1
increment(); // 2
log(); // Current value is 0When using
setTimeout
andsetInterval
, the function delays execution, but any variables saved within the function retain their values as they were at the time the function was defined. This means that if variables change during the delay time, the function only accesses the old values of those variables.
prototype
every object has a
prototype
, from which objects inherit properties and methodsan instance inherits
prototype
fromconstructor
, which is placed on the__proto__
a
constructor
has aprototype
which includes two propertiesconstructor
andproto
. additionally, it inheritproto
fromObject.prototype
- the
prototype.constructor
refer to the default constructor - even all the built-in functions such as Object, Function, Array、RegExp、Date、Boolean、Number、String , the
prototype.proto
of them point to theObject.prototype
, that means they inherited are fromObject
, andObject.prototype.proto
refer to null.
1
2
3Person.prototype.constructor === Person // Person is a constructor, Person.prototype.constructor point to the "constructor" function self
person01.__proto__ == Person.prototype // person01 is an instance, person01.__proto__ point to a place same as Person.prototype
Array.prototype.__proto__ == Object.prototype == Object.prototype.__proto__ = null- the
property chain
when we access an object
‘s property, first the engine will try to find the property within the object itself. if it doesn’t find, it then look at the object.__proto__
. if it still doesn’t find , it continues up the __proto__
chain, checking each subsequent __proto__
. until it find Object.prototype
, in which the prototype
is null, then the engine can conclude that the property doesn’t exist.
diff between constructor and normal function
a
constructor
usually doesn’t usereturn
keyword, becausethis
of aconstructor
will be used as the result ofnew
keyword.when a
constructor
returns an object, that object will be used as the result returned by thenew
keyword. otherwise, if the result is a primitive type, thenthis
will be returned by thenew
keyword.1
2
3
4
5
6
7function Person(name) {
this.name = name;
return "Hello"; // a primitive value
}
const person1 = new Person("Alice");
console.log(person1); // Output: Person { name: "Alice" }by the first rule,
this
andnew
are used in a constructor but not in a normal functionwhat does NEW do?
- create an Object
- bind
this
of the current scope to that object - copy the prototype from the constructor, and placed it in the
object._proto_
- execute the code inside the constructor, and return the object
Inheritance
- create a child object classes which will inherit features from another class
- OO => object oriented programming
- favor object composition over inheritance
- concatenative inheritance, inherit features from another object by copying the source objects properties
- Object.assign()
- … spread syntax
- bind, call and apply(can receive an array). binding “this” to a function
1 | let beBound = { a: 1 } |
prototype delegation
new
constructor- functional inheritance / factory function. It is not a constructor or class. Instead, it operates by generating an object from a factory and extending the produced object by assigning properties to it through concatenative inheritance.
- class extend / sub-classing.
inherit everything from a class, can’t choose what you wanted
this initialization by calling the parent’s constructor with super() and can pass arguments to the parent, while in the constructor function that the new keyword does the initialization automatically.
deep and shallow copy
basic data types: data are stored in
stack
reference data types: data are stored in
heap
, whilestack
only have object’s referenceshallow copy
: copy the reference of objectdeep copy
: copy datathe following methods perform a
deep copy
only for the first layer of an object.1
2
3
4Object.assign({}, state)
{...state}
Array.prototype.concat()
Array.prototype.slice()
completely deep copy
structuredClone()
creates a deep clone of a given value(include circular references). to cloneDOM element
File
,Map
,Set
, and functions that are not part of the built-in objects, will result in an error or an incomplete copyJSON.parse(JSON.stringify())
, some complex types will be translated into string:Dates
,functions
,undefined
,Infinity
,RegExps
,Maps
,Sets
,Blobs
,FileLists
,ImageData
,sparse Arrays
,Typed Arrays
undefined
will be ignoredan object with circular references(properties are refer to each other) can’t be converted
1
2
3
4
5
6
7
8
9
10
11
12let obj = {
a: 1,
b: {
c: 2,
d: 3,
},
f: undefined,
}
obj.c = obj.b
obj.e = obj.a
obj.b.c = obj.c
obj.b.d = obj.b
MessageChannel
, data that is deliveredMessageChannel
are deep copied. but delivering a function will cause error1
2
3
4
5
6
7
8
9
10
11function deepCopy(obj) {
return new Promise((resolve) => {
const { port1, port2 } = new MessageChannel()
port2.onmessage = (ev) => resolve(ev.data)
port1.postMessage(obj)
})
}
deepCopy(obj).then((copy) => {
console.log(copy);
})
Single-threaded
a thread
is a single unit of execution. one or more thread
s can be exist in a process
. a Single-threaded
programming language which has a single-threaded
runtime engine that runs tasks in a program sequentially.
JS as a browser script, interacts with user and manipulates dom. two threads will bring synchronize problem, as if one thread changes a node, and another thread removes that node, which thread the browser should believe. therefore even in the web worker
, manipulating dom is not allowed, and web worker
is controlled by main-thread
Event Loop
Heap and Stack?
both of them are two areas in memory where data is stored.Heap
(dynamic memory allocation) stores objects which mutable and have a variable size.Stack
(Static memory allocation) store Primitive values which is immutable and have a fixed size.Call Stack
Call Stack
is in theMain-Thread
and is used to store functions for executionsynchronous and asynchronous
they are two types of js tasks.synchronous tasks
are stored in theCall Stack
, waiting for executionasynchronous tasks
likefetch
orsetTimeout
are handled by otherprocess
in the browser. JS isSingle-threaded
, but browser isMulti-process
Task Queue(Callback Queue)
followingFIFO(first in first out)
asynchronous tasks
are related withcallbacks
. if aasynchronous task
is finished by browser, then it’s correspondingcallback
will push into theTask Queue
Event Loop
if all the tasks inCall Stack
are completed, then JS engine will continuously scansTask Queue
to find tasks and push them intoCall Stack
. this process where JS engine constantly scans for tasks is called asEvent Loop
.
throughEvent Loop
, JS engine can handleasynchronous tasks
, and meanwhile keeps the responsive of the pageCall Frame
every call of function will leave aCall Frame(调用帧)
, which keeps the inner information about function including variables and the location where the function called. those information will be deleted after the function is completed.following
LIFO(last in first out)
1
2
3
4
5// put C into stack => B in => A in => A out => B out => C out
function funA() { console.log('funA') };
function funB() { funA() }
function funC() { funB() }
funC()two types of tasks in Task Queue, Macro and Micro
Macro tasks
includesetImmediate(Deprecated)
/setTimeout
/setInterval
/MessageChannel
/requestAnimationFrame
/UI render
/I/O in node.js
Micro tasks
include theonerror
andthen
callback.setImmediate -> MessageChannel -> setTimeout 0
the engine checks
Macro Task
first and theMicro Task
second.Promise initialize and resolve are synchronous
.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20setTimeout(function () {
console.log(1)
}, 0)
var p1 = new Promise(function (resolve, reject) {
console.log(2)
setTimeout(function () {
console.log(4)
resolve(1)
}, 0)
})
setTimeout(function () {
console.log(3)
}, 0)
for (var i = 0; i < 5; i++) {
;(function (j) {
p1.then(function (value) {
console.log("promise then - " + j)
})
})(i)
}
async
await
, look at the following example:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20async function async1(){
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2(){
console.log('async2')
}
console.log('script start')
setTimeout(function(){
console.log('setTimeout')
},0)
async1();
new Promise(function(resolve){
console.log('promise1')
resolve();
}).then(function(){
console.log('promise2')
})
console.log('script end')async1()
doesn’t haveawait
prefix,async1
will be translated by v8 like:1
2
3
4
5
6
7
8// `async2` is Promise initialization, so it‘s a synchronous
// the code after `await` will be put in `then` callback
function async1(){
console.log('async1 start')
Promise.resolve(async2).then(()=>{
console.log('async1 end')
})
}Tail Call 尾调用
refers to calling another function “at the end” of a function’s execution.1
function a(x) { return b(x) }
b
is aTail Call
. givenCall Stack
, when a function is called, it creates aCall Frame
that holds internal information until the call is completed. whileTail Call
is the final action, theCall Frame
will be kept untilTail Call
is finished.- optimize
Tail Call
to reduce stack space usage, is calledTail call optimization
.
Tail Recursion
due tofcall frame
,Recursion
often consumes a significant amount of memory and resultsstack overflow
in languages that supportTail call optimization
,Tail Recursion
can be used to avoid such issues1
2
3
4
5
6
7// the recursive call is the last operation performed by the function
// the call frame associated with that recursive call can be discarded or reused.
function factorial(n, acc = 1) {
if (n === 0) return acc;
return factorial(n - 1, n * acc); // Tail recursion
}
console.log(factorial(5)); // Output: 120
debounce and throttle
debounce
. a function can be executed when it is not called during a specific time1
2
3
4
5
6
7
8
9
10
11// execute debounce => got a function which bound with the debounce scope
// every time the instance executed that will clean and reassign the timer
const debounce = (func, delay) => {
let timer
return function () {
const context = this, args = arguments
clearTimeout(timer) // to clean before reassign
timer = setTimeout(() => func.apply(context, args), delay)
}
}
const instance = debounce(function () { console.log("executing") }, 3000)throttle
. a function can be executed only when the time is up1
2
3
4
5
6
7
8
9
10
11
12
13
14// execute throttle => got a function which bound with the throttle scope
//when the isExpired is true, that means that the function can be executed and when it executed, then change the isExpired's state to false and set a time to change back
const throttle = (func, delay) => {
let isExpired = true
return function () {
const context = this
const args = arguments
if (isExpired === false) return
func.apply(context, args)
isExpired = false
setTimeout(() => isExpired = true, delay)
}
}
const instance = throttle(function () { console.log("executing") }, 3000)
breakpoint resume
web: fileReader + slice + FormData
server: createWriteStream + createReadStream
messageChannel
- to communicate between two
iframe
s /web worker
s /js module
s - deep copy
generator
use generator
to simulate async function
1 | function run(fn: any) { |
vue vs react
both of them are component-based architecture
Vue
- considered easier to learn for beginners due to its simpler syntax and clear documentation.
- use a Single File Component (SFC) which contains a template section for HTML markup, a script section for JS logic, and a style section for CSS.
- has a growing community, most libraries are developed by the official team.
- has a powerful two-way data binding system, keeping data and the UI in sync.
1 | <!-- The input value is bound to the 'msg' data property --> |
React
- has a steeper learning curve due to its extensive ecosystem and more complex concepts.
- uses JSX (JS XML), this allows to write HTML-like code in js files. JSX may be more powerful and expressive.
- has a larger ecosystem and community support, with many third-party libraries and tools available.
- follows a one-way data flow, explicitly manage state and re-render components when needed.
- data flows in a one-way direction, from outside to inside, and from top to bottom. this ensures a simple and predictable data flow
the differences between class component and function component can considered as the difference between vue and react. since vue uses class component
- no
this
issues in function components, you don’t have to do scope bonding - code lesser with function component, but worse maintaining
- doesn’t need to manage state and life cycle
architectural patterns
MVC
- Model - View - Controller
model
contains data model, and describes how the data can be changed and manipulated.view
is UI components. it receives data from the model (via the controller) and display it to the user.controller
sits betweenmodel
andview
, processing the data from themodel
and passing back to theview
for rendering.- view and model can interact with each other directly, so it’s coupled.
MVVM
- Model – View – ViewModel
view
andmodel
are same as inMVC
ViewModel
sits below the UI layer, acts as a bridge between the View and Model. Unlike the Controller in MVC, it doesn’t handle user interactions directly. it binds data between the View and Model, and ensures that the View reflects the state of the Model and vice versa.view
andmodel
can’t interact with each other, it’s decoupled.- vue and react can be vm or mvvm, early Angular is mvc.
active view and passive view
- the later only outputs UI and doesn’t accept user’s input, contains zero logic
- the former contains events, data binging, and behaviors
Typescript
references
setting tsconfig for specific file
diff with js
pro
- object-orient language static type checking. it can find low level bugs, like spelling mistake, incorrect or instanceof variable properties
- type infer.
- optional parameters
- enum support
- better support in IDE, like intelliSense of editor, auto-supplement
- the type files can increase code reading ability, and make the project maintaining easer
.d.ts
can be viewed as specifications- to identify incompatible interfaces when the field name changed
con
- compiling step is required, and it may take a long time.
- abstract class is not support
- definition files for a third library is required
- pollutes the code with type gymnastics
type judgement
Generics
keyof
typeof
indexed access:
User["name]
map types, use
-
or+
to remove readonly or optional modifier1
2
3
4
5
6
7
8
9
10type OptionsFlags<Type> = {
[Property in keyof Type]: Type[Property]
}
// change all readonly or optional properties to normal
type CreateMutable<Type> = {
-readonly [Property in keyof Type]: Type[Property];
};
type Concrete<Type> = {
[Property in keyof Type]-?: Type[Property];
};
Diff of null
and undefined
null
means an absence of valueundefined
means not initialized
Diff of .ts
and .d.ts
.d.ts
file is a declaration file, and would not be complied as ajs
file- in a
.d.ts
file, if we want it act as a global declaration, then we have to use/// Triple-Slash Directives
to import dependencies /// <reference types="node" />
is used for importing an outside module, while/// <reference types="./global.d.ts" />
is for importing a localdeclaration
file
- in a
Diff of type
and interface
type
is used to declare a type alias, act like a variable. while interface introduce a named object type.1
2
3// get the type of a variable to deduct (a part) of a payment from (the total)
let div = document.createElement("div")
type B = typeof divinterface
, can be declared repeatedly, but atype
cannot1
2
3
4
5
6
7
8interface User {
name: string;
age: number;
}
interface User {
sex: string;
}
/* { name: string; age: number; sex: string } */
features
- satisfies
is used to ensure that an expression meets certain constraints without altering the type of the expression.
circular references
1
2interface LocalRes<T> { [x: string]: T }
type LocalResPackage = LocalRes<LocalResPackage | string>new
describe the shape of a constructorabstract
to mark a class withabstract
, means that the class is only meant to be extended from, can’t be used directly1
2
3
4
5
6
7
8abstract class Shape {
abstract getArea(): number;
}
new Shape(); // error Cannot create an instance of an abstract class.
class Square extends Shape {}
new Square(3) // rightextends
conditional typesSomeType extends OtherType ? TrueType : FalseType;
1
2
3// if Dog extends from Animal, then Example = number, otherwise Example = string
type Example = Dog extends Animal ? number : string;infer
can be used to unpack type, to get the item’s type of an array, the return value’s type or the parameter’s type of a function1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// if T is a function ? the return value of the function : any
type Unpack<T> = T extends (...args: any[]) => infer R ? R : any;
// if T is an Array ? R : T
type Unpack<T> = T extends Array<infer R> ? R : T
// the item type of array
typeof UserChosen[number]
// if R is Reducer ? Reducer's first parameter S : never
type ReducerState<R extends Reducer<any, any>> = R extends Reducer<infer S, any> ? S : never;
type Reducer<S, A> = (prevState: S, action: A) => S;
// get the parameter type of a constructor
abstract class AbstractClass {
constructor(a: string, b: number) { }
}
export type InferAbstract<T> = T extends abstract new (...args: infer Args) => infer _ ? Args : never; // new a function which return a value, infer the parameter as Args, mark the value as abstract class, if T is a abstract class ? Args : never
type Result = InferAbstract<typeof AbstractClass> // [a: string, b: number]decorators, use the form
@expression
, where the expression must infer to a function.1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19function first() {
console.log("first(): factory evaluated");
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("first(): called");
};
}
function second() {
console.log("second(): factory evaluated");
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("second(): called");
};
}
class ExampleClass {
@first()
@second()
method() {}
}Record
1
2
3
4
5
6type AnyObject = Record<string, any>
type Coord = Record<"x" | "y", number>
type Coord = {
x: number,
y: number,e
}Readonly
Partial
Required
: all the properties are Readonly or selectable or required1
2
3
4
5type Coord = Partial<Record<"x" | "y", number>>
type Coord = {
x?: number,
y?: number,
}Pick
omit
: to pick or omit some properties from a given type1
2
3type Coord = Record<"x" | "y", number>
type CoordX = Pick<Coord, "x">
type CoordX = Omit<Coord, "x">ReturnType
Parameters
, the former is used for getting the output of a function, while the later is used for a function’s input1
2let timer: ReturnType<typeof setTimeout>
Parameters<(props: Event) => void>typeof
1
2const zed: Hero = { name: "影流之主", skill: "影子" };
type LOL = typeof zed; // type LOL = Herokeyof
collecting key1
2
3
4interface Person { name: string; age: number; location: string; }
type K1 = keyof Person; // "name" | "age" | "location"
type K2 = keyof Person[]; // number | "length" | "push"|"concat" | ...
type K3 = keyof { [x: string]: Person }; // string | numberenums
1
2
3
4
5
6
7
8
9
10
11enum Themes {
default = "_default",
thinkuem = "_thinkuem",
safeuem = "_safeuem",
}
// collect all the values of an enum, but the types of all the values will be inferred as string, even some values are number or string
type ThemesVal = `${Themes}`
// generate a interface
type ThemesVal = Record<Themes, string>
// collect all the keys of a enum
type ThemesVal = keyof typeof Themestemplate literal type,a set of every possible string literal that could be represented by each union member
1
2
3type a = 1 | 2 | 3
type b = 4 | 5 | 6
type ab = `${a}_${b}` // "1_4" | "1_5" | "1_6" | "2_4" | "2_5" | "2_6" | "3_4" | "3_5" | "3_6"template literal
has four convenient featuresUppercase
Lowercase
Capitalize
Uncapitalize
1
2
3type PropEventSource<Type> = {
on(eventName: `${string & keyof Type}Changed`, callback: (newValue: any) => void): void;
};type assertion,
as
or<>
syntax1
2
3
4
5let value: unknown = "Foo";
let len: number = (value as string).length;
let len: number = (<string>value).length;
// response is changed in the interceptor, so the first type parameter <unknown> indicates that the response type is not known or specified.
client.post<unknown, EquipmentUptime>(api.insert, data);is
1
2
3export function foo(arg: string): arg is MyType {
return ...
}in
1
console.log('model' in car); // boolean
this
1
2
3
4
5
6
7class Box<T> {
value?: T;
hasValue(): this is { value: T } {
return this.value !== undefined;
}
}as const
to infer in an explicitly way, infer 1 to 1 instead of number, infer false to false instead of boolean1
2
3
4
5
6let x = [0, 1] as const; // let x: [0,1]
// another write pattern: let x = <const>[0, 1];
let x = [0,1] // let x: number[]
let y = [10, 20] as const; // Type 'readonly [10, 20]'
let z = { text: "hello" } as const; // Type '{ readonly text: "hello" }'any
extends object
instead ofany
when reference to an objectvoid
is used when a function’s output isnull
orundefined
, if a fun does not usereturn
keyword then its value isundefined
unknown
is a type-safe of any type. you can narrow downunknow
to any type by type assertionnever
is used when a function can’t end which means it can’t return a value even an undefined. to express an empty object1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16function get<T extends object, K extends keyof T>(o: T, name: K): T[K] {
return o[name]
}
let foo: unknown = "hello";
let bar: string = foo as string;
function login(data: LoginForm): void {}
function login(data: LoginForm): never {
while (true) {}
}
function login(data: LoginForm): never {
throw new Error("error");
}
type EmptyObject = Record<string, never>map types
, to generate a type According to a map object, and can be agenerics
1
2
3type OptionsFlags<Type> = {
[Property in keyof Type]: boolean;
};index access
for looking up a specific property of a type1
type Age = Person["age"]
generics
generate a type with a specific params1
2
3
4function identity<T>(arg: T): T {
return arg
}
let myIdentity: <Type>(arg: Type) => Type = identityimplements
, to check that whether a class is satisfied the contract specified by one or above interfaces1
2
3
4
5
6
7
8
9interface Runnable {
run(): void;
}
class Job implements Runnable {
run() {
console.log("running the scheduled job!");
}
}triple slash directives, to introduce other files in the compiling process
1
/// <reference path="..." />
class modifiers
- public
- protected: All the members of the class and its child classes can access them, But not the instance of the class.
- private: Only the members of the class can access them.
useful tricks
reduce
method needs to provide the initial type and the return type when the return type is not same with the type of array item1
reduce< [string, Lan], { [k: string]: Lan }>((a, c) => {})
refer to React component
1
2new() => React.Component<any, any>
typeof React.Componentpromise type
, the argument’s type ofresolve
is number, while the argument’s type ofreject
is infer to any1
2
3
4
5function test(arg: string): Promise<number> {
return new Promise<number>((resolve, reject) => {
arg === "a" ? resolve(1) : reject("1");
});
}the resolve type of promise
1
type resolve = Awaited<ReturnType<typeof drawSlogan>>
to override a property of a interface extended
1
2
3interface ColorPickerProps extends Omit<BasicProps<string>, "change"> {
change: import("react-color").ColorChangeHandler
}use
map
andliteral
to create new property names1
2
3type Getters<Type> = {
[Property in keyof Type as `get${Capitalize<string & Property>}`]: () => Type[Property]
};to extend html attributes
1
2
3
4
5declare module "react" {
interface DOMAttributes<T> {
name?: string
}
}
React
life cycle
Mount Phase
initialize
- class:
constructor
- fun: inside the function
- class:
before render
class:
getDerivedStateFromProps
, React will call it right before calling render, both on the initial mount and on subsequent updates. It should return an object to update the state, or null to update nothing.fun: compare the state and then return the appropriate result within the function
1
2
3
4
5
6
7
8
9
10
11function ScrollView({row}) {
const [isScrollingDown, setIsScrollingDown] = useState(false);
const [prevRow, setPrevRow] = useState(null);
if (row !== prevRow) {
setIsScrollingDown(prevRow !== null && row > prevRow);
setPrevRow(row);
}
return `Scrolling down: ${isScrollingDown}`;
}
rendering
after render
- class:
componentDidMount
- fun:
useEffect()
with an empty dependency array
- class:
Update Phase
before update
class:
getDerivedStateFromProps
=>shouldComponentUpdate
fun:
useMemo
for shallowly comparing1
2
3
4
5// MyComponent will only re-render if the value prop changes
const MyComponent = React.memo(({ value }) => {
// Component logic
return <div>{value}</div>;
});
rendering
- class:
getSnapshotBeforeUpdate(prevProps, prevState)
it could return a value as the third argument ofcomponentDidUpdate
- fun: use
useRef
to get the old and new state - class:
componentDidUpdate
- fun:
useEffect()
with watched data
- class:
unmount stage
- class:
componentWillUnmount
- fun: the returned function of
useEffect()
- class:
Error Handling
getDerivedStateFromError(error)
: allow the component to capture errors in its children when they occur during renderingcomponentDidCatch(error, info)
: It can log error information and display a fallback UI when an error is thrown by a child component.
view updating
props changing
In React, data flows in a one-way direction, from outside to inside, and from top to bottom. To ensure this simple and predictable data flow, props
are kept read-only
state changing:useState(), useReducer(), redux state
the data will not update immediately when we call setState
, multiple updates from different components will be merged into a single re-render automatically. it’s called batching update
.
the process
setState
setState(partialState)
=> mergespartialState
into the current state
=> ifisBatchingUpdates === true
(is react in the batch updating status), then push this update into_pendingStateQueue
(the queue of pending updates) , else setisBatchingUpdates = true
and re-call the previous step
=> callwaper()
to iterate_pendingStateQueue
to execute update
=>componentWillReceiveProps
=> to merge the states to get the new state
=>componentShouldUpdate
, and then determines whether to continue the update process
=>componentWillUpdate
=>render
=>componentDidUpdate
even an empty object like
this.setState({})
will also trigger a new update cyclethe updated data can be achieved in callback
setTimeout
or native events can step over React asynchronous behavior and achieve a sync response1
2
3
4
5
6
7
8
9componentDidMount(){
setTimeout(() => {
this.setState({ number: 3 })
console.log(this.state.number) // 3
}, 0)
}
componentDidMount() {
document.body.addEventListener('click', this.changeVal, false)
}ReactDOM.flushSync()
in v18, this method is used when you don’t want to applyautomatic batching
. updates in this method will be update immediately, and it’s a sync method, since we know thatsetState
is a async method.
1 | import { flushSync } from 'react-dom'; // Note: react-dom, not react |
context, this is shallowly compare
forceUpdate(), only support in class component, and shouldComponentUpdate()
will be skipped
dom changing through ref
or native dom handlers
components conversation
- parent to children: props
- children to parent: callbacks inside the parent props, event bubbling(eventually, events will bubble up to the parent)
- between brother: find the common parent node, and then through the above methods
- context, other global state management tools
- ref
- importing a module and interacting within module scope
JSX
- every file should import react, as long as
jsx
code is contained- cause
jsx
will be translated bybabel
toReact.createElement()
- cause
- a custom component name should begin with a capital letter
- if the first letter is lowercase, the component will be treated as a native html element. this rule helps to differentiate custom components from standard HTML tags.
- a component should only return one element
- virtual dom is a tree structure, only one root is allowed
- return multiple elements: return an array of elements,
<React.Fragment></React.Fragment>(<></> is a syntax sugar)
high order component
- HOC is a function, which accepts a component and additional arguments, then returns a new component that maintains a similar interface to the original one.
- HOC’s name begins with
with
, such aswithButton
1 | type HOC = (component: React.component, props) => React.component |
features
- It allows for the addition or modification of the props of a component, enabling us to handle complex or dirty business logic without affecting the original component.
- unifying the data source. such as
connect
in redux. - to renders different components based on data. e.g., rendering after login can help avoid setting up multiple routers.
- If multiple components have the same dependencies, instead of importing the function into each component separately, we can apply the function to different components using HOC
container
andcomponent
. The former handles logic, while the latter receives props fromcontainer
and is only responsible for rendering.
Render Props
- it is a mode, a component with
a callback
which accepts component’s data and return React elements - tips: try not use
Render Props
withpureComponent
, becausethis callback
will return a new value after parent re-render. whilepureComponent
is shadow compare for reduce the times of children re-render, but withRender Props
the result of compare will always be false.
1 | <DataProvider render={data => ( |
render prop
is kind of a simplyHOC
1 | <Mouse render={mouse => <Component {...this.props} mouse={mouse} />}/> |
ref
- ref is a way for accessing dom
- create ref by
React.createRef()
oruseRef()
- it is not support to access
ref
directly on afunction component
which does not have ref instance.
callback ref
- differ from
React.createRef()
, pass a function to components is also allowed - a better way is use with
useCallback()
hook, then it wouldn’t be executed every time after component updated
1 | const inputRef = (node) => { |
ref forwarding
- Ref forwarding lets components opt into exposing any child component’s ref as their own.
- we can customize the data exposed to the outside using
useImperativeHandle()
. - to access child node from a parent component for triggering focus or measuring the size or position of a child dom.
- it is useful in
HOC
, like assigning ref to input’s ref in a input component
1 | function FancyInput(props, ref) { |
hooks
- each component has an initial list of “memory cells”, when we call a hook like
useState()
, it reads the current cell or initializes it during the first render.- hook is a function which lets you to “hook into”
React state
and lifecycle features from function components.- use pure function as much as possible
useState() keeps the local state in a function component, when we update a state variable, react replaces the state instead of merging it like
this.state()
in class component.1
2
3
4// fun will only execute once when the component initialize
const [goodGet, goodSet] = React.useState(() => fun(0))
// fun will execute every time the component re-render
const [badGet, badSet] = React.useState(fun(1))useReducer(), store a complicated state, act like a small redux in a component.
useRef(), store data, and the value returned remains valid throughout the entire life cycle
useEffect() / useLayoutEffect()
- one is called after the data is updated, the another is called after the DOM is updated.
1
2
3
4
5
6
7
8
9
10// empty dependency array
useEffect(() => {
// mounted = componentDidMount and componentDidUpdate
return fun() // unmount = componentWillUnmount
}, [])
// specific dependency array
useEffect(() => {
// updated
return fun()// componentWillUnmount and componentWillUpdate
}, [id])useContext() accept a context object created by
createContext()
and returns the current context value.. it’s used when components of different nesting levels need to access the same data.1
const value = useContext(MyContext)
createContext() accept a default value and returned a context object which has three properties. context will shallowly compare the properties of value to decide whether it should re-render.
1
const MyContext = React.createContext(defaultValue)
use useContext() with useReducer()
allows passing callbacks to children, avoiding the need to pass callbacks layer by layer.
create a context object for passingdispatch
to children, so any child within the component can get thedispatch
byuseContext
.provider
: a react component, that allows to consume components to subscribe to context changes.consumer
: a react component, that allows components to subscribe to context valuedisplayName
: can be modified directly, and is showed in DevToolscontextType
: a property on a class component can be assigned a Context object
1
2
3
4
5
6
7< MyContext.Provider value = {/* some value */ } />
<MyContext.Consumer>
{value => /*you can return a component and assign the value to it*/}
</MyContext.Consumer>
MyContext.displayName = 'MyDisplayName'useCallback() / useMemo() accept a function and an array of dependencies
- the former memorizes the received function, while the latter memorizes the value returned by the received function
useCallback()
allows to keep same callback after re-render, and is recommend to use ascallback ref
to get dom node after mound
1
2
3
4const measuredRef = useCallback(node => {
console.log(node);
}, []);
<h1 ref={measuredRef}>Hello, world</h1>custom hook
- It allows for the sharing of stateful logic, rather than the state itself. Its purpose is to encapsulate reusable logic.
useTransition
useDeferredValue()
- Using the staled value allows de-prioritizing the updating of a part of the UI. Deferring the re-rendering of that part serves as a performance optimization to prevent it from blocking the rest of the UI. this effect may similar to
debounce
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// in this case, SlowList is running slowly and should update in response to user input. This indicates that SlowList is blocking user input and the rendering of this component.
// With the help of useDeferredValue, the dependencies are delayed to update, consequently causing SlowList to be delayed.
function App() {
const [text, setText] = useState('');
const deferredText = useDeferredValue(text);
// the re-call of SlowList depends on the deferredText
const SlowList = useMemo(function SlowList({ text }) {}, [deferredText]);
console.log(deferredText, text)
return (
<>
<input value={text} onChange={e => setText(e.target.value)} />
<SlowList/>
</>
);
}- what’s happened?
useDeferredValue
is realized byuseTransition
anduseEffect
under the react hood- input
1
=>setText
executes,text
updates to1
=> render(text
= 1,deferredText
= “”) => thecallback
ofuseEffect
executes => UpdatedeferredText
to matchtext
=> render(text
= 1,deferredText
= “”)
- Using the staled value allows de-prioritizing the updating of a part of the UI. Deferring the re-rendering of that part serves as a performance optimization to prevent it from blocking the rest of the UI. this effect may similar to
difference between class and hook
class component
is hard to reconstruct and decomposecompilation of
class component
will generate a lot of auxiliary functionsclass component
requirethis
when passing a function to a component1
2
3
4
5
6
7
8
9
10
11// by a arrow-function. when the parent refresh, a new arrow function will be generated and the offspring will refresh, even the received props haven't change
<button onClick={() => this.handleClick1()}> btn3 </button>
// by bind. the side effect of this is same with the last one
<button onClick={this.handleClick1.bind(this)}> btn2 </button>
// to declare in the constructor, but it cannot pass parameters
constructor(props) { this.handleClick1 = this.handleClick1.bind(this) }
// by the static property of class, same with the last one
handleClick3 = () => { }no
this
issues in function components, which helps to avoid problems with scopecode lesser with function component, but worse maintaining
doesn’t need to manage state and life cycle
key
when an array re-rendering, React will check each list item according to the last render. if an inexistent item of the last render is found in the current render, then react will create an new element. if an item of the last render is altered in the current render, then react will delete the old one and create a new one.
- The index of an item in an array is Lack of Stability, since it can be changed if items are added, removed, or reordered.
- When items are added or removed from the list, React may need to re-render the reset items
shouldComponentUpdate VS pureComponent
- the former is in the life cycle of class components, by return a boolean to decide whether to continue update
- the later can shallowly compare props and states
- both of them are helpful for avoiding needless re-render.
fiber
stack Reconciliation(differ process)
- current tree and WIP(working-in-progress) tree react creates
WIP tree(working-in-progress)
based oncurrent tree
which marks the current view.WIP tree
is used to perform updates under the hood. - React uses
DFS(depth first search)
to traverse two virtual dom tree, comparing the new and old props, as well as thecurrent tree
with theWIP tree
, to identify changed nodes and determine which needs to be updated, this process called Reconciliation. The result ofReconciliation
will be applied to thecurrent tree
. - during
Reconciliation
, the traversal process can cause performance problems as the DOM tree grows larger, and it cannot be stopped once it’s started. React occupies the resources of the browser until it’s finished, so when handling complex views, it can lead to blocking in the main thread, resulting in unresponsiveness in the page.
what is fiber
- React saves references to the
return(parent)
,sibling
, andchild
nodes, the data structure is similar tolinked list
. This more powerful representation of the virtual DOM tree is known asFiber
. Fiber
‘s references enable React to memorize the work in progress, and then pause and resume theReconciliation
process.
Fiber structure
- React slices the process of
Reconciliation
into small pieces, this is calledtime slicing
. It gives control to the browser to respond to user interactions and then takes back control to continue it’s work slice by slice(react => browser => react => browser ….). this mechanism of handling control is known as Fiber structure. in theFiber structure
, react gives control to browser to respond to user interactions at the right time, creating the perception of faster responsiveness.
fiber Reconciliation(differ process)
- In the
Fiber structure
, duringReconciliation
, React saves the nodes that haseffect(require changes)
in thefiber
‘s’ propertyeffectTag
, and usesnextEffect
to link those nodes inlinked list
structure. - After
Reconciliation
, React steps into the commit phase. During thecommit phase
, React applies all theeffects
toWIP tree
in one go, while this process cannot be interrupted.
Concurrent Mode
- with
time slicing
, react ables to bounce back and forth between multiple tasks, and pause one task while other more urgent task are seen to. once the more urgent one are done, then jump back the less urgent one, bringing with the updated information from the more urgent one. useTransition
, this hook is used to wraps a less urgent update.
DFS(depth first search) 深度优先遍历 a search algorithm used for traversing or searching tree or graph data structures.
linked list 链表, a common data structure used to store a collection of elements, where each element is connected to the next one through a node. Each node contains two parts: data and a reference (or pointer) to the next node.
controlled and uncontrolled
they are two different approaches to managing form inputs and components
controlled
is driven byprops
orstate
, following one-direction data flow.uncontrolled
is driven bydom
itself, and retrieves value byref
.1
2
3
4
5// uncontrolled
<input type="text" ref={inputRef} />
// controlled
<input value={state.value} onChange={handleChange} />controlled components
offer more control and are preferred in most cases, whileuncontrolled components
can be useful in certain scenarios. In many cases, a mix ofcontrolled
anduncontrolled
components may be the best approach- for form inputs where real-time validation, formatting or data manipulation is not required.
uncontrolled components
can minimize state management overhead and improve performance. - when integrating with external libraries like date pickers or rich text editors, using controlled components allows these libraries to manage their own state
- for form inputs where real-time validation, formatting or data manipulation is not required.
Built-in React Components
Fragment
1 | // explicitly writing form is required when pass key to a `Fragment` |
Profiler
1 | // measure rendering performance of a React tree. but adds some additional overhead, so it is disabled in the production build by default |
Suspense + dynamic import + lazy loading
lazy loading
should always be declared at the top level of modules.- with webpack code splitting, each module loaded by
import()
will be split to separate files. - Data fetching, Lazy-loading by
lazy
fallback
will be used if any ofthe children
suspend while waiting for data. nesting multipleSuspense
components can create a loading sequence for revealing a component as it loads.
1 | const MarkdownPreview = lazy(() => delayForDemo(import('./MarkdownPreview.js'))); |
Portal
to render a component within other nodes. it can be used for dialog or message components
1 | ReactDOM.createPortal(child,container) |
StrictMode
- enables additional checks and warnings for its descendants. it‘s used in the DEV mode only.
- under
StrictMode
, setState updaters run twice.
redux
concept
A(change) –> B(send an action
to store
) –> C(store
dispatch the action to a reducer
) –> D(the reducer
return a new state to store
) –> E(state
changed) –> G(execute listeners
)
- store a container created by
createStore()
, where data is changed and saved. - state data, an object
- action An object include a required
type
property and other business related properties. The different values of thetype
determine the number of actions that a store can perform. - reducer a function, receive an
action
,and return a newstate
. it automatically triggered bystore.dispatch()
Reducers
should be as the parameter pass to thecreateStore()
when initialize thestore
.
Redux Methods
createStore()
,reducers
as parameter is required, an initial state, the third argument is enhancer likemiddleware
provider
allow the redux hooks and connect to componentsstore.getState()
get the present statestore.dispatch()
sending an action to reducerstore.replaceReducer()
Replaces the reducer currently used by the store.combineReducers()
organize your reducers to manage their own slices of state. accept an object whose values are different reducing functions and turn it into a single reducing function you can pass tocreateStore
.1
combineReducers({ todo: myTodoReducer, counter: myCounterReducer })
bindActionCreators
is wrap action into dispatch1
2
3type actionCreator = (payLoad: any) => {...{type: string }, ...payload}
type dispatchAction = (payLoad: any) => dispatch(actionCreator(payLoad))
(actionCreators: actionCreator | actionCreator[], dispatch: Function) => dispatchAction | dispatchAction[]store.subscribe()
receives an listeners function and return a function in which you can disengage the listener.connect
return a function which like aHOC
accepts a component and wrap it to subscribe store’s updates and able to dispatch actions.how it works?
withProvider
component provided by redux we can wrap a component and get the component’s context and children, then any nested components can accessstore
withHooks
andconnect
1
2
3
4
5
6
7
8
9
10
11
12
13
14(mapStateToProps: mapStateToProps, mapDispatchToProps: mapDispatchToProps, mergeProps: mergeProps, options) => ((component) => connectedComponent)
// combine state and component's props and pass to the component, if this argument is passed to the components, then mapStateToProps will be executed as every time the store and own-props are updated.
type mapStateToProps = (state: object, ownProps?: object) => stateProps
// wrap actions as a part of props pass to the component
type mapDispatchToProps = (dispatch: Function, props?: object) => dispatchProps
// return an object as a result of mapStateToProps and mapDispatchToProps
type mergeProps = (stateProps, dispatchProps, ownProps) => mapStateToProps & mapDispatchToProps
type stateProps = any
interface dispatchProps {
dispatchPlainObject: () => dispatch(action)
}middleware
is used to inject a third-party in the redux processing, allow you to do sth (like logging, crash reporting, talking to an asynchronous API, routing, and more) after an action is dispatched and before a reducer update the state.1
(getState: store.getState, action, next: (action) => void) => void
action => middleware => reducer => state
next
is used to passaction
to the next middleware. you can pass the current action to continue the middleware chain or pass another action.middleware chin
: an action can have an array of middleware that is linked bynext
.- tips: if
next
is used in a middleware for passing another action, then that action will be directly to the reducer and will not go through its own middleware chain
- tips: if
- use
dispatch
inside a middleware will stop current middleware chain and start another middleware chin. - it is not different, either use
dispatch
, ornext
, or do nothing to stop middleware chain.
redux-toolkit
- core api
- createAction,createReducer
- createSlice:including
createAction
andcreateReducer
- PayloadAction:
ts
泛型,用以声明action.payload
createAsyncThunk
accepts a Redux action type string and a callback function that should return a promise. return a standard Redux thunk action creator
V19
- useActionState
- useFormStatus
- only returns status information for a parent
<form>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21function Submit() {
const { pending } = useFormStatus()
return (
<button type="submit" disabled={pending}> {pending ? "Submitting..." : "Submit"} </button>
)
}
function Username() {
const { pending, data } = useFormStatus()
console.log("Username", data?.getAll("username"))
return <input type="text" name="username" disabled={pending} />
}
function Form() {
const { pending } = useFormStatus()
console.log("Form", pending) // always false
return (
<form action={submitForm}>
<Username />
<Submit />
</form>
)
}
- only returns status information for a parent
- useOptimistic
Vue
2x: Object.defineProperty
3x: Proxy, setter and getter
computed
- similar to memo(), the function will re-evaluate when some of its reactive dependencies have changed
- a
computed
variable can be re-written by a setter1
2
3
4
5
6
7
8
9
10
11const fullName = computed({
// getter
get() {
return firstName.value + ' ' + lastName.value
},
// setter
set(newValue) {
// Note: we are using destructuring assignment syntax here.
[firstName.value, lastName.value] = newValue.split(' ')
}
})
nextTick() a callback after a state change to wait for the DOM updates to complete.
web3
window.ethereum (an EIP-1193 compliant provider)
Web3.givenProvider
vite
based on rullup, integrating features like code splitting , cache and more from rullup, and provides a development server or HMR out of the box
turpopack
currently support nextjs only
webpack
module building, browser compatibility, code compressing, code splitting, lazy loading
building process
- generate a config from the
webpack.config.js
and the command line. - use
compiler
module to create acompilation
instance which has access to all modules and their dependencies. execute thecompiler.run()
to start working.compiler
andcompilation
are the heart of webpack, both of them extend fromtapable
. - analysis process is started from the
entry
file. useacron parser
to generates AST(Abstract Syntax Tree / 抽象语法树) for theentry
file. - traverse through entire AST to create a dependency graph. at this stage, if webpack find any matched
rules
forloader
s, the loaders will convert those codes(e.g. css files) into js, and thenParser
parses them into AST. - this process will be repeatedly executed for the each dependency, to recursive traverse.
- bundle all the files.
- in the above process
- webpack compiles the different types of file to js file by
loader
sloader
is responsible for file converting. every file type can have more than one loader, those loaders will be invoked with method chaining in order. so the output of a loader will be the arguments of the next loader.
compiler
will throw some hooks when webpack starts/stops, emit assets, watch mode etc. those events can be listened byplugin
and allowsplugin
to intervene the result of output.plugin
can extends features. listen events sended by compiler allows a plugin to effect the result.
- webpack compiles the different types of file to js file by
optimization
tree shaking
compress code
by some plugins, liketerser
,css minimize
code splitting
, useimport()
to split code into multiple chunk andlazy-loading
them.import()
can cooperate withsuspense
feature in react.
boost build time
- webpack cache strategies
- get precise time by
speed-measure-webpack-plugin
, like how long the engine spends in each plugin / loader - save time from each plugin or loader
- ts-loader, use
happyPackMode
ortranspileOnly
to turn off type checking. the former will implicitly setstranspileOnly: true
and will not reports syntactic errors. it is usually used withhappypack
. fork-ts-checker-webpack-plugin
works for ts type checking in a separate process which runs in parallel with webpack
- ts-loader, use
tree shaking
after checking
import and export
,tree shaking
will remove the modules which is imported but doesn’t be used. from this point, what method do we use to import file is critical, and we can knowtree shaking
only supportsES module
.to import the specific modules instead of the whole library
1
2
3
4
5
6// Import everything (NOT TREE-SHAKABLE)
import _ from 'lodash';
// CAN BE TREE SHAKEN
import { debounce } from 'lodash';
import debounce from 'lodash/lib/debounce';side effect
refer to a function will effect the variables or scope outside the functionhowever, the border between
used
andnot used
is not clean, some modules are started to work when it is imported. sinceobject
is reference type, which means that if a function’s arguments are object, then any changes on we made on it will be easily effect the data outside the function. so there has a propertysideEffects
in thepackage.json
to tellwebpack
whether should betree shaking
.1
2
3
4
5
6
7
8
9
10
11// all the modules have/haven't side effects, and then can't/can be tree shaking
{
"sideEffects": true/false
}
// give webpack an array with side effects
{
"sideEffects": [
"./src/file1.js",
"./src/file2.js"
]
}
module federation
to expose some of our components to the outside, and therefor which can be used in other projects.
this feature is considered as an idea of micro-frontend
HTTP
http: HTTP > TCP > IP > MAC
https: HTTP(application) > SSL/TSL(application) > TCP(transport) > IP(internet) > MAC(link)
http2: HTTP > HPack and Stream> SSL/TSL > TCP > IP > MAC
http vs https
http
requests are sent in plaintext. HTTPS addsSSL/TLS protocol
betweenTCP
andHTTP
for encrypting datahttp
uses80 port
as default, whilehttps
uses403
as default- friendly to SEO. Search engines like Google prefer HTTPS websites
- HTTPS is seen as a trust signal which will be indicates by browser
three-way handshake is used to establish TCP connection, to ensure that the service and the client both can send and receive data
- The client sends a SYN packet (SYN = synchronize) to the server, and specifying its initial sequence number. (client can send and server can receive).
- the server responds with a packet containing both SYN and ACK(Acknowledgement Number) flags. (server can send)
- the client sends back an ACK packet. (client can receive).
- what it’s used for
- prevent historical connection
127.0.0.1, localhost, 0.0.0.0
- localhost is domain, equal to 127.0.0.1 which is
loopback address(回环地址)
- localhost is domain, equal to 127.0.0.1 which is
URL
- Reserved characters :
: / ; ? #
encodeURI
decodeURI
, don’t encode reserved charactersencodeURIComponent
decodeURIComponent
encode reserved characters
- Reserved characters :
CORS
same origin policy
, requires same protocol
, domain
and port
http versions
- http1.0
- http1.1
connection:keep-alive
feature allows for long-lasting connections- supports
pipeline transport
(but it’s not allowed in browsers) - It compresses only
body
, excludingheader
. - the server responds to requests in the order they were received, a delay in one request can cause subsequent requests to be blocked. This issue is known as
head-of-line blocking(队头阻塞)
- http2.0
- Compress both the header and body. Both the client and the server maintain a dynamic table of header information. Every header field is stored in this table and assigned an index number. For headers with the same name, only the index number will be sent. this called
HPACK
- uses binary format, reducing the step of transforming requests into binary form
- introduces
Stream
concept, allowing multiple requests and responses to be sent and received concurrently within a single TCP connection.- multiple streams exist in one tcp connection, and own a stream-id as an identifier. a full request (request and correspondent response) can be split in frames and then sent with the same stream identifier.
- a stream is initiated when client or server sends bytes.
- server push. since the server can create stream
Head-of-line blocking
still exists in the TCP layer. TCP is a byte-oriented protocol, and data is only sent to the application layer when the received bytes are complete. Packet loss triggers TCP to resend the missing packets, which can block all the requests.
- Compress both the header and body. Both the client and the server maintain a dynamic table of header information. Every header field is stored in this table and assigned an index number. For headers with the same name, only the index number will be sent. this called
- http3.0
methods
post | put | delete
contain request body for saving data.get
: retrieve data, safe and can be cachedpost
: creating new resources, submitting form data, or sending large amounts of data that cannot be sent in a URL query string.put
: updating existing resources
headers
Content-Disposition
: a response header which is indicating if the content is expected to be displayed inline in the browser,or as an attachment to downloaded and saved locally.1
2
3// inline or attachment
res.set('Content-Disposition', 'attachment; filename=foo.fdf');
res.send(_res)
http cache
memory cache, disk cache
- cache use priority: Service Worker -> Memory Cache -> Disk Cache -> Push Cache
- memory cache: fast but limited in time; cache is deleted when the browser is closed.
- disk cache: need I/O operations during read and write
strong cache
headers
, priority:pragma
<=cache-control
<=expires
Expires
, an absolute date which is the expire date of the current resourceCache-Control
max-age:5000
, Specifies the maximum amount of time in secondsno-store
,strong cache
is not allowedno-cache
, submit a request to the server for validation before usingstrong cache
private
public
Pragma: no-cache
, for compatibility with older HTTP/1.0 caches.
negotiated cache
headers
Last-Modified
/Last-Modified-Since
,ETag
/If-None-Match
Last-Modified
set by the server, represents the last modified date of the current resourcesETag
, set by the server, a hash code represents the current resourceLast-Modified-Since / if-none-match
sent by the client with the value ofLast-Modified / ETag
from the previous response. The server compares the values in the request with the current values. If they match, the server responds with304 Not Modified.
client scenarios
- press
f5
to refresh: setsCache-Control:max-age:0;
, means the cache is invalid ctrl + f5
force to refresh, setsCache-Control:no-cache
code
- 1XX- Informational
- 2XX- Success
- 3XX - Redirection
- 301 vs 302, 301 is permanent redirection, while 302 is temporary redirection. For permanent redirects, the browser caches the redirection location, so the cached location is used the next time.
- 4XX - Client Error, 400 Bad Request, 401 Unauthorized, 404 Not Found
- 5XX - Server Error, 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable
https optimization
- reduce the number of request
- use http cache
- combine small and light requests, like small images
- use compress as needed
lossless compression
,Accept-Encoding: gzip, deflate
Content-Encoding: gzip
lossy compression
,Accept: audio/*; q=0.2, audio/basic
, q refer to the number of quality
thread and process
real-time communication
SSE
http long-lasting connection
plain text only
one-way communication, server to client
standard HTTP connection
Websocket
plain text and binary format
bidirectional communication, server to client and client to server
use HTTP handshake, and then upgrade to ws
protocol
long-polling
extending the time of timeout, and the server holds the request open until it has new data to send to the client or until a timeout occurs
NPM
1 | npm version patch // v1.0.1 |
- control the files of a package
- define the
file
field in thepackage.json
- use
.npmignore
which is used as same asgitignore
- define the
Vscode
short key | function |
---|---|
Ctrl+Shift+[ | 折叠 |
Ctrl+Shift+] | 展开 |
ctrl+d | 选中单词 |
alt+shift+鼠标点选 | 多个位置 |
alt +鼠标点选 | 选中 |
alt + z | word break |
ctrl + shift + L | pitch on the same words simultaneously |
ctrl + shift + p | show command menu |
Setting json | C:\Users\tong\AppData\Roaming\Code\User |
Line break | “files.eol”: “\n” |
ctrl + g | go to a specif line |
search patterns
symbol | example | explain |
---|---|---|
OR或者管道符号(竖线) | x OR y | 返回x或者y的信息,或者和两者都相关的信息 |
AND | x AND y | 返回和两者都相关的信息 |
- 短横线 | x -y | 排除一个相似的容易造成误导的词语,返回x相关的信息而不是y,注意: 符号-和y之间没有空格 |
* 通配符 | x * y | 匹配任何信息 |
() 括号 | (x OR y) -z | 将多个款项和符号组合搜索 |
$ 美元符号 | iphone $2000 | 价格搜索 |
define: | define:china | 显示谷歌内置的词典,以卡片形式展现 |
cache: | cache:https://github.com | 返回该页面最新缓存版本 |
filetype: 或者 ext: | 个人简历 filetype:pdf | 返回符合指定的文件类型的信息 |
site: | js site:github.com | 将搜索限制在某个指定的网站 |
related: | related:github.com | 查找和给定域名相关的站点 |
intitle: | intitle:github | 返回所有标题中包含“github”的信息 |
allintitle: | allintitle:github js | 和intitle类似,返回标题中包含所有单词的信息 |
inurl: | inurl:github | 和intitle类似,不同的是匹配的是url而不是标题 |
allinurl | allinurl:github js | 同上 |
intext: | intext:github | 和intitle类似,不同的是匹配的是内容而不是标题 |
allintext: | allintext:github js | 同上 |
AROUND(X) | apple AROUND(4)iphone | 间隔限制,单词“apple”和“iphone”必须出现在内容中,并且相隔不超过四个单词。 |
weather: | weather:san francisco | 查找指定位置的天气 |
stocks: | stocks:aapl | 查找指定的股票信息 |
map: | map:silicon valley | 地图搜索 |
movie: | movie:steve jobs | 电影搜索 |
in | $329 in GBP | 单位转换,前者向后者转换 |
source: | apple source:the_verge | 在google News中查找来自某个来源的新 |
terms
en | ch |
---|---|
closed testing | 精密测试 |
records
2023/7/19
CSS filter
can formstacking context
input
‘s’ propertyhidden
does not work in Safari
2024/11/15
- Vertical or horizontal lines with gradient strokes in SVG won’t display.
Keyword objectBoundingBox should not be used when the geometry of the applicable element has no width or no height, such as the case of a horizontal or vertical line, even when the line has actual thickness when viewed due to having a non-zero stroke width since stroke width is ignored for bounding box calculations. When the geometry of the applicable element has no width or height and objectBoundingBox is specified, then the given effect (e.g., a gradient or a filter) will be ignored.
https://stackoverflow.com/questions/21638169/svg-line-with-gradient-stroke-wont-display-if-vertical-or-horizontal- change pattern to “userSpaceOnUse”
- Gradually add a tiny amount to the values, ensuring they are not vertical or horizontal
2024/11/26
- yarn network problem, change mirror is not work and the network is fine with the official mirror url “https://registry.yarnpkg.com"
- delete .lock file can work, but of couse i cannot do it. so instead delete the lock file, i changed all the mirror in the .lock file, this will helps a little.
- increase the network timeout is working, the default value is 30 seconds.
yarn install --network-timeout 1000000
2024/11/27
- rn error, can find a package, because jcenter is derprecated
1
2
3
4
5Execution failed for task ':app:checkDevDebugAarMetadata'.
> Could not resolve all files for configuration ':app:devDebugRuntimeClasspath'.
> Could not find updateapputils-2.3.0.aar (com.teprinciple:updateapputils:2.3.0).
Searched in the following locations:
https://jcenter.bintray.com/com/teprinciple/updateapputils/2.3.0/updateapputils-2.3.0.aar - assembleRelease: Builds the release version for the entire project (all modules).
app:assembleRelease: Builds the release version for the app module specifically, which is often the main module in an Android project.