2019-07 下旬

作者: Bougie 创建于: 2019-07-21 | 成长
  • 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 运行环境下的一些功能。

  • 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 的理解
好好想想先 😌

  • 2019-07-28: Object.defineProperty 和 Proxy 实现双向绑定的区别
好好想想先 😌
  • 参考链接
  • 一句话
    • 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://www.bougieblog.cn/a.html?hello=world&a=你'
    escape(str) // "https%3A//www.bougieblog.cn/a.html%3Fhello%3Dworld%26a%3D%u4F60"
    encodeURI(str) // "https://www.bougieblog.cn/a.html?hello=world&a=%E4%BD%A0"
    encodeURIComponent(str) // "https%3A%2F%2Fwww.bougieblog.cn%2Fa.html%3Fhello%3Dworld%26a%3D%E4%BD%A0"
    
上次更新: 2019-8-10 23:51:27