├── FE ├── README.md ├── snakeBorder.html ├── 网络协议.md └── 重绘与回流.md ├── README.md ├── assets ├── README.md └── img │ ├── browerRender.png │ ├── css │ ├── cssvar1.png │ ├── cssvar2.png │ ├── cssvar3.png │ └── cssvar4.png │ ├── event.png │ ├── js.jpg │ ├── prototype.jpg │ ├── react.jpg │ ├── reactLifecycle.png │ ├── react_sc │ ├── FiberEl.png │ ├── FiberTree.jpg │ ├── createEl_babel.png │ └── fiber-scheduler.png │ ├── redux.jpg │ ├── task.jpg │ ├── webpack │ └── cdn.png │ └── xieyi.jpg ├── books ├── 你不知道的JavaScript(上卷).pdf ├── 你不知道的JavaScript(下卷).pdf └── 你不知道的JavaScript(中卷).pdf ├── css └── less-media.md ├── git ├── README.md └── mac配置多个ssh.md ├── js ├── Observer.md ├── README.md ├── call,apply与bind.md ├── eval和with欺骗词法作用域影响性能.md ├── new运算符.md ├── 宏任务与微任务.md ├── 强大的Array.reduce.md ├── 排序算法.md └── 构造函数和原型.md ├── js常用小技巧.md ├── node ├── npm.md └── package.md ├── react ├── 01.react-basic.md ├── 02.react-advance.md ├── 03.Hook.md ├── 04.redux.md ├── 05.redux-saga.md ├── 06.React源码学习-createElment.md ├── 07.React源码学习-Component.md ├── 08.React源码学习-FiberRoot与Fiber.md ├── 09.React源码学习-update.md ├── 10.React源码学习-expirationTime.md ├── 11.React源码学习-任务调度.md ├── 12.React源码学习-beginWork.md ├── 13.React源码学习-commit.md ├── 14.umi2+Antd实现动态主题色切换实践.md └── README.md └── webpack ├── HtmlWebpackPlugin.md └── webpack4.md /FE/README.md: -------------------------------------------------------------------------------- 1 | ### 记录前端知识点 2 | -------------------------------------------------------------------------------- /FE/snakeBorder.html: -------------------------------------------------------------------------------- 1 | 49 |
-------------------------------------------------------------------------------- /FE/网络协议.md: -------------------------------------------------------------------------------- 1 | ## 网络协议 2 | 3 | ### OSI与TCP/IP协议模型 4 | 5 |  -------------------------------------------------------------------------------- /FE/重绘与回流.md: -------------------------------------------------------------------------------- 1 | ### 重绘 2 | 3 | 当节点需要更改外观而不会影响布局的,比如改变 color 就叫称为重绘 4 | 5 | ### 回流 6 | 7 | 将可见DOM节点以及它对应的样式结合起来,可是我们还需要计算它们在设备视口(viewport)内的确切位置和大小,这个计算的阶段就是回流。 8 | 9 | *发生回流的几种情况:* 10 | 11 | - 添加或删除可见的DOM元素 12 | - 元素的位置发生变化 13 | - 元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等) 14 | - 内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代。 15 | - 页面一开始渲染的时候(这肯定避免不了) 16 | - 浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的) 17 | 18 | ##### 回流一定会触发重绘,而重绘不一定会回流 19 | 20 | 这是由于浏览器的渲染过程决定的,其过程如下: 21 | 22 | - 解析HTML,生成DOM树,解析CSS,生成CSSOM树 23 | - 将DOM树和CSSOM树结合,生成渲染树(Render Tree) 24 | - Layout(回流):根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小) 25 | - Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素 26 | - Display:将像素发送给GPU,展示在页面上。 27 | 28 |  29 | 30 | ### 如何减少重绘和回流 31 | 32 | 减少回流和重绘其实就是需要减少对render tree的操作(合并多次多DOM和样式的修改),并减少对一些样式信息的请求,尽量利用好浏览器的优化策略。 33 | 34 | - 改变样式通过添加class或el.style.cssText,而不是el.style.单个属性 35 | - 尽可能少的修改dom,对于需要频繁操作的dom可以让其暂避重绘检查: 36 | - 使用DocumentFragment进行缓存操作,引发一次回流和重绘 37 | - 使用display:none暂时隐藏当前处理的dom 38 | - 使用cloneNode(true or false) 和 replaceChild 39 | - 对于需要动画的元素使用定位使其脱离文档流 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 目录 2 | 3 | > 持续更新中,不建议直接fork,欢迎star 👍 4 | 5 | ### ***JS*** 6 | - [js常用小技巧( 推荐:★★★★★ )](/js常用小技巧.md) 7 | - [宏任务与微任务](/js/宏任务与微任务.md) 8 | - [call,apply与bind](/js/call,apply与bind.md) 9 | - [new运算符详解](/js/new运算符.md) 10 | - [es5构造函数和原型](/js/构造函数和原型.md) 11 | - [eval和with欺骗词法作用域影响性能](/js/eval和with欺骗词法作用域影响性能.md) 12 | - [排序算法](/js/排序算法.md) 13 | - [强大的Array.reduce](/js/强大的Array.reduce.md) 14 | - [Observer API(监听resize和无限滚动的新方案)](/js/Observer.md) 15 | 16 | ### node 17 | - [常用 npm 包推荐](/node/npm.md) 18 | - [package.json 笔记](/node/package.md) 19 | 20 | ### ***React*** 21 | - [从0开始使用webpack构建一个React脚手架](https://github.com/TigerHee/react-cli-diy) 22 | - [01.react-基础](/react/01.react-basic.md) 23 | - [02.react-进阶](/react/02.react-advance.md) 24 | - [03.Hook](/react/03.Hook.md) 25 | - [04.redux](/react/04.redux.md) 26 | - [05.redux-saga](/react/05.redux-saga.md) 27 | - [06.React源码学习-createElment](/react/06.React源码学习-createElment.md) 28 | - [07.React源码学习-Component](/react/07.React源码学习-Component.md) 29 | - [08.React源码学习-FiberRoot与Fiber](/react/08.React源码学习-FiberRoot与Fiber.md) 30 | - [09.React源码学习-update](/react/09.React源码学习-update.md) 31 | - [10.React源码学习-expirationTime](/react/10.React源码学习-expirationTime.md) 32 | - [11.React源码学习-任务调度](/react/11.React源码学习-任务调度.md) 33 | - [12.React源码学习-beginWork](/react/12.React源码学习-beginWork.md) 34 | - [13.React源码学习-commit](/react/13.React源码学习-commit.md) 35 | - [14.umi2+Antd实现动态主题色切换实践](/react/14.umi2+Antd实现动态主题色切换实践.md) 36 | 37 | ### ***FE*** 38 | - [重绘与回流](/FE/重绘与回流.md) 39 | - [蛇形边框](/FE/snakeBorder.html) 40 | 41 | ### ***书籍*** 42 | - [你不知道的JavaScript(上卷)](/books/你不知道的JavaScript(上卷).pdf) 43 | - [你不知道的JavaScript(中卷)](/books/你不知道的JavaScript(中卷).pdf) 44 | - [你不知道的JavaScript(下卷)](/books/你不知道的JavaScript(下卷).pdf) 45 | 46 | ### ***webpack*** 47 | - [从0到掌握webpack4](/webpack/webpack4.md) 48 | - [使用HtmlWebpackPlugin向html内插入第三方cdn资源](/webpack/HtmlWebpackPlugin.md) 49 | 50 | ### ***git*** 51 | - [git常用指令](/git/README.md) 52 | - [mac配置多个ssh key](/git/mac配置多个ssh.md) 53 | 54 | ### ***CSS*** 55 | - [less函数实现媒体查询](/css/less-media.md) 56 | -------------------------------------------------------------------------------- /assets/README.md: -------------------------------------------------------------------------------- 1 | ### 此项目所需的静态资源存放目录 -------------------------------------------------------------------------------- /assets/img/browerRender.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/browerRender.png -------------------------------------------------------------------------------- /assets/img/css/cssvar1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/css/cssvar1.png -------------------------------------------------------------------------------- /assets/img/css/cssvar2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/css/cssvar2.png -------------------------------------------------------------------------------- /assets/img/css/cssvar3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/css/cssvar3.png -------------------------------------------------------------------------------- /assets/img/css/cssvar4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/css/cssvar4.png -------------------------------------------------------------------------------- /assets/img/event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/event.png -------------------------------------------------------------------------------- /assets/img/js.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/js.jpg -------------------------------------------------------------------------------- /assets/img/prototype.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/prototype.jpg -------------------------------------------------------------------------------- /assets/img/react.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/react.jpg -------------------------------------------------------------------------------- /assets/img/reactLifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/reactLifecycle.png -------------------------------------------------------------------------------- /assets/img/react_sc/FiberEl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/react_sc/FiberEl.png -------------------------------------------------------------------------------- /assets/img/react_sc/FiberTree.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/react_sc/FiberTree.jpg -------------------------------------------------------------------------------- /assets/img/react_sc/createEl_babel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/react_sc/createEl_babel.png -------------------------------------------------------------------------------- /assets/img/react_sc/fiber-scheduler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/react_sc/fiber-scheduler.png -------------------------------------------------------------------------------- /assets/img/redux.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/redux.jpg -------------------------------------------------------------------------------- /assets/img/task.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/task.jpg -------------------------------------------------------------------------------- /assets/img/webpack/cdn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/webpack/cdn.png -------------------------------------------------------------------------------- /assets/img/xieyi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/assets/img/xieyi.jpg -------------------------------------------------------------------------------- /books/你不知道的JavaScript(上卷).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/books/你不知道的JavaScript(上卷).pdf -------------------------------------------------------------------------------- /books/你不知道的JavaScript(下卷).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/books/你不知道的JavaScript(下卷).pdf -------------------------------------------------------------------------------- /books/你不知道的JavaScript(中卷).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TigerHee/shareJS/18d2906d6e26b9db47ff3382e691d3c96fceb7c1/books/你不知道的JavaScript(中卷).pdf -------------------------------------------------------------------------------- /css/less-media.md: -------------------------------------------------------------------------------- 1 | ## less函数实现媒体查询 2 | 3 | - 公用的less函数文件 4 | 5 | 如:mix.less 6 | 7 | ```less 8 | @mq-width-md:768px; 9 | @mq-width-lg:1024px; 10 | 11 | // < 768px 12 | .mediaQuerySm(@style) { 13 | @media screen and (max-width:@mq-width-md) { 14 | @style() 15 | } 16 | } 17 | 18 | // < 1024px 19 | .mediaQueryMd(@style) { 20 | @media screen and (max-width:@mq-width-lg) { 21 | @style() 22 | } 23 | } 24 | ``` 25 | 26 | - 实际组件引入并使用函数 27 | 28 | ```less 29 | @import '~xxx/mix.less'; // 路径自定 30 | 31 | .cls { 32 | padding: 20px; 33 | .mediaQueryMd({ 34 | padding: 12px; 35 | }); 36 | .mediaQuerySm({ 37 | padding: 8px; 38 | }); 39 | } 40 | ``` -------------------------------------------------------------------------------- /git/README.md: -------------------------------------------------------------------------------- 1 | ### 获取本地SSH Key: 2 | ```sh 3 | ls ~/.ssh 4 | 5 | cat ~/.ssh/id_rsa.pub 6 | ``` 7 | 8 | ### 在远程仓库的master分支基础上建立新分支: 9 | ``` 10 | git checkout master -b dev 11 | 12 | git push origin dev 13 | ``` -------------------------------------------------------------------------------- /git/mac配置多个ssh.md: -------------------------------------------------------------------------------- 1 | ## mac配置多个ssh key 2 | 3 | 1. 进入ssh目录: 4 | ``` 5 | cd ~/.ssh 6 | ``` 7 | 8 | 2. 创建新的ssh key: 9 | ``` 10 | ssh-keygen -t rsa -C "tigerhee@qq.com" 11 | ``` 12 | 13 | 后续提示内输入name: id_rsa_tiger 14 | 15 | 3. 创建config文件: 16 | ``` 17 | touch config 18 | ``` 19 | 20 | 配置config: 21 | 22 | ``` 23 | # github 24 | Host git 25 | HostName github.com 26 | PreferredAuthentications publickey 27 | IdentityFile ~/.ssh/id_rsa 28 | 29 | # github tiger 30 | Host git2 31 | HostName github.com 32 | PreferredAuthentications publickey 33 | User tigerhee@qq.com 34 | IdentityFile ~/.ssh/id_rsa_tiger 35 | ``` 36 | 4. 添加密钥: 37 | ``` 38 | ssh-add ~/.ssh/id_rsa_tiger 39 | ``` 40 | 41 | 5. 到要用git2的仓库修改其git配置: 42 | 43 | ``` 44 | git config user.email "tigerhee@qq.com" 45 | git config user.name "tigerHee" 46 | ``` -------------------------------------------------------------------------------- /js/Observer.md: -------------------------------------------------------------------------------- 1 | ## Observer API 2 | 3 | > 友情提示:兼容性还不是很友好 4 | 5 | ### 1. ResizeObserver 6 | 7 | ResizeObserver 接口可以监听到 Element 的内容区域或 SVGElement的边界框改变。内容区域则需要减去内边距padding。 8 | 9 | - #### 构造器: 10 | 11 | - `ResizeObserver()` 12 | 13 | 创建并返回一个ResizeObserver对象。 14 | 15 | - #### 方法: 16 | 17 | - `ResizeObserver.observe()` 18 | 19 | 开始观察指定的 Element或 SVGElement。 20 | 21 | - `ResizeObserver.disconnect()` 22 | 23 | 取消和结束目标对象上所有对 Element或 SVGElement 观察。 24 | 25 | - `ResizeObserver.unobserve()` 26 | 27 | 结束观察指定的Element或 SVGElement。 28 | 29 | - #### 示例: 30 | 31 | 监听body的size变化: 32 | 33 | ```js 34 | const resizeObserver = new ResizeObserver(entries => { 35 | for (let entry of entries) { 36 | console.log(entry) 37 | } 38 | }); 39 | resizeObserver.observe(document.querySelector('body')); 40 | ``` 41 | 42 | ### 2. IntersectionObserver 43 | 44 | Intersection Observer API提供了一种异步观察目标元素与祖先元素或顶级文档viewport的交集中的变化的方法。 45 | 46 | - 可能使用到的场景: 47 | - 当页面滚动时,懒加载图片或其他内容 48 | - 实现“可无限滚动”网站,也就是当用户滚动网页时直接加载更多内容,无需翻页 49 | - 根据用户是否已滚动到相应区域来灵活开始执行任务或动画 50 | 51 | Intersection Observer API 允许你配置一个回调函数,每当目标(target)元素与设备视窗或者其他指定元素发生交集的时候执行。设备视窗或者其他元素我们称它为根元素或根(root)。通常,您需要关注文档最接近的可滚动祖先元素的交集更改,如果元素不是可滚动元素的后代,则默认为设备视窗。如果要观察相对于根(root)元素的交集,请指定根(root)元素为null。 52 | 53 | 目标(target)元素与根(root)元素之间的交叉度是交叉比(intersection ratio)。这是目标(target)元素相对于根(root)的交集百分比的表示,它的取值在0.0和1.0之间。 54 | 55 | - #### 构造器: 56 | 57 | - `IntersectionObserver(callback, options)` 58 | 59 | ##### `callback`接收参数: 60 | 61 | - IntersectionObserverEntry对象 62 | 63 | - 观察者的列表 64 | 65 | ##### `options`对象属性: 66 | 67 | - root: 68 | 69 | 指定根(root)元素,用于检查目标的可见性。必须是目标元素的父级元素。如果未指定或者为null,则默认为浏览器视窗。 70 | 71 | - rootMargin: 72 | 73 | root元素的外边距。该属性值是用作root元素和target发生交集时候的计算交集的区域范围,使用该属性可以控制root元素每一边的收缩或者扩张。默认值为0。 74 | 75 | - threshold: 76 | 77 | 可以是单一的number (eg: 0.5) 或是number数组 (eg: [0, 0.25, 0.5, 0.75, 1]),target元素和root元素相交程度达到该值的时候IntersectionObserver注册的回调函数将会被执行。 78 | 79 | ##### `IntersectionObserverEntry`对象属性: 80 | 81 | - time: 82 | 83 | 可见性发生变化的时间,是一个高精度时间戳 84 | 85 | - target: 86 | 87 | 被观察的目标元素,是一个 DOM 节点对象 88 | 89 | - rootBounds: 90 | 91 | 根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null 92 | 93 | - boundingClientRect: 94 | 95 | 目标元素的矩形区域的信息 96 | 97 | - intersectionRect: 98 | 99 | 目标元素与视口(或根元素)的交叉区域的信息 100 | 101 | - intersectionRatio: 102 | 103 | 目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0 104 | 105 | - #### 示例: 106 | 107 | - 无限滚动: 108 | 109 | 在无限滚动的底部放一个footer,监听footer的可见否来实现无限滚动 110 | 111 | ```js 112 | let Observer = new IntersectionObserver((entries) => { 113 | // 如果footer不可见,就返回 114 | if (entries[0].intersectionRatio <= 0) return; 115 | // 加载更多 116 | loadMore(); 117 | }); 118 | 119 | // 开始观察 120 | Observer.observe( 121 | document.querySelector('.scrollerFooter') 122 | ); 123 | ``` -------------------------------------------------------------------------------- /js/README.md: -------------------------------------------------------------------------------- 1 | ### 记录JS的知识点 -------------------------------------------------------------------------------- /js/call,apply与bind.md: -------------------------------------------------------------------------------- 1 | ## call, apply 与 bind 2 | 3 | #### 1.call() 与 apply() 4 | 5 | call或apply会自动执行对应的函数 6 | 7 | ```js 8 | fun.call(thisNew[, arg1[, arg2[, ...]]]) 9 | ``` 10 | 11 | ```js 12 | fun.apply(thisNew[, argsArray]) 13 | ``` 14 | 15 | thisNew: fun函数运行时指定的this值,可能的值为: 16 | 17 | - 不传,或者传null,undefined, this指向window对象 18 | - 传递另一个函数的函数名fun2,this指向函数fun2的引用 19 | - 值为原始值(数字,字符串,布尔值),this会指向该原始值的自动包装对象,如 String、Number、Boolean 20 | - 传递一个对象,函数中的this指向这个对象 21 | 22 | 用例: 23 | 24 | call: 25 | 26 | ```js 27 | window.name = 'windowName' 28 | var obj = { 29 | name: 'objName' 30 | } 31 | function getName(p1, p2) { 32 | console.log('name === ', this.name) 33 | console.log('p1 === ', p1) 34 | console.log('p2 === ', p2) 35 | } 36 | getName('str1', 'str2') 37 | getName.call(obj, 'str1', 'str2') 38 | ``` 39 | 40 | apply: 41 | 42 | ```js 43 | Math.max.apply(null, [2, 3, 1, 4]) 44 | ``` 45 | 46 | #### 2.bind() 47 | 48 | bind()方法会创建一个新函数,称为绑定函数。bind是ES5新增的一个方法,不会执行对应的函数,而是返回对绑定函数的引用。 49 | 50 | ```js 51 | fun.bind(thisNew[, arg1[, arg2[, ...]]]); 52 | ``` 53 | 54 | 用例: 55 | 56 | ```js 57 | var $ = document.querySelectorAll.bind(document) 58 | ``` 59 | 60 | #### 3.三者异同 61 | 62 | 相同: 63 | 64 | - 改变函数体内 this 的指向 65 | 66 | 不同: 67 | 68 | - call、apply的区别:接受参数的方式不一样 69 | 70 | - bind不立即执行。而apply、call 立即执行 71 | 72 | #### 4.模拟实现 73 | 74 | call: 75 | 76 | ```js 77 | Function.prototype.customCall = function () { 78 | if (typeof this !== 'function') { 79 | throw new TypeError('error!') 80 | } 81 | let context = arguments[0] || window 82 | context.fn = this 83 | let args = [...arguments].slice(1) 84 | let result = context.fn(...args) 85 | delete context.fn 86 | return result 87 | } 88 | ``` 89 | 90 | apply: 91 | 92 | ```js 93 | Function.prototype.customApply = function () { 94 | if (typeof this !== 'function') { 95 | throw new TypeError('error!') 96 | } 97 | let context = arguments[0] || window 98 | context.fn = this 99 | let result = !!arguments[1] ? context.fn(...arguments[1]) : context.fn() 100 | delete context.fn 101 | return result 102 | } 103 | ``` 104 | 105 | bind: 106 | 107 | ```js 108 | Function.prototype.customBind = function () { 109 | if (typeof this !== 'function') { 110 | throw new TypeError('error!') 111 | } 112 | const that = this 113 | let context = arguments[0] || window 114 | const args = [...arguments].slice(1) 115 | return function() { 116 | return that.apply(context, args.concat([...arguments])) 117 | } 118 | } 119 | ``` 120 | -------------------------------------------------------------------------------- /js/eval和with欺骗词法作用域影响性能.md: -------------------------------------------------------------------------------- 1 | ## 欺骗词法作用域影响性能 2 | 3 | 词法作用域就是定义在词法阶段的作用域。换句话说,词法作用域是由你在写 代码时将变量和块作用域写在哪里来决定的,因此当词法分析器处理代码时会保持作用域 不变(大部分情况下是这样的) 4 | 5 | #### JS代码执行过程的重要成员: 6 | 7 | - 引擎: 8 | 9 | 从头到尾负责整个js程序的编译及执行过程 10 | 11 | - 编译器: 12 | 13 | 引擎的好朋友之一,负责语法分析及代码生成等 14 | 15 | - 作用域: 16 | 17 | 引擎的另一好朋友,负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当期执行的代码对这些标识符的访问权限 18 | 19 | #### 对变量的查询分类: 20 | 21 | - LHS查询: 22 | 23 | 查找的目的是对变量进行赋值 24 | 25 | - RHS查询: 26 | 27 | 查找的目的是获取变量的值 28 | 29 | js引擎首先会在代码执行前对其进行编译,在这个过程中,像var a=2这样的声明会被分解成两个独立的步骤: 30 | 31 | 1.首先,var a在其作用域中声明变量,这会在最开始的阶段,也就是代码执行前进行; 32 | 33 | 2.接下来,a=2会查询(LHS查询)变量a并对其进行赋值; 34 | 35 | #### 欺骗词法作用域会导致性能下降: 36 | 37 | eval和with会在运行时修改或创建新的作用域,以此来欺骗其他在书写时定义的词法作用域。 38 | 39 | js引擎会在编译阶段进行数项的性能优化,其中有些优化项依赖于能够根据代码的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到标识符。 40 | 但如果引擎在代码中发现了eval和with,它只能简单地假设关于标识符位置的判断都是无效的,因为无法在词法分析阶段明确的知道eval会接收到什么代码,这些代码会如何对作用域进行修改,也无法知道传递给with用来创建新词法作用域的对象内容到底是什么, 41 | 42 | 最悲观的情况是如果出现了 eval(..) 或 with,所有的优化可能都是无意义的,因此最简 单的做法就是完全不做任何优化。 43 | 44 | 如果代码中大量使用 eval(..) 或 with,那么运行起来一定会变得非常慢。无论引擎多聪 明,试图将这些悲观情况的副作用限制在最小范围内,也无法避免如果没有这些优化,代 码会运行得更慢这个事实。 -------------------------------------------------------------------------------- /js/new运算符.md: -------------------------------------------------------------------------------- 1 | #### new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。 2 | 3 | --- 4 | new进行了如下操作: 5 | - 创建一个新对象obj 6 | - 把obj的__proto__指向构造函数的prototype对象 实现继承 7 | - 将步骤1新创建的对象obj作为this的上下文 8 | - 返回创建的对象obj(如果该函数没有返回对象,则返回this) 9 | --- 10 | 11 | ##### *自己实现一个new:* 12 | 13 | ```js 14 | function _new(...args) { 15 | const [constructor, ...otherArgs] = args; 16 | 17 | if(typeof constructor !== 'function') { 18 | throw new TypeError('constructor is not a function'); 19 | }; 20 | 21 | // 1~2 步骤简单写法 const obj = Object.create(constructor.prototype); 22 | 23 | // 1.创建一个空的简单JavaScript对象(即{}); 24 | const obj = {}; 25 | 26 | // 2.链接该对象(即设置该对象的构造函数)到另一个对象 ; 27 | Object.setPrototypeOf(obj, constructor.prototype) 28 | 29 | // 3.将步骤1新创建的对象作为this的上下文 30 | const result = constructor.apply(obj, otherArgs); 31 | 32 | // 4.如果该函数没有返回对象,则返回this。 33 | return isPrimitive(result) ? obj : result 34 | } 35 | 36 | function isPrimitive(value) { 37 | return value == null || ['string', 'number', 'boolean', 'symbol'].includes(typeof(value)) 38 | } 39 | 40 | function Test(x, y) { 41 | this.x = x; 42 | this.y = y; 43 | } 44 | 45 | var testObj = _new(Test, 1, 2) 46 | ``` 47 | -------------------------------------------------------------------------------- /js/宏任务与微任务.md: -------------------------------------------------------------------------------- 1 | ### 事件循环 2 | 3 | JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。为了协调事件、用户交互、脚本、UI 渲染和网络处理等行为,防止主线程的不阻塞,Event Loop 的方案应用而生。Event Loop 包含两类:一类是基于 [Browsing Context][1],一种是基于 [Worker][2]。二者的运行是独立的,也就是说,每一个 JavaScript 运行的"线程环境"都有一个独立的 Event Loop,每一个 Web Worker 也有一个独立的 Event Loop。 4 | 5 | > 本文所涉及到的事件循环是基于 Browsing Context。 6 | 7 | ### 任务队列 8 | 9 | 根据规范,事件循环是通过任务队列的机制来进行协调的。一个 Event Loop 中,可以有一个或者多个任务队列(task queue),一个任务队列便是一系列有序任务(task)的集合;每个任务都有一个任务源(task source),源自同一个任务源的 task 必须放到同一个任务队列,从不同源来的则被添加到不同队列。setTimeout/Promise 等API便是任务源,而进入任务队列的是他们指定的具体执行任务。 10 | 11 | 在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下: 12 | 13 | - 在此次 tick 中选择最先进入队列的任务(oldest task),如果有则执行(一次) 14 | - 检查是否存在 Microtasks,如果存在则不停地执行,直至清空 Microtasks Queue 15 | - 更新 render 16 | - 主线程重复执行上述步骤 17 | 18 | 在上诉tick的基础上需要了解几点: 19 | 20 | - JS分为同步任务和异步任务 21 | - 同步任务都在主线程上执行,形成一个执行栈 22 | - 主线程之外,事件触发线程管理着一个任务队列,只要异步任务有了运行结果,就在任务队列之中放置一个事件。 23 | - 一旦执行栈中的所有同步任务执行完毕(此时JS引擎空闲),系统就会读取任务队列,将可运行的异步任务添加到可执行栈中,开始执行。 24 | 25 |  26 | 27 | ### 宏任务 28 | 29 | (macro)task,可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)。 30 | 31 | 浏览器为了能够使得JS内部(macro)task与DOM任务能够有序的执行,会在一个(macro)task执行结束后,在下一个(macro)task 执行开始前,对页面进行重新渲染,流程如下: 32 | 33 | ``` 34 | (macro)task->渲染->(macro)task->... 35 | ``` 36 | 37 | ##### 宏任务包含: 38 | ``` 39 | script(整体代码) 40 | setTimeout 41 | setInterval 42 | I/O 43 | UI交互事件 44 | postMessage 45 | MessageChannel 46 | setImmediate(Node.js 环境) 47 | ``` 48 | 49 | ### 微任务 50 | 51 | microtask,可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在当前task任务后,下一个task之前,在渲染之前。 52 | 53 | 所以它的响应速度相比setTimeout(setTimeout是task)会更快,因为无需等渲染。也就是说,在某一个macrotask执行完后,就会将在它执行期间产生的所有microtask都执行完毕(在渲染前)。 54 | 55 | ##### 微任务包含: 56 | ``` 57 | Promise.then 58 | Object.observe 59 | MutaionObserver 60 | process.nextTick(Node.js 环境) 61 | ``` 62 | 63 | ### 运行机制 64 | 65 | 在事件循环中,每进行一次循环操作称为 tick,每一次 tick 的任务处理模型是比较复杂的,但关键步骤如下: 66 | 67 | - 执行一个宏任务(栈中没有就从事件队列中获取) 68 | - 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中 69 | - 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行) 70 | - 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染 71 | - 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取) 72 | 73 | 如图: 74 | 75 |  76 | 77 | [1]: https://html.spec.whatwg.org/multipage/browsers.html#browsing-context 78 | [2]: https://www.w3.org/TR/workers/#worker -------------------------------------------------------------------------------- /js/强大的Array.reduce.md: -------------------------------------------------------------------------------- 1 | ## 强大的 Array.reduce 2 | 3 | 它可以返回任意值,它的功能就是将一个数组的内容聚合成单个值 4 | 5 | #### 语法: 6 | 7 | ```js 8 | arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue]) 9 | ``` 10 | 11 | #### 参数说明: 12 | 13 | - callback - 执行数组中每个值 (如果没有提供 initialValue 则第一个值除外)的函数 14 | - accumulator - 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或 initialValue 15 | - currentValue - 数组中正在处理的元素 16 | - index - 数组中正在处理的当前元素的索引。 如果提供了 initialValue,则起始索引号为 0,否则从索引 1 起始 17 | - array - 调用 reduce()的数组 18 | - initialValue - 作为第一次调用 callback 函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错 19 | 20 | #### 注意: 21 | 22 | 如果数组为空且没有提供 initialValue,会抛出 TypeError 。如果数组仅有一个元素(无论位置如何)并且没有提供 initialValue, 或者有提供 initialValue 但是数组为空,那么此唯一值将被返回并且 callback 不会被执行。 23 | 24 | #### 使用场景: 25 | 26 | ##### 数组求和 27 | 28 | ```js 29 | [ 1, 2, 3 ].reduce(( acc, cur ) => acc + cur, 0) 30 | ``` 31 | 32 | ##### 累加对象数组里的值 33 | 34 | ```js 35 | [{x: 1}, {x:2}, {x:3}].reduce(function (acc, cur) { 36 | return acc + cur.x; 37 | }, 0) 38 | ``` 39 | 40 | ##### 按序执行 Promise 41 | 42 | 在不想用 async await 的时,同样可以处理 promise 回调链的问题 43 | 44 | ```js 45 | function p1(a) { 46 | return new Promise((resolve, reject) => { 47 | resolve(a * 2); 48 | }); 49 | } 50 | function p2(a) { 51 | return new Promise((resolve, reject) => { 52 | resolve(a * 3); 53 | }); 54 | } 55 | function p3(a) { 56 | return new Promise((resolve, reject) => { 57 | resolve(a * 4); 58 | }); 59 | } 60 | let initVal = 1; 61 | [p1, p2, p3].reduce( 62 | (promiseChain, currentFunction) => promiseChain.then(currentFunction), 63 | Promise.resolve(initVal) 64 | ).then(res=>console.log(res)) 65 | ``` 66 | 67 | ##### 二维数组转一维数组 68 | 69 | ```js 70 | [[0, 1], [2, 3], [4, 5]].reduce(( acc, cur ) => acc.concat(cur), []) 71 | ``` 72 | 73 | ##### 统计数组中每个元素出现的次数 74 | 75 | ```js 76 | ['aa', 'bb', 'aa', 'cc', 'aa', 'bb'].reduce((allNames, name) => { 77 | if (name in allNames) { 78 | allNames[name]++; 79 | } 80 | else { 81 | allNames[name] = 1; 82 | } 83 | return allNames; 84 | }, {}) 85 | ``` 86 | 87 | ##### 数组去重 88 | 89 | ```js 90 | [1, 2, 3, 4, 4, 1].reduce((acc, cur) => { 91 | if (acc.includes(cur)) { 92 | return acc 93 | } else { 94 | return [...acc, cur] 95 | } 96 | }, []) 97 | ``` 98 | -------------------------------------------------------------------------------- /js/排序算法.md: -------------------------------------------------------------------------------- 1 | ## 排序算法 2 | 3 | #### 冒泡排序 4 | 5 | ```js 6 | var arr = [1, 5, 9, 3, 2, 6, 8, 4] 7 | var length = arr.length 8 | for (var i = 0; i < length; i++) { 9 | for (var j = i + 1; j < length; j++) { 10 | if (arr[i] > arr[j]) { 11 | ;[arr[i], arr[j]] = [arr[j], arr[i]] 12 | } 13 | } 14 | } 15 | console.log('arr === ', arr) 16 | ``` 17 | 18 | #### 快速排序 19 | 20 | 找到一个基准点,然后将集合分成两部分,左边的小于基准点,右边的大于基准点 21 | 22 | ```js 23 | let testArr = [1, 5, 9, 3, 2, 6, 8, 4] 24 | function sortFn(arr) { 25 | let length = arr.length 26 | if (length <= 1) { 27 | return arr 28 | } 29 | let sortIndex = parseInt(length / 2) 30 | let sortItem = arr.splice(sortIndex, 1)[0] 31 | let leftArr = [] 32 | let rightArr = [] 33 | arr.forEach(item => { 34 | if (item < sortItem) { 35 | leftArr.push(item) 36 | } else { 37 | rightArr.push(item) 38 | } 39 | }) 40 | return [...sortFn(leftArr), ...sortFn([sortItem, ...rightArr])] 41 | } 42 | 43 | console.log('arr === ', sortFn(testArr)) 44 | ``` 45 | 46 | #### 选择排序 47 | 48 | 寻找最小的数,将最小数的索引保存 49 | 50 | ```js 51 | var arr = [1, 5, 9, 3, 2, 6, 8, 4] 52 | var length = arr.length 53 | var minIndex 54 | for (var i = 0; i < length; i++) { 55 | minIndex = i 56 | for (var j = i + 1; j < length; j++) { 57 | if (arr[j] < arr[minIndex]) { 58 | minIndex = j 59 | } 60 | } 61 | ;[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]] 62 | } 63 | console.log('arr === ', arr) 64 | ``` 65 | 66 | #### 插入排序 67 | 68 | 类似摸扑克牌 69 | 70 | ```js 71 | var arr = [1, 5, 9, 3, 2, 6, 8, 4] 72 | var length = arr.length 73 | var preIndex, current 74 | for (var i = 1; i < length; i++) { 75 | preIndex = i - 1 76 | current = arr[i] 77 | while (preIndex >= 0 && arr[preIndex] > current) { 78 | arr[preIndex + 1] = arr[preIndex] 79 | preIndex-- 80 | } 81 | arr[preIndex + 1] = current 82 | } 83 | console.log('arr === ', arr) 84 | ``` 85 | #### 二分插入排序 86 | #### 希尔排序 87 | #### 归并排序 88 | #### 堆排序 89 | -------------------------------------------------------------------------------- /js/构造函数和原型.md: -------------------------------------------------------------------------------- 1 | ## 构造函数和原型 2 | 3 | #### 构造函数 4 | 5 | 构造函数通过原型分配的函数是所有对象所`共享的` 6 | 7 | JS规定,每一个构造函数都有一个 `prototype` 属性,指向另一个对象,注意这个prototype就是一个对象,这个对象的所有属性和方法都会被构造函数所拥有。 8 | 9 | 我们把那些不变的方法直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法。 10 | 11 | - 原型是什么? 12 | 13 | *一个对象,我们也称prototype为原型对象,每个构造函数都有* 14 | 15 | - 原型的作用是什么? 16 | 17 | *共享方法* 18 | 19 | 一般情况下,我们的公共属性定义在构造函数里面,公共的方法放到原型对象上。 20 | 21 | ```js 22 | function Star(name, age) { 23 | this.name = name; 24 | this.age = age; 25 | } 26 | 27 | Star.prototype.sing = function() { 28 | console.log('我会唱歌'); 29 | } 30 | 31 | var ldh = new Star('刘德华', 18); 32 | var zxy = new Star('张学友', 19); 33 | console.log(ldh.sing === zxy.sing); // true 34 | ldh.sing(); 35 | console.log(ldl.__proto__ === Star.prototype); // true 36 | ``` 37 | #### 实例对象 38 | 39 | 构造函数生成的实例对象有一个属性 `__proto__` , 指向其构造函数的原型对象 `prototype` 40 | 41 | 所以实例对象的 `__proto__` 和构造函数的 `prototype` 是等价的。 42 | 43 | 实例对象方法和属性查找规则: 先在对象自己身上找,没有再去构造函数的prototype上及原型链上找。 44 | 45 | #### constructor 46 | 47 | 对象原型(__proto__)和构造函数的原型对象(prototype)里面都有一个属性`constructor`属性, constructor我们称为构造函数,因为它指回构造函数本身。 48 | 49 | constructor主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。 50 | ```js 51 | Star.prototype = { 52 | constructor: Star, 53 | sing: function() { 54 | console.log('唱歌') 55 | }, 56 | dance: funciton() { 57 | console.log('跳舞') 58 | } 59 | } 60 | ``` 61 | 62 | #### 构造函数,原型对象以及实力对象的关系 63 | 64 |  65 | 66 | #### this指向 67 | 68 | 1. 在构造函数中,this指向的是实例对象。 69 | 70 | 2. 原型对象prototype的函数中,this指向实例对象。 71 | 72 | #### 继承 73 | 74 | 借用父构造函数继承属性,利用原型对象继承方法 75 | ```js 76 | function Father(name, age) { 77 | this.name = name; 78 | this.age = age; 79 | } 80 | function Son(name, age){ 81 | Father.call(this, name, age); 82 | } 83 | Father.prototype.money = funciton() { 84 | console.log('money'); 85 | } 86 | Son.prototype = new Father(); 87 | Son.prototype.constructor = Son; 88 | Son.prototype.other = function() { 89 | console.log('other'); 90 | } 91 | var son = new Son('姓名', 18); 92 | console.log(son); 93 | ``` 94 | -------------------------------------------------------------------------------- /js常用小技巧.md: -------------------------------------------------------------------------------- 1 | - 小数取整: 2 | 3 | ```js 4 | 1.234 | 0 5 | ``` 6 | 7 | ```js 8 | ~~1.234 9 | ``` 10 | 11 | ```js 12 | 1.234 >> 0 13 | ``` 14 | 15 | - 妙用隐式转换: 16 | 17 | - 字符串转number: 18 | 19 | ```js 20 | +'123' 21 | ``` 22 | 23 | - new Date转时间戳: 24 | 25 | ```js 26 | +new Date() 27 | ``` 28 | 29 | - 数组/多维数组转为逗号分隔字符串(可用于多维数组转一维): 30 | 31 | ```js 32 | ""+[1, 2 , 3, 3, [2, 3, 4]] 33 | ``` 34 | 35 | - 解构: 36 | 37 | - 交换a,b的值: 38 | 39 | ```js 40 | var a=1; 41 | var b=2; 42 | [a, b] = [b, a]; 43 | console.log(a, b); 44 | ``` 45 | 46 | - 扩展运算符: 47 | 48 | - 取数组最大值/最小值: 49 | 50 | ```js 51 | Math.max(...[1,2,3]) 52 | Math.min(...[1,2,3]) 53 | ``` 54 | 55 | - 生成时间: 56 | 57 | ```js 58 | new Date(...[2018,6,4]) 59 | ``` 60 | 61 | - 字符串转数组: 62 | 63 | ```js 64 | method 1: 65 | [...'string'] 66 | 67 | method 2: 68 | Array.from('string') 69 | ``` 70 | 71 | - 合并对象: 72 | 73 | ```js 74 | let obj1 = {a:1, b:2}; 75 | let obj2 = {b:3, c:4}; 76 | 77 | {...obj1, ...obj2} 78 | 等同于 79 | Object.assign(obj1, obj2) 80 | ``` 81 | 82 | - 利用URL API获取url的query值 83 | 84 | ```js 85 | var url = new URL('http://localhost:8000/news?a=1&b=2&c=3'); 86 | var searchParams = url.searchParams; 87 | for (let key of searchParams.keys()){ 88 | console.log('===='); 89 | console.log('key === ', key); 90 | console.log('value === ', searchParams.get(key)) 91 | } 92 | ``` 93 | 94 | - 常用方法: 95 | 96 | - 数字前补0: 97 | 98 | ```js 99 | function preFixNum(num, length) { 100 | return (Array(length).join('0') + num).slice(-length); 101 | } 102 | ``` 103 | 104 | - 数组元素为对象的去重: 105 | 106 | ```js 107 | [...new Set(arr.map(v => JSON.stringify(v)))].map(v => JSON.parse(v)) 108 | ``` 109 | 110 | - 数组求和: 111 | 112 | ```js 113 | var arr = [1,2,3,4,5]; 114 | 115 | method 1: 116 | var sum = eval(arr.join('+')); 117 | 118 | method 2: 119 | var sum = arr.reduce((prev,cur) => prev + cur); 120 | ``` 121 | 122 | - 金钱格式化(千分): 123 | 124 | ```js 125 | let money = 11111; 126 | 127 | method 1: 128 | money.toLocaleString('en-US'); 129 | 130 | method 2: 131 | Intl.NumberFormat().format(money); 132 | 133 | method 3: 134 | String(money).replace(/\B(?=(\d{3})+(?!\d))/g, ','); 135 | ``` 136 | 137 | - 短路逻辑代替if: 138 | 139 | ```js 140 | isTrue && console.log(1); 141 | ``` 142 | 143 | - RGB to Hex: 144 | 145 | ```js 146 | function RGBtoHEX(rgb){ 147 | return ((1<<24) + (rgb.r<<16) + (rgb.g<<8) + rgb.b).toString(16).substr(1); 148 | } 149 | ``` 150 | 151 | - 延时函数: 152 | 153 | ```js 154 | const delay = ms => new Promise(resolve => setTimeout(resolve, ms)) 155 | ``` 156 | 157 | - 生成指定长度数组: 158 | 159 | ```js 160 | Array.from(new Array(10).keys()); 161 | ``` 162 | 163 | - 快速创建a标签: 164 | 165 | ```js 166 | let a = '超链接'.link('https://github.com/TigerHee/shareJS'); 167 | console.log('a === ', a) 168 | ``` 169 | 170 | - 正则进阶: 171 | 172 | - 捕获括号: 173 | 174 | ```js 175 | 匹配 'tigerHee' 并且记住匹配项 176 | /(tigerHee)/ 177 | ``` 178 | 179 | - 非捕获括号: 180 | 181 | ```js 182 | 匹配 'tigerHee' 但是不记住匹配项 183 | /(?:tigerHee)/ 184 | ``` 185 | 186 | - 先行断言: 187 | 188 | ```js 189 | 匹配'tiger'仅仅当'tiger'后面跟着'Hee' 190 | /tiger(?=Hee)/ 191 | ``` 192 | 193 | - 后行断言: 194 | 195 | ```js 196 | 匹配'Hee'仅仅当'Hee'前面是'tiger' 197 | /(?<=tiger)Hee/ 198 | ``` 199 | 200 | - 正向否定查找: 201 | 202 | ```js 203 | 匹配'tiger'仅仅当'tiger'后面不跟着'java' 204 | /tiger(?!java)/ 205 | ``` 206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /node/npm.md: -------------------------------------------------------------------------------- 1 | ## 常用 npm 包 2 | 3 | - ### `decimal.js` 4 | 5 | > 高精度计算库 6 | 7 | - ### `WOW.js` 8 | 9 | > 页面滚动时元素出现的动画库 10 | 11 | [demo](https://www.delac.io/wow/) 12 | 13 | - ### `object-path` 14 | 15 | > js 可选链式调用之前的替代品,解决 `TypeError: Cannot read property ‘x’ of undefined`的问题 16 | 17 | ##### 用例: 18 | 19 | ```js 20 | import objectPath from "object-path"; 21 | 22 | objectPath.get(obj, ["a.c.b"], "DEFAULT"); 23 | ``` 24 | 25 | - ### `water-wave` 26 | 27 | > 一个创建点击后产生水波纹效果的 React 组件 28 | 29 | - ### `clsx` 30 | 31 | > clsx 是一个小型工具集,用于有条件地从一个对象中构造 className 字符串,此对象的键是类字符串(class strings),而值是布尔值(booleans) 32 | 33 | ##### 用例: 34 | 35 | ```js 36 | // 使用前: 37 | ; 38 | 39 | // 使用后 40 | ; 46 | ``` 47 | 48 | ## package.json 49 | 50 | - ### 锁死依赖包的依赖: 51 | 52 | ```js 53 | { 54 | "dependencies": {}, 55 | "resolutions": { 56 | "包名": "版本号" 57 | } 58 | } 59 | ``` 60 | -------------------------------------------------------------------------------- /node/package.md: -------------------------------------------------------------------------------- 1 | ## package.json 笔记 2 | 3 | #### resolutions 4 | 5 | 锁死依赖包内部依赖的版本 6 | 7 | ```js 8 | // eg: 9 | 10 | "resolutions": { 11 | "@react-dnd/asap": "4.0.0" 12 | }, 13 | ``` -------------------------------------------------------------------------------- /react/01.react-basic.md: -------------------------------------------------------------------------------- 1 | ## react 基础 2 | 3 | ### JSX 4 | 5 | - JSX是一个 JavaScript 的语法扩展,可以很好地描述 UI 应该呈现出它应有交互的本质形式。 6 | - React DOM 在渲染所有输入内容之前,默认会进行转义。它可以确保在你的应用中,永远不会注入那些并非自己明确编写的内容。所有的内容在渲染之前都被转换成了字符串。 7 | - JSX 里的 class 变成了 className 8 | 9 | ###### 深入了解: 10 | 11 | JSX 仅仅只是 React.createElement(component, props, ...children) 函数的语法糖。 12 | 13 | 如下JSX代码: 14 | ``` 15 |You clicked {count} times
115 | // 更新 State: 可以通过调用 setCount 来更新当前的 count 116 | 117 |