1.位运算 #

1.1 比特 #

bit

0b1000=2*2*2=Math.pow(2,3)=8=0~7

1.2 数值数据 #

1.2.1 无符号数据的表示 #

1.2.2 有符号数据的表示 #

1.2.2.1 原码 #

1.2.2.2 反码 #

1.2.2.3 补码 #

1.3 位运算 #

运算 使用 说明
按位与(&) x & y 每一个比特位都为1时,结果为1,否则为0
按位或() x y 每一个比特位都为0时,结果为0,否则为1
按位异或(^) x ^ y 每一个比特位相同结果为0,否则为1
按位非(~) ~ x 对每一个比特位取反,0变为1,1变为0
左移(<<) x << y 将x的每一个比特位左移y位,右侧补充0
有符号右移(>>) x >> y 将x的每一个比特位向右移y个位,右侧移除位丢弃,左侧填充为最高位
无符号右移(>>>) x >>> y 将x的每一个比特位向右移y个位,右侧移除位丢弃,左侧填充为0
let a = 0b100;//4
let b = 0b011;//3
console.log((a & b).toString(2));//000 0
console.log((a | b).toString(2));//111 7 
console.log((a ^ b).toString(2));//111 7 
//按位非运算时,任何数字x的运算结果都是-(x + 1)。例如,〜4运算结果为-5
console.log((~a));//-5
console.log((~a).toString(2));//111
let a = 0b001;
//左移
console.log((a << 2).toString(2));// 0b100

//无符号右移(>>>) 丢弃被移除的位 左侧补0
let b = 0b100;
console.log((b >>> 1).toString(2));// 0b010

//有符号右移(>>) 丢弃被移除的位 左侧填充最高位
let c = 0b101;//-3    110
console.log((-3 >> 1));

1.4 使用 #

//定义常量
const OP_INSERT = 1 << 0; // 0b001
const OP_REMOVE = 1 << 1; // 0b010

let OP = 0b000;
//增加操作
OP |= OP_INSERT;
OP |= OP_REMOVE;
console.log(OP.toString(2));//0b11

//删除操作
OP = OP & ~OP_INSERT;
console.log(OP.toString(2));//0b10

//判断包含
console.log((OP & OP_INSERT) === OP_INSERT);
console.log((OP & OP_REMOVE) === OP_REMOVE);
//判断不包含
console.log((OP & OP_INSERT) === 0);
console.log((OP & OP_REMOVE) === 0);

1.5 ES5规范 #

1.6 Hydration #




1.7 React中的应用场景 #

//一共有16种优先级
//同步优先级
const SyncLanePriority = 15;
const SyncBatchedLanePriority = 14;
//离散事件优先级
const InputDiscreteHydrationLanePriority = 13;
const InputDiscreteLanePriority = 12;
//连续事件优先级
const InputContinuousHydrationLanePriority = 11;
const InputContinuousLanePriority = 10;
//默认优先级
const DefaultHydrationLanePriority = 9;
const DefaultLanePriority = 8;
//渐变优先级
const TransitionHydrationPriority = 7;
const TransitionPriority = 6;
const RetryLanePriority = 5;
const SelectiveHydrationLanePriority = 4;
//空闲优先级
const IdleHydrationLanePriority = 3;
const IdleLanePriority = 2;
//离屏优先级
const OffscreenLanePriority = 1;
//未设置优先级
const NoLanePriority = 0;
/**
 * 一共有31条车道
 */
const TotalLanes = 31;
//没有车道,所有位都为0
const NoLanes = 0b0000000000000000000000000000000;
const NoLane = 0b0000000000000000000000000000000;
//同步车道,优先级最高
const SyncLane = 0b0000000000000000000000000000001;
const SyncBatchedLane = 0b0000000000000000000000000000010;
//离散用户交互车道 click
const InputDiscreteHydrationLane = 0b0000000000000000000000000000100;
const InputDiscreteLanes = 0b0000000000000000000000000011000;
//连续交互车道 mousemove
const InputContinuousHydrationLane = 0b0000000000000000000000000100000;
const InputContinuousLanes = 0b0000000000000000000000011000000;
//默认车道
const DefaultHydrationLane = 0b0000000000000000000000100000000;
const DefaultLanes = 0b0000000000000000000111000000000;
//渐变车道
const TransitionHydrationLane = 0b0000000000000000001000000000000;
const TransitionLanes = 0b0000000001111111110000000000000;
//重试车道
const RetryLanes = 0b0000011110000000000000000000000;
const SomeRetryLane = 0b0000010000000000000000000000000;
//选择性水合车道
const SelectiveHydrationLane = 0b0000100000000000000000000000000;
//非空闲车道
const NonIdleLanes = 0b0000111111111111111111111111111;
const IdleHydrationLane = 0b0001000000000000000000000000000;
//空闲车道
const IdleLanes = 0b0110000000000000000000000000000;
//离屏车道
const OffscreenLane = 0b1000000000000000000000000000000;

/**
 * 分离出所有比特位中最右边的1
 * 分离出最高优先级的车道
 * @param {*} lanes 车道
 * @returns 车道
 */
function getHighestPriorityLane(lanes) {
    return lanes & -lanes;
}

//console.log(getHighestPriorityLane(InputDiscreteLanes));//8 0b1000
//console.log('0000000000000000000000000011000');
//console.log('1111111111111111111111111101000');

/**
 * 分离出所有比特位中最左边的1
 * 分离出最低优先级的车道
 * @param {*} lanes 车道
 * @returns 车道
 */
function getLowestPriorityLane(lanes) {
    const index = 31 - Math.clz32(lanes);
    return index < 0 ? NoLanes : 1 << index;
}
console.log(getLowestPriorityLane(InputDiscreteLanes));//16 0b10000
console.log('0000000000000000000000000011000');
console.log(Math.clz32(InputDiscreteLanes));//27
console.log(31 - Math.clz32(InputDiscreteLanes));//4

2. 最小堆 #

2.1 二叉树 #

2.2 满二叉树 #

2.3 完全二叉树 #

2.4 最小堆 #

2.5 SchedulerMinHeap.js #

react\packages\scheduler\src\SchedulerMinHeap.js

export function push(heap, node) {
  const index = heap.length;
  heap.push(node);
  siftUp(heap, node, index);
}
export function peek(heap) {
  const first = heap[0];
  return first === undefined ? null : first;
}
export function pop(heap) {
  const first = heap[0];
  if (first !== undefined) {
    const last = heap.pop();
    if (last !== first) {
      heap[0] = last;
      siftDown(heap, last, 0);
    }
    return first;
  } else {
    return null;
  }
}

function siftUp(heap, node, i) {
  let index = i;
  while (true) {
    const parentIndex = index - 1 >>> 1;
    const parent = heap[parentIndex];
    if (parent !== undefined && compare(parent, node) > 0) {
      heap[parentIndex] = node;
      heap[index] = parent;
      index = parentIndex;
    } else {

      return;
    }
  }
}

function siftDown(heap, node, i) {
  let index = i;
  const length = heap.length;
  while (index < length) {
    const leftIndex = (index + 1) * 2 - 1;
    const left = heap[leftIndex];
    const rightIndex = leftIndex + 1;
    const right = heap[rightIndex]; 
    if (left !== undefined && compare(left, node) < 0) {
      if (right !== undefined && compare(right, left) < 0) {
        heap[index] = right;
        heap[rightIndex] = node;
        index = rightIndex;
      } else {
        heap[index] = left;
        heap[leftIndex] = node;
        index = leftIndex;
      }
    } else if (right !== undefined && compare(right, node) < 0) {
      heap[index] = right;
      heap[rightIndex] = node;
      index = rightIndex;
    } else {
      return;
    }
  }
}

function compare(a, b) {
  const diff = a.sortIndex - b.sortIndex;
  return diff !== 0 ? diff : a.id - b.id;
}
const { push, pop, peek } = require('./SchedulerMinHeap');
let heap = [];
push(heap, { sortIndex: 1 });
push(heap, { sortIndex: 2 });
push(heap, { sortIndex: 3 });
console.log(peek(heap));
push(heap, { sortIndex: 4 });
push(heap, { sortIndex: 5 });
push(heap, { sortIndex: 6 });
push(heap, { sortIndex: 7 });
console.log(peek(heap));
pop(heap);
console.log(peek(heap));

3. 链表 #

3.1 链表分类 #

3.1.1 单向链表 #

3.1.2 双向链表 #

3.1.3 循环链表 #

3.1.4 示例 #

3.1.4.1 ReactFiberLane.js #

ReactFiberLane.js

const NoLanes = 0b00;
const NoLane = 0b00;
const SyncLane = 0b01;
const SyncBatchedLane = 0b10;
/**
 * 判断subset是不是set的子集
 * @param {*} set 
 * @param {*} subset 
 * @returns 
 */
function isSubsetOfLanes(set, subset) {
    return (set & subset) === subset;
}
/**
 * 合并两个车道
 * @param {*} a 
 * @param {*} b 
 * @returns 
 */
function mergeLanes(a, b) {
    return a | b;
}
module.exports = {
    NoLane,
    NoLanes,
    SyncLane,
    SyncBatchedLane,
    isSubsetOfLanes,
    mergeLanes
}
3.1.4.2 ReactUpdateQueue.js #

ReactUpdateQueue.js

const { NoLane, NoLanes, isSubsetOfLanes, mergeLanes } = require('./ReactFiberLane') ;
function initializeUpdateQueue(fiber) { 
    const queue = {
        baseState: fiber.memoizedState,//本次更新前该Fiber节点的state,Update基于该state计算更新后的state
        firstBaseUpdate: null,//本次更新前该Fiber节点已保存的Update链表头
        lastBaseUpdate: null,//本次更新前该Fiber节点已保存的Update链表尾
        shared: {
            //触发更新时,产生的Update会保存在shared.pending中形成单向环状链表
            //当由Update计算state时这个环会被剪开并连接在lastBaseUpdate后面
            pending: null
        }
    }
    fiber.updateQueue = queue;
}
function enqueueUpdate(fiber, update) {
    const updateQueue = fiber.updateQueue;
    if (updateQueue === null) {
        return;
    }
    const sharedQueue = updateQueue.shared;
    const pending = sharedQueue.pending;
    if (pending === null) {
        update.next = update;
    } else {
        update.next = pending.next;
        pending.next = update;
    }
    sharedQueue.pending = update;
}

/**
 * 处理更新队列
 * @param {*} fiber 
 * @param {*} renderLanes 
 */
function processUpdateQueue(fiber, renderLanes) {
    //获取此fiber上的更新队列
    const queue = fiber.updateQueue;
    //获取第一个更新
    let firstBaseUpdate = queue.firstBaseUpdate;
    let lastBaseUpdate = queue.lastBaseUpdate; 
    //判断一下是否在等待生效的的更新,如果有,变成base队列
    let pendingQueue = queue.shared.pending;
    if (pendingQueue !== null) {
        //等待生效的队列是循环队列
        queue.shared.pending = null; 
        //最后一个等待的更新 update4
        const lastPendingUpdate = pendingQueue;
        //第一个等待的更新 update1
        const firstPendingUpdate = lastPendingUpdate.next;
        //把环剪断,最后一个不再指向第一个
        lastPendingUpdate.next = null;
        //把等待生效的队列添加到base队列中
        //如果base队列为空
        if (lastBaseUpdate === null) {
            firstBaseUpdate = firstPendingUpdate;
        } else {//否则就把当前的更新队列添加到base队列的尾部
            lastBaseUpdate.next = firstPendingUpdate;
        }
        //尾部也接上
        lastBaseUpdate = lastPendingUpdate;
    } 
    //开始计算新的状态
    if (firstBaseUpdate !== null) {
        //先获取老的值{number:0}
        let newState = queue.baseState;
        let newLanes = NoLanes;
        let newBaseState = null;//新的基础状态
        let newFirstBaseUpdate = null;//第一个跳过的更新
        let newLastBaseUpdate = null;//新的最后一个基本更新
        let update = firstBaseUpdate;//指向第一个更新
        do {
            //获取更新车道
            const updateLane = update.lane;
            //如果优先级不够,跳过这个更新,如果这是第一个跳过的更新,上一个状态和更新成为newBaseState和newFirstBaseUpdate
            if (!isSubsetOfLanes(renderLanes, updateLane)) {
                const clone = {
                    lane: updateLane,
                    payload: update.payload
                };
                if (newLastBaseUpdate === null) {
                    newFirstBaseUpdate = newLastBaseUpdate = clone;// first=last=update1
                    newBaseState = newState;//0
                } else {
                    newLastBaseUpdate = newLastBaseUpdate.next = clone;
                }
                //更新队列中的剩下的优先级
                newLanes = mergeLanes(newLanes, updateLane);
            } else {
                //如果有足够的优先级 如果有曾经跳过的更新,仍然追加在后面
                if (newLastBaseUpdate !== null) {
                    const clone = {
                        //NoLane是所有的优先级的子集,永远不会被跳过
                        lane: NoLane,
                        payload: update.payload
                    };
                    newLastBaseUpdate = newLastBaseUpdate.next = clone;
                }
                newState = getStateFromUpdate(update, newState);
            }
            update = update.next;
            if (!update) {
                break;
            }
        } while (true);

        if (!newLastBaseUpdate) {
            newBaseState = newState;
        }
        queue.baseState = newBaseState;
        queue.firstBaseUpdate = newFirstBaseUpdate;
        queue.lastBaseUpdate = newLastBaseUpdate;
        fiber.lanes = newLanes;
        fiber.memoizedState = newState;
    }
}

function getStateFromUpdate(update, prevState) {
    const payload = update.payload;
    let partialState = payload(prevState);
    return Object.assign({}, prevState, partialState);
}
module.exports = {
    initializeUpdateQueue,
    enqueueUpdate,
    processUpdateQueue
}
3.1.4.3 use.js #

use.js


4. 树的遍历 #

4.1 深度优先(DFS) #

function dfs(node) {
    console.log(node.name);
    node.children&&node.children.forEach(child => {
        dfs(child);
    });
}
let root = {
    name: 'A',
    children: [
        {
            name: 'B',
            children: [
                { name: 'B1' },
                { name: 'B2' }
            ]
        },
        {
            name: 'C',
            children: [
                { name: 'C1' },
                { name: 'C2' }
            ]
        }
    ]
}
dfs(root);

4.2 广度优先(BFS) #

function bfs(node) {
    const stack = [];
    stack.push(node);
    let current;
    while (current = stack.shift()) {
        console.log(current.name);
        current.children && current.children.forEach(child => {
            stack.push(child);
        });
    }
}
let root = {
    name: 'A',
    children: [
        {
            name: 'B',
            children: [
                { name: 'B1' },
                { name: 'B2' }
            ]
        },
        {
            name: 'C',
            children: [
                { name: 'C1' },
                { name: 'C2' }
            ]
        }
    ]
}
bfs(root);

5. 栈 #

5.1 栈代码 #

class Stack {
    constructor() {
        this.data = [];
        this.top = 0;
    }
    push(node) {
        this.data[this.top++] = node;
    }
    pop() {
        return this.data[--this.top];
    }
    peek() {
        return this.data[this.top - 1];
    }
    size() {
        return this.top;
    }
    clear() {
        this.top = 0;
    }
}

const stack = new Stack();
stack.push('1');
stack.push('2');
stack.push('3');
console.log('stack.size()', stack.size());
console.log('stack.peek', stack.peek());
console.log('stack.pop()', stack.pop());
console.log('stack.peek()', stack.peek());
stack.push('4');
console.log('stack.peek', stack.peek());
stack.clear();
console.log('stack.size', stack.size());
stack.push('5');
console.log('stack.peek', stack.peek());

5.2 应用场景 #

5.2.1 App.js #

import React from "react";
const NumberContext = React.createContext(0);
export default function App() {
    return (
        <NumberContext.Provider value={'A'}>
            <NumberContext.Consumer>
                {(v1) => (
                    <NumberContext.Provider value={'B'}>
                        <NumberContext.Consumer>
                            {(v2) => (
                                <NumberContext.Provider value={'C'}>
                                    <NumberContext.Consumer>
                                        {(v3) => (
                                            <div>
                                                {v1} {v2} {v3}
                                            </div>
                                        )}
                                    </NumberContext.Consumer>
                                </NumberContext.Provider>
                            )}
                        </NumberContext.Consumer>
                    </NumberContext.Provider>
                )}
            </NumberContext.Consumer>
        </NumberContext.Provider>
    );
}

5.2.2 ReactFiberStack.js #

src\react\packages\react-reconciler\src\ReactFiberStack.js

const valueStack = [];
let index = -1;
function createCursor(defaultValue) {
    return {current: defaultValue};
}

function isEmpty() {
    return index === -1;
}

function pop(cursor) {
    if (index < 0) {
        return;
    }
    cursor.current = valueStack[index];
    valueStack[index] = null;
    index--;
}

function push(cursor, value) {
    index++;
    valueStack[index] = cursor.current;
    cursor.current = value;
}

module.exports =  {
    createCursor, isEmpty, pop, push
};

5.2.3 ReactFiberNewContext.js #

src\react\packages\react-reconciler\src\ReactFiberNewContext.js

function pushProvider(providerFiber, nextValue) {
    const context = providerFiber.type._context;
    push(valueCursor, context._currentValue, providerFiber);
    context._currentValue = nextValue;
}
function popProvider(providerFiber) {
    const currentValue = valueCursor.current;
    pop(valueCursor, providerFiber);
    const context = providerFiber.type._context;
    context._currentValue = currentValue;
}
module.exports =  {
    pushProvider, popProvider
};

5.2.4 use.js #

const { createCursor, pop, push } = require('./ReactFiberStack.js');
const { pushProvider, popProvider } = require('./ReactFiberNewContext.js');
let valueCursor = createCursor();
let providerFiber = { type: { _context: {} } };
pushProvider(providerFiber, 'A');
console.log(providerFiber.type._context._currentValue);
pushProvider(providerFiber, 'B');
console.log(providerFiber.type._context._currentValue);
pushProvider(providerFiber, 'C');
console.log(providerFiber.type._context._currentValue);
popProvider(providerFiber);
console.log(providerFiber.type._context._currentValue);
popProvider(providerFiber);
console.log(providerFiber.type._context._currentValue);
popProvider(providerFiber);

6.二进制 #

6.1 真值 #

+ 00000001 # +1
- 00000001 # -1

6.2 原码 #

0 0000001 # +1
1 0000001 # -1

6.3 反码 #

0 0000001 # +1
1 1111110 # -1

6.4 补码 #

0 0000001 # +1
1 1111111 # -1

6.5 二进制数整数 #

6.6 ~非 #

0b00000011
3
~0b00000011 =>  0b11111100
-4
(~0b00000011).toString();
'-4'
(~0b00000011).toString(2);
'-100'

求补码的真值
1 表示负号
剩下的 1111100 开始转换
11111001
1111011 取反
0000100 4

6.7 getHighestPriorityLane #

/**
 * 分离出所有比特位中最右边的1
 * 分离出最高优先级的车道
 * @param {*} lanes 车道
 * @returns 车道
 */
function getHighestPriorityLane(lanes) {
    return lanes & -lanes;
}

lanes=0b00001100=12
-lanes=-12
1
0001100
1110011
1110100
11110100
00001100

6.8 左移 #

(0b00000010<<1).toString(2)

6.9 >> 有符号右移 #

(-0b111>>1).toString(2) "-100"
-0b111 -7
100000111 原码
111111000 反码
111111001 补码
111111100

1
111111100
111111011
000000100
1000000100
-100
-4

6.10 >>>无符号右移 #

(0b111>>>1).toString(2)
>>> "11"
(-0b111>>>1).toString(2)
>>> "1111111111111111111111111111100"

00000000000000000000000000000111
11111111111111111111111111111000
11111111111111111111111111111001
01111111111111111111111111111100
2147483644

PHP网站源码贵港SEO按效果付费价格衡阳网站优化软件多少钱湘西网站优化推广多少钱兰州网站开发武威建设网站宿迁百姓网标王公司坪地高端网站设计多少钱垦利百姓网标王公司青岛外贸网站制作多少钱宁波网站设计模板报价保定网页制作公司固原设计网站价格乌海网站推广系统多少钱昭通网站制作设计多少钱许昌外贸网站设计价格东营网站关键词优化推荐襄樊seo网站优化多少钱潍坊设计公司网站推荐丹东阿里店铺托管多少钱吴忠关键词排名醴陵SEO按天扣费多少钱山南网站优化软件多少钱荆州SEO按天计费公司延安营销网站阜阳推广网站价格保山外贸网站设计公司漯河网站建设设计哪家好临夏企业网站改版公司承德网站设计推荐南联网站制作设计歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

PHP网站源码 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化