跳至主要內容
请使用JS完成异步接口请求

XMLHttpRequest的 readyState 状态码

  • 0 - 代表未初始化。 还没有调用 open 方法
  • 1 - 代表正在加载。 open 方法已被调用,但 send 方法还没有被调用
  • 2 - 代表已加载完毕。send 已被调用。请求已经开始
  • 3 - 代表正在与服务器交互中。服务器正在解析响应内容
  • 4 - 代表完成。响应发送完毕

Get请求

function getAjax(url, query) {
  let queryData = []
  for (let key in query) {
    queryData.push(`${key}=${query[key]}`)
  }
  url = `${url}?${queryData.join('&')}&timeStamp=${new Date().getTime()}`
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest()
    xhr.open('get', url)
    xhr.send()
    xhr.onreadystatechange = () => {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          resolve(JSON.parse(xhr.responseText))
        } else {
          reject(xhr.statusText)
        }
      } else {
        reject(xhr.statusText)
      }
    }
  })
}

石怜安小于 1 分钟JavaScriptJavaScript
浏览器渲染原理

当浏览器的 「网络线程」 收到 「HTML 文档」后,会产生一个 渲染任务,并将其传递 「渲染主线程」 的消息队列。

在事件循环机制的作用下,渲染主线程取出消息队列中的渲染任务,开启渲染流程。

渲染时间点

石怜安大约 6 分钟JavaScriptJavaScript
浏览器进程模型

何为进程

程序运行需要有他自己专属的 「内存空间」,这块内存空间可以理解为 「进程」。

每个应用至少有一个进程,进程之间相互独立,即便要通信,也要双方同意。

何为线程

有了进程后,就可以运行程序的代码了。

运行代码的 「」 称之为 「线程」。

一个进程至少有一个线程,所以在进程开启后会自动创建一个线程来运行代码,该线程称之为 主线程


石怜安大约 8 分钟JavaScriptJavaScript
闭包以及内存泄漏原因

全文概述

描述: 函数嵌套函数,内部函数被外部函数返回并保存下来,就会产生闭包

特点: 可以重复利用变量,并且这个变量不会污染全局;这个变量一直保存在内存中,不会被垃圾回收机制回收

缺点: 闭包较多的时候,会消耗内存,导致页面性能下降,在IE浏览器中会导致内存泄露

使用: 防抖,节流,函数嵌套函数避免全局污染

高级描述:

  1. 函数 + 其定义时所处的词法环境
  2. 函数本身 + 内部属性[Environment]

内存泄漏条件:

  1. 持有了不再需要的函数引用,会导致函数关联的 词法环境 无法销毁,从而导致内存泄露
  2. 当多个函数 共享词法环境 时,会导致词法环境膨胀,从而导致出现 无法触达无法回收 的内存空间,导致内存泄漏

石怜安大约 4 分钟JavaScriptJavaScript
JavaScript 小技巧

一行代码完成结构加赋值

经常使用结构赋值,一般都是先结构,再赋值,当然也可以一行就完成解构加赋值操作,看起来非常简化,当然可读性你懂得!

let people = { name: null, age: null };
let result = { name: '张三',  age: 16 };

({ name: people.name, age: people.age } = result);
console.log(people) // {"name":"张三","age":16}

石怜安大约 5 分钟JavaScriptJavaScript
请使用JS完成一个JSON扁平化

代码实现

function expandJsonTool(data, k) {
  var jmap = {}
  var expandJson = function (jstr, mapIndex) {
    if (jstr instanceof Array) {
      for (var i in jstr) {
        expandJson(jstr[i], `${mapIndex}[${i}]`);
      }
    } else if (jstr instanceof Object) {
      for (var i in jstr) {
        // 如果mapIndex为false,null,''时,则不加初始索引
        if (!mapIndex) {
          var key = i;
        } else {
          var key = `${mapIndex}.${i}`;
        }
        // Array 是 Object 的子集,先判断是否为 Array,如果是,则不走Object的判断
        if (jstr[i] instanceof Array) {
          for (var j in jstr[i]) {
            expandJson(jstr[i][j], `${key}[${j}]`);
          }
        } else if ((jstr[i] instanceof Object)) {
          expandJson(jstr[i], key);
        } else if (typeof jstr[i] === 'string' && jstr[i].includes('{') && jstr[i].includes('}')) {
          expandJson(JSON.parse(jstr[i]), key);
        } else {
          jmap[key] = jstr[i]
        }
      }
    }
  }
  expandJson(data, k);
  return jmap
}

石怜安大约 1 分钟JavaScriptJavaScript
请使用JS完成一个LRU缓存

什么是 LRU?

LRU 英文全称是 Least Recently Used,英译过来就是 最近最少使用 的意思。

百度百科

LRU 是一种常用的页面置换算法,选择 最近 最久 未使用 的页面予以淘汰

该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所 经历的时间t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。


石怜安大约 5 分钟JavaScriptJavaScript
请使用JS完成异步加载图片
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
</html>
<script>
    function loadImage(url) {
        const promise = new Promise((resolve, reject) => {
            const img = document.createElement('img')
            img.onload = function() {
                resolve(img)
            }
            img.onerror = function() {
                const err = new Error(`图片加载失败,URL为: ${url}`)
                reject(err)
            }
            img.src = url
        })
        return promise
    }
    const url1 = 'https://placeholder.pics/svg/80x80/FF2030/FFF/image1'
    const url2 = 'https://placeholder.pics/svg/80x80/FF2030/FFF/image2'
    loadImage(url1)
        .then((res) => {
            document.body.appendChild(res)
            console.log('图片1加载成功', res)
            return loadImage(url2)
        }).then((res) => {
            document.body.appendChild(res)
            console.log('图片2加载成功', res)
         })
        .catch((err) => {
            console.log(err)
        })
</script>

石怜安小于 1 分钟JavaScriptJavaScript