2019-07 下旬 ✅
- 创建于:2019-07-21
- 更新于:2023-03-16

# 2019-07-31: react-router 3 和 react-router 4 的区别, react-router 和 react-router-dom 的关系 ✅✅
好好想想先 😌
- 参考链接
- 一句话
- react-router 3 和 react-router 4 的区别
- react-router 4 分为 react-router 和 react-router-dom
- react-router 3 支持配置式声明,react-router 4 只支持组件式声明
- react-router 3 有路由生命周期,react-router 4 中没有
- react-router 和 react-router-dom 的关系
- react-router: 实现了路由的核心功能
- react-router-dom: 基于 react-router,加入了在浏览器运行环境下的一些功能,例如:Link 组件,会渲染一个 a 标签,Link 组件源码 a 标签行; BrowserRouter 和 HashRouter 组件,前者使用 pushState 和 popState 事件构建路由,后者使用 window.location.hash 和 hashchange 事件构建路由。
- react-router-native: 基于 react-router,类似 react-router-dom,加入了 react-native 运行环境下的一些功能。
- react-router 3 和 react-router 4 的区别
# 2019-07-30: React 内置了哪些 Hooks?有何作用? ✅✅
好好想想先 😌
参考链接
一句话
- useState - 返回一个 state,以及更新 state 的函数。
function Counter({ initialCount }) { const [count, setCount] = useState(initialCount) return ( <> Count: {count} <button onClick={() => setCount(initialCount)}>Reset</button> <button onClick={() => setCount((prevCount) => prevCount + 1)}> + </button> <button onClick={() => setCount((prevCount) => prevCount - 1)}>-</button> </> ) }- useEffect(didUpdate) - 该 Hook 接收一个包含命令式、且可能有副作用代码的函数。
useEffect(() => { const subscription = props.source.subscribe() return () => { // 清除订阅 subscription.unsubscribe() } }) // 依赖项 useEffect(() => { const subscription = props.source.subscribe() return () => { subscription.unsubscribe() } }, [props.source])- useContext - 接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。
const value = useContext(MyContext)
# 2019-07-29: 对 React Hooks 的理解 ✅✅
好好想想先 😌
- 参考链接
- 一句话
- 无生命周期
- 无 class API,无 this 的烦劳
# 2019-07-28: Object.defineProperty 和 Proxy 实现双向绑定的区别 ✅✅
好好想想先 😌
- 参考链接
- 一句话
- Object.defineProperty 通过设置 set 属性来实现双向绑定
- Proxy 通过设置 handler 的 set 来实现双向绑定
- Object.defineProperty 无法监控到数组下标的变化,导致通过数组下标添加元素,不能实时响应;
- Object.defineProperty 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。Proxy 可以劫持整个对象,并返回一个新的对象。
- Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。
# 2019-07-27: 实现一个防抖和节流函数 ✅✅
好好想想先 😌
参考链接
一句话
- 防抖
function debounce(func, wait) { let timeout return function () { let args = arguments if (timeout) clearTimeout(timeout) timeout = setTimeout(() => { func.apply(this, args) }, wait) } }- 节流
function throttle(func, wait) { let timeout return function () { let context = this let args = arguments if (!timeout) { timeout = setTimeout(() => { timeout = null func.apply(context, args) }, wait) } } }
# 2019-07-26: 实现一个 flattenDeep ✅✅
好好想想先 😌
- 一句话
function flattenDeep(arr) { return arr.reduce( (acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), [] ) } console.log(flattenDeep([1, 2, [3, [4, [5]]]]))
# 2019-07-25: 数组去重的方法 ✅✅
好好想想先 😌
- 参考链接
- 一句话
- 利用 Set
function uniq(arr) { return Array.from(new Set(arr)) }- 利用 reduce
function uniq(arr) { return arr.reduce( (prev, cur) => (prev.includes(cur) ? prev : [...prev, cur]), [] ) }
# 2019-07-24: 响应头有哪些值?分别有什么作用? ✅✅
好好想想先 😌
参考链接
一句话
Allow 服务器支持哪些请求方法(如 GET、POST 等)。
Content-Encoding 文档的编码(Encode)方法。只有在解码之后才可以得到 Content-Type 头指定的内容类型。利用 gzip 压缩文档能够显著地减少 HTML 文档的下载时间。Java 的 GZIPOutputStream 可以很方便地进行 gzip 压缩,但只有 Unix 上的 Netscape 和 Windows 上的 IE 4、IE 5 才支持它。因此,Servlet 应该通过查看 Accept-Encoding 头(即 request.getHeader("Accept-Encoding"))检查浏览器是否支持 gzip,为支持 gzip 的浏览器返回经 gzip 压缩的 HTML 页面,为其他浏览器返回普通页面。
Content-Length 表示内容长度。只有当浏览器使用持久 HTTP 连接时才需要这个数据。如果你想要利用持久连接的优势,可以把输出文档写入 ByteArrayOutputStream,完成后查看其大小,然后把该值放入 Content-Length 头,最后通过 byteArrayStream.writeTo(response.getOutputStream()发送内容。
Content-Type 表示后面的文档属于什么 MIME 类型。Servlet 默认为 text/plain,但通常需要显式地指定为 text/html。由于经常要设置 Content-Type,因此 HttpServletResponse 提供了一个专用的方法 setContentType。
Date 当前的 GMT 时间。你可以用 setDateHeader 来设置这个头以避免转换时间格式的麻烦。
Expires 应该在什么时候认为文档已经过期,从而不再缓存它?
Last-Modified 文档的最后改动时间。客户可以通过 If-Modified-Since 请求头提供一个日期,该请求将被视为一个条件 GET,只有改动时间迟于指定时间的文档才会返回,否则返回一个 304(Not Modified)状态。Last-Modified 也可用 setDateHeader 方法来设置。
Location 表示客户应当到哪里去提取文档。Location 通常不是直接设置的,而是通过 HttpServletResponse 的 sendRedirect 方法,该方法同时设置状态代码为 302。
Refresh 表示浏览器应该在多少时间之后刷新文档,以秒计。除了刷新当前文档之外,你还可以通过 setHeader("Refresh", "5; URL=http://host/path")让浏览器读取指定的页面。 注意这种功能通常是通过设置 HTML 页面 HEAD 区的< META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">实现,这是因为,自动刷新或重定向对于那些不能使用 CGI 或 Servlet 的 HTML 编写者十分重要。但是,对于 Servlet 来说,直接设置 Refresh 头更加方便。注意 Refresh 的意义是"N 秒之后刷新本页面或访问指定页面",而不是"每隔 N 秒刷新本页面或访问指定页面"。因此,连续刷新要求每次都发送一个 Refresh 头,而发送 204 状态代码则可以阻止浏览器继续刷新,不管是使用 Refresh 头还是< META HTTP-EQUIV="Refresh" ...>。注意 Refresh 头不属于 HTTP 1.1 正式规范的一部分,而是一个扩展,但 Netscape 和 IE 都支持它。
Server 服务器名字。Servlet 一般不设置这个值,而是由 Web 服务器自己设置。
Set-Cookie 设置和页面关联的 Cookie。Servlet 不应使用 response.setHeader("Set-Cookie", ...),而是应使用 HttpServletResponse 提供的专用方法 addCookie。参见下文有关 Cookie 设置的讨论。
WWW-Authenticate 客户应该在 Authorization 头中提供什么类型的授权信息?在包含 401(Unauthorized)状态行的应答中这个头是必需的。例如,response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")。 注意 Servlet 一般不进行这方面的处理,而是让 Web 服务器的专门机制来控制受密码保护页面的访问(例如.htaccess)。
Cache-Control 是最重要的规则。这个字段用于指定所有缓存机制在整个请求/响应链中必须服从的指令。这些指令指定用于阻止缓存对请求或响应造成不利干扰的行为。这些指令通常覆盖默认缓存算法。缓存指令是单向的,即请求中存在一个指令并不意味着响应中将存在同一个指令。网页的缓存是由 HTTP 消息头中的“Cache-control”来控制的,常见的取值有 private、no-cache、max-age、must-revalidate 等,默认为 private。其作用根据不同的重新浏览方式分为以下几种情况。
ETag
# 2019-07-23: 什么是 webworker? 有何特点? ✅✅
好好想想先 😌
参考链接
一句话
- Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。
- 主线程
var worker = new Worker('work.js') worker.postMessage('Hello World') worker.postMessage({ method: 'echo', args: ['Work'] }) worker.onmessage = function (event) { console.log('Received message ' + event.data) doSomething() } function doSomething() { // 执行任务 worker.postMessage('Work done!') } worker.terminate()- worker 线程
self.addEventListener( 'message', function (e) { var data = e.data switch (data.cmd) { case 'start': self.postMessage('WORKER STARTED: ' + data.msg) break case 'stop': self.postMessage('WORKER STOPPED: ' + data.msg) self.close() // Terminates the worker. break default: self.postMessage('Unknown command: ' + data.msg) } }, false )
# 2019-07-22: Object 对象上有哪些静态方法?作用是什么? ✅✅
好好想想先 😌
参考链接
一句话
- Object.assign() * - 通过复制一个或多个对象来创建一个新的对象。
- Object.create() - 使用指定的原型对象和属性创建一个新对象。
- Object.defineProperty() * - 给对象添加一个属性并指定该属性的配置。
- Object.defineProperties() * - 给对象添加多个属性并分别指定它们的配置。
- Object.entries() * - 返回给定对象自身可枚举属性的 [key, value] 数组。
- Object.freeze() - 冻结对象:其他代码不能删除或更改任何属性。
- Object.getOwnPropertyDescriptor() - 返回对象指定的属性配置。
- Object.getOwnPropertyDescriptors()
- Object.getOwnPropertyNames() - 返回一个数组,它包含了指定对象所有的可枚举或不可枚举的属性名。
- Object.getOwnPropertySymbols() - 返回一个数组,它包含了指定对象自身所有的符号属性。
- Object.getPrototypeOf() * - 返回指定对象的原型对象。
- Object.is() - 比较两个值是否相同。所有 NaN 值都相等(这与==和===不同)。
- Object.isExtensible() - 判断对象是否可扩展。
- Object.isFrozen() - 判断对象是否已经冻结。
- Object.isSealed() - 判断对象是否已经密封。
- Object.keys() * - 返回一个包含所有给定对象自身可枚举属性名称的数组。
- Object.preventExtensions() - 防止对象的任何扩展。
- Object.seal() - 防止其他代码删除对象的属性。
- Object.setPrototypeOf() * - 设置对象的原型(即内部 [[Prototype]] 属性)。
- Object.values() * - 返回给定对象自身可枚举值的数组。
# 2019-07-21: encodeURI, encodeURIComponent, escape 作用 ✅✅
好好想想先 😌
- 参考链接
- 一句话
- URI(统一资源标识符)
- Scheme : First / Second ; Third ? Fourth
- escape() 函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串
- encodeURI() 函数可把字符串作为 URI 进行编码
- encodeURIComponent() 函数可把字符串作为 URI 组件进行编码
const str = 'https://bougieL.github.io/a.html?hello=world&a=你' escape(str) // "https%3A//bougieL.github.io/a.html%3Fhello%3Dworld%26a%3D%u4F60" encodeURI(str) // "https://bougieL.github.io/a.html?hello=world&a=%E4%BD%A0" encodeURIComponent(str) // "https%3A%2F%2FbougieL.github.io%2Fa.html%3Fhello%3Dworld%26a%3D%E4%BD%A0" - URI(统一资源标识符)