目录
records
彻底搬到北京了
回顾基础
底层逻辑依然是跟着roadmap走
js
1.简介
- 是什么
- 历史
- 版本
- 如何运行
deno,node,bun
bunx shadcn-ui@latest add button
2.关于变量
- 变量声明 var let const
- 变量提升
- 命名规则
- 函数作用域 块 函数 全局
3.数据类型
- 原始数据类型 string undefined bigint number null Symbol Boolean
- Object 内置Objects 例如 String , Number 继承,原型 原型链
- typeof
4.type casting
In programming language, casting is a way of telling the compiler to change an expression or value from one type to another
- 显式类型转换
- 隐式类型转换
- 类型转换vs强制类型转换
5.数据结构
A Data structure is a format to organize, manage and store data in a way that allows efficient access and modification. JavaScript has primitive (built-in) and non-primitive (not built-in) data structures. Primitive data structures come by default with the programming language and you can implement them out of the box (like arrays and objects). Non-primitive data structures don’t come by default and you have to code them up if you want to use them.
-
key集合 Map,WeakMap,Set,WeakSet
-
结构化数据
Structured data is used by search-engines, like Google, to understand the content of the page, as well as to gather information about the web and the world in general.
JSON
-
索引集合
-
类型化数组 JavaScript 类型化数组是一种类似数组的对象,并提供了一种用于在内存缓冲中访问原始二进制数据的机制. 这部分有点难,缓冲和视图那里,基本上只会手抄别人的模板,这里的mdn文章需要精读
-
数组
-
6.相等性比较
-
操作符 == === Object.is()
-
相等算法 IsLooselyEqual:== IsStrictlyEqual:=== SameValue:Object.is() SameValueZero:被许多内置运算使用
通常情况下,唯一需要关注 Object.is 对零的特殊行为的时机是在实施特定的元编程范式时,特别是涉及属性描述符时,当你的工作需要镜像 Object.defineProperty 的某些特性时.如果你的用例不需要这样做,建议避免使用 Object.is,而改用 ===.即使你的要求涉及将两个 NaN 值之间的比较计算为 true,通常特殊处理 NaN 检查(使用先前版本的 ECMAScript 中提供的 isNaN 方法)比解决相关计算如何影响零的符号更为简单.
7.循环和遍历
- for
- do while
- while
- conditional statements ifelse/Switch
- for in
- for of
- break/continue labeled statements
8.control flow
-
Conditional Statements
if/else Switch
-
Exception Handling 异常处理 throw
try/Catch/finally
Utilizing Error Objects 利用错误对象
Error构造函数:
AggregateError 聚合错误
EvalError EvalError(评估错误)
InternalError 内部错误
RangeError 范围错误
ReferenceError 引用错误
SyntaxError 语法错误
try {
willGiveErrorSometime();
} catch (error) {
if (error instanceof RangeError) {
rangeErrorHandler(error);
} else if (error instanceof ReferenceError) {
referenceErrorHandle(error);
} else {
errorHandler(error);
}
}
9.表达式与运算符
这里只记一些之前不知道的/记不太清楚的:
- delete
delete Math.PI; // returns false (cannot delete predefined properties)
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
delete trees[3];
if (3 in trees) {
// 不会被执行
}
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
trees[3] = undefined;
if (3 in trees) {
// this gets executed(会被执行)
}
- typeof
typeof null === "object";
typeof undefined === "undefined";
- void
你可以使用 void 运算符指明一个超文本链接.该表达式是有效的,但是并不会在当前文档中进行加载.
如下创建了一个超链接文本,当用户单击该文本时,不会有任何效果.
<a href="javascript:void(0)">Click here to do nothing</a>
下面的代码创建了一个超链接,当用户单击它时,提交一个表单.
<a href="javascript:void(document.form.submit())">Click here to submit</a>
- this 指代当前的对象
function validate(obj, lowval, hival) {
if (obj.value < lowval || obj.value > hival) console.log("Invalid Value!");
}
<p>Enter a number between 18 and 99:</p>
<input type="text" name="age" size="3" onChange="validate(this, 18, 99);" />
- 数值推导(实验性)
[for (i of [ 1, 2, 3 ]) i*i ];
// [ 1, 4, 9 ]
var abc = [ "A", "B", "C" ];
[for (letters of abc) letters.toLowerCase()];
// [ "a", "b", "c" ]
Comprehensions 特性被许多编程语言所采用,该特性能够使你快速地通过一个已有的数组来创建出一个新的数组
10.函数
// ES2015
const args = Array.from(arguments);
const args = [...arguments];
function myConcat(separator) {
var args = Array.prototype.slice.call(arguments, 1);
return args.join(separator);
}
myConcat.apply(null, ["-", ";", "."]);
- 作用域与函数调用栈
调用栈是解释器(比如 Web 浏览器中的 JavaScript 解释器)用来追踪其在调用多个函数的脚本中所处位置的机制——当前正在运行的函数是哪一个,以及在该函数内部调用了哪些函数,等等.
当脚本调用一个函数时,解释器就会把该函数添加进调用栈,然后开始执行这个函数. 正在调用栈中执行的函数调用的其他任何函数也将会被添加进调用栈.一旦这个函数被调用,便会立即执行. 当前函数执行完毕后,解释器将其清出调用栈,继续执行当前执行环境下的剩余的代码. 当分配的调用栈空间被占满时,会引发“堆栈溢出”错误.
递归/词法作用域/闭包
- 内置函数
11.严格模式
12.使用this关键字
react
1.cli tools
vite/create react app
2.components
class components
import React, { Component } from "react";
interface LifecycleExampleState {
counter: number;
}
class LifecycleExample extends Component<{}, LifecycleExampleState> {
constructor(props: {}) {
super(props);
this.state = {
counter: 0,
};
console.log("Constructor");
}
static getDerivedStateFromProps(
nextProps: {},
nextState: LifecycleExampleState
) {
console.log("getDerivedStateFromProps", nextProps, nextState);
return null;
}
componentDidMount() {
console.log("componentDidMount");
}
shouldComponentUpdate(nextProps: {}, nextState: LifecycleExampleState) {
console.log("shouldComponentUpdate", nextProps, nextState);
return true;
}
getSnapshotBeforeUpdate(prevProps: {}, prevState: LifecycleExampleState) {
console.log("getSnapshotBeforeUpdate", prevProps, prevState);
return null;
}
componentDidUpdate(
prevProps: {},
prevState: LifecycleExampleState,
snapshot: null
) {
console.log("componentDidUpdate", prevProps, prevState, snapshot);
}
componentWillUnmount() {
console.log("componentWillUnmount");
}
static getDerivedStateFromError(error: Error) {
console.log("getDerivedStateFromError", error);
return null;
}
componentDidCatch(error: Error, info: React.ErrorInfo) {
console.log("componentDidCatch", error, info);
}
handleIncrement = () => {
this.setState(prevState => ({
counter: prevState.counter + 1,
}));
};
render() {
console.log("Render");
return (
<div>
<h1>Counter: {this.state.counter}</h1>
<button onClick={this.handleIncrement}>Increment</button>
</div>
);
}
}
export default LifecycleExample;
函数式组件
import React, { useState, useEffect, useReducer } from "react";
interface LifecycleExampleProps {
initialCounter: number;
}
interface LifecycleExampleState {
counter: number;
}
type Action = { type: "increment" } | { type: "decrement" };
const counterReducer = (
state: LifecycleExampleState,
action: Action
): LifecycleExampleState => {
switch (action.type) {
case "increment":
return { ...state, counter: state.counter + 1 };
case "decrement":
return { ...state, counter: state.counter - 1 };
default:
return state;
}
};
const LifecycleExample: React.FC<LifecycleExampleProps> = ({
initialCounter,
}) => {
const [state, dispatch] = useReducer(counterReducer, {
counter: initialCounter,
});
useEffect(() => {
console.log("Component Did Mount");
return () => {
console.log("Component Will Unmount");
};
}, []); // Empty dependency array means it runs once on mount and once on unmount
useEffect(() => {
console.log("Counter Value Changed:", state.counter);
}, [state.counter]); // Runs whenever counter value changes
const handleIncrement = () => {
dispatch({ type: "increment" });
};
const handleDecrement = () => {
dispatch({ type: "decrement" });
};
console.log("Render");
return (
<div>
<h1>Counter: {state.counter}</h1>
<button onClick={handleIncrement}>Increment</button>
<button onClick={handleDecrement}>Decrement</button>
</div>
);
};
export default LifecycleExample;
组件基础:
- jsx(javascript xml)
const jsx = <h1>This is JSX</h1>;
React.createElement(type, [props], [...children])
=>
{
"type": "h1",
"props": {
"children": "This is JSX"
}
}
class JSXDemo extends React.Component {
render() {
const jsx = <h1>This is JSX</h1>;
console.log(jsx);
return jsx;
}
}
ReactDOM.render(<JSXDemo />, document.getElementById("root"));
- props vs state
一个是传递给组件的,一个是在组件内部进行管理的 使用props传递父组件控制的数据和回调函数,确保子组件的行为由父组件控制. 使用state管理组件内部的状态和数据,确保组件能够根据用户交互或其他内部逻辑动态更新.
-
条件渲染
-
Composition vs Inheritance
在React中,组件之间的代码复用主要通过组合(Composition)来实现,而不是继承(Inheritance).React团队建议使用组合而不是继承来实现组件的复用,因为组合更符合React的设计哲学,即”组合优于继承”.
继承会导致组件之间的耦合度更高,不利于代码的复用和维护.
组件渲染
- 组件生命周期 使用 useEffect 模拟生命周期方法
import React, { useState, useEffect } from "react";
function MyFunctionComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
// componentDidMount 和 componentDidUpdate 的组合
console.log(`Count has been updated to: ${count}`);
return () => {
// componentWillUnmount
console.log("Cleanup");
};
}, [count]); // 只有 count 改变时才会触发
const incrementCount = () => {
setCount(prevCount => prevCount + 1);
};
return (
<div>
<p>Count: {count}</p>
<button onClick={incrementCount}>Increment</button>
</div>
);
}
export default MyFunctionComponent;
-
Lists and Keys
-
render props
React Render Props 通过一个值为函数的 prop 动态决定组件渲染内容的技术 指一个用于告知组件该渲染什么内容的函数 prop.通过这种模式,可以在不使用高阶组件(HOC)或 context 的情况下共享组件逻辑
例如
import React, { Component, type ReactNode } from "react";
// 定义 Mouse 组件的 props 类型
interface MouseProps {
render: (state: MouseState) => ReactNode;
}
// 定义 Mouse 组件的 state 类型
interface MouseState {
x: number;
y: number;
}
class Mouse extends Component<MouseProps, MouseState> {
constructor(props: MouseProps) {
super(props);
this.state = { x: 0, y: 0 };
this.handleMouseMove = this.handleMouseMove.bind(this);
}
handleMouseMove(event: React.MouseEvent<HTMLDivElement>) {
this.setState({
x: event.clientX,
y: event.clientY,
});
}
render() {
return (
<div style={{ height: "100vh" }} onMouseMove={this.handleMouseMove}>
{this.props.render(this.state)}
</div>
);
}
}
export default Mouse;
使用
import Mouse from "./mouse";
function App() {
return (
<div>
<p>Move the mouse around!</p>
<Mouse
render={({ x, y }) => (
<p>
The current mouse position is ({x}, {y})
</p>
)}
/>
</div>
);
}
export default App;
结果
Move the mouse around!
The current mouse position is (0, 0)
- Refs
import React, { useRef, useEffect } from "react";
function MyComponent() {
const myRef = useRef(null);
useEffect(() => {
myRef.current.focus(); // 获取焦点
}, []);
return <input ref={myRef} />;
}
类组件中
import React, { Component } from "react";
class MyComponent extends Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
componentDidMount() {
this.myRef.current.focus(); // 获取焦点
}
render() {
return <input ref={this.myRef} />;
}
}
- Events
SyntheticEvent =>事件处理函数
React使用合成事件而不是原生DOM事件,因此某些特性可能与原生DOM事件有所不同(例如,事件委托)
在使用函数组件时,事件处理函数可以直接作为 JSX 中的箭头函数定义,而不需要将它们作为类方法来定义.
合成事件对象在每次事件触发时都会被重用,因此如果你想在异步代码中访问合成事件属性,需要在事件处理函数中调用 event.persist() 方法,以确保事件对象在异步代码中仍然可用.
demo:
import React, { Component } from "react";
class MyComponent extends Component {
handleClick = event => {
console.log("Button clicked!");
};
render() {
return <button onClick={this.handleClick}>Click me</button>;
}
}
export default MyComponent;
-
High Order Components
高阶组件(Higher Order Components,HOC)是一种用于增强组件功能的模式.它是一个函数,接受一个组件作为参数,并返回一个新的组件.通过高阶组件,你可以在不修改原始组件代码的情况下,添加新的功能或修改现有功能.
demo
import React from "react";
function withLogger(WrappedComponent) {
return class extends React.Component {
componentDidMount() {
console.log("Component is mounted");
}
render() {
return <WrappedComponent {...this.props} />;
}
};
}
// 使用高阶组件增强组件功能
const EnhancedComponent = withLogger(MyComponent);
以下是一个更具体的示例,演示了如何使用高阶组件来添加身份验证功能:
import React from "react";
// 定义一个高阶组件,用于身份验证
function withAuthorization(WrappedComponent) {
return class extends React.Component {
componentDidMount() {
// 模拟检查用户是否已登录
const isAuthenticated = true;
if (!isAuthenticated) {
// 如果用户未登录,则重定向到登录页面
this.props.history.push("/login");
}
}
render() {
return <WrappedComponent {...this.props} />;
}
};
}
// 创建一个需要身份验证的组件
class MyProtectedComponent extends React.Component {
render() {
return <div>Protected content</div>;
}
}
// 使用高阶组件增强组件功能
const EnhancedComponent = withAuthorization(MyProtectedComponent);
勾子 hooks
-
basic hooks useState/useEffect
-
自定义hooks
-
common hooks
Routers路由控制
react router/reach router
源码学习
- React 不再使用 requestIdleCallback,而改用 scheduler 包来管理任务调度,这是因为 scheduler 包提供了更强大和精确的任务调度功能,支持任务优先级管理,能够更好地优化任务执行顺序和性能
问题解决,详细见react相关
1.react17之前jsx文件为什么要声明import React from ‘react’,之后为什么不需要了
在 React 17 之前,显式引入 React 是为了确保 JSX 被正确编译为 React.createElement 调用.而在 React 17 之后,通过引入新的 JSX 转换功能,编译器会自动处理所需的引入
2.jsx和Fiber有什么关系
JSX 是用于编写组件的语法糖,而 Fiber 是用于优化 React 应用性能的底层机制
3.Fiber是什么,它为什么能提高性能
Fiber 是一种重新实现的协调算法,旨在增强 React 处理 UI 更新的能力.
它将更新工作分成更小的任务单元,可以在需要时中断和恢复这些任务,从而提高响应能力.
4.componentDidMount和useEffect的区别是什么
使用场景:
componentDidMount 只能在类组件中使用.
useEffect 只能在函数组件中使用.
依赖管理:
componentDidMount 只会在组件挂载后执行一次.
useEffect 默认在每次渲染后都会执行,但可以通过依赖数组来控制其执行时机.如果依赖数组为空([]),它的行为类似于 componentDidMount,只在组件挂载后执行一次.
清理副作用:
componentDidMount 本身没有清理副作用的机制,需要在 componentWillUnmount 方法中处理清理逻辑.
useEffect 可以直接返回一个清理函数,在组件卸载或者依赖项变化时自动执行该清理函数.
5.scheduler与fiber
区别与联系
React 的 Scheduler 和 Fiber 是两个不同但相互关联的组件,它们在 React 应用中扮演了不同的角色,分别负责任务调度和组件更新.以下是它们的区别与联系的详细解释:
Fiber
定义和作用:
- Fiber 是 React 的新的协调引擎,它重新设计了 React 的核心算法,用于更高效地管理组件更新和渲染.
- 核心目标:通过分割可中断的工作单元来提高 React 的性能,使得渲染过程能够被中断和恢复,从而保持应用的响应性.
主要特性:
- 时间分片:将渲染工作拆分成多个小任务,可以在主线程空闲时执行这些任务.
- 优先级管理:支持对不同任务分配不同的优先级,高优先级任务(如用户交互)会被优先处理.
- 增量渲染:允许在更新过程中中断并恢复任务,减少长时间的主线程阻塞,提升用户体验.
- 链表结构:使用链表结构来组织和遍历组件树中的 Fiber 节点,使任务调度更加灵活和高效.
Scheduler
定义和作用:
- Scheduler 是一个独立的包,用于任务的调度和优先级管理.
- 核心目标:提供一个高效的任务调度机制,确保高优先级任务能够及时执行,而低优先级任务在主线程空闲时处理.
主要特性:
- 任务优先级:支持将任务分为不同的优先级,如 Immediate(立即)、User-blocking(用户阻塞)、Normal(普通)、Low(低)和 Idle(空闲).
- 时间分片:调度器可以在时间片内执行任务,并在每个时间片结束后将控制权交还给浏览器,从而避免长时间阻塞主线程.
- 任务调度:调度器根据任务的优先级和过
期时间(deadline)来决定何时执行哪些任务,确保高优先级任务优先得到处理.
Fiber 和 Scheduler 的联系与区别
联系
-
目标一致:
- 提高性能和响应性:Fiber 和 Scheduler 都旨在提高 React 应用的性能和响应性.Fiber 通过增量渲染和时间分片实现,而 Scheduler 通过高效的任务调度和优先级管理实现.
-
协同工作:
- Fiber 使用 Scheduler 进行任务调度:在 React 应用中,Fiber 引擎会将需要执行的工作单元提交给 Scheduler,由 Scheduler 来决定这些工作单元的执行时机和顺序.
- 协调任务执行:Scheduler 负责管理任务的调度,而 Fiber 负责具体的协调和渲染工作.两者协同工作,共同实现高效的组件更新和渲染.
区别
-
职责不同:
- Fiber:主要负责组件树的协调和渲染.它使用链表结构来组织组件,并通过时间分片和增量渲染来优化更新过程.
- Scheduler:主要负责任务的调度和优先级管理.它根据任务的优先级和过期时间来安排任务的执行,以确保高优先级任务得到及时处理.
-
实现层级:
- Fiber 是 React 的内部机制:Fiber 是 React 的核心引擎部分,直接管理组件树的更新和渲染.
- Scheduler 是一个独立的任务调度库:Scheduler 可以独立于 React 使用,用于任何需要高效任务调度的场景.它提供了基础设施,使 Fiber 可以更灵活地进行任务管理.
示例说明
假设我们有一个需要高频更新的动画组件,同时还有一些用户交互任务(如按钮点击).下面是 Fiber 和 Scheduler 如何协同工作的示例:
- 动画任务(低优先级)和 用户交互任务(高优先级)被提交给 Fiber.
- Fiber 将这些任务按优先级和依赖关系组织成 Fiber 节点,并使用 Scheduler 来调度这些任务的执行.
import {
unstable_scheduleCallback as scheduleCallback,
unstable_NormalPriority as NormalPriority,
unstable_UserBlockingPriority as UserBlockingPriority,
} from "scheduler";
// 动画任务
function startAnimation() {
scheduleCallback(NormalPriority, () => {
// 动画逻辑
console.log("Animating...");
});
}
// 用户交互任务
function handleClick() {
scheduleCallback(UserBlockingPriority, () => {
// 用户交互逻辑
console.log("Button clicked!");
});
}
// 在组件挂载时启动动画
useEffect(() => {
startAnimation();
}, []);
// 在按钮点击时处理用户交互
<button onClick={handleClick}>Click me</button>;
在这个示例中:
- 动画任务被设为
NormalPriority
,因此在主线程空闲时执行. - 用户交互任务被设为
UserBlockingPriority
,确保在用户点击按钮时能够及时响应.
总结
- Fiber 和 Scheduler 的区别在于它们的职责和实现层级:Fiber 是 React 内部的协调引擎,负责组件树的更新和渲染;Scheduler 是独立的任务调度库,负责任务的优先级管理和调度.
- Fiber 和 Scheduler 的联系在于它们的协同工作:Fiber 通过 Scheduler 来高效地调度和管理任务,确保 React 应用的高性能和响应性.通过这种协作,React 能够更好地处理复杂的用户界面更新和交互操作.
计算机网络
tips/小知识
- in
const car = { make: "Honda", model: "Accord", year: 1998 };
console.log("make" in car);
// Expected output: true
delete car.make;
if ("make" in car === false) {
car.make = "Suzuki";
}
console.log(car.make);
// Expected output: "Suzuki"
- ??
Nullish coalescing operator 空值合并运算符
0 ?? 42; //0
null ?? "some"; //some
??只在第一个操作数为null 或 undefined 时(而不是其他假值)返回第二个操作数