前端基础面试题

CSS

HTML

  • 如何理解HTML语义化?
    (使用div和ul都能实现列表,但更推荐使用ul)
    增加代码可读性
    让搜索引擎更容易读懂(SEO)

  • 默认情况下,哪些HTML标签是块级元素、哪些是内联元素?
    display:block/table; 有 div h1 h2 ul ol li p table 等
    display:inline; 有 a、big、br、em、i、span、strong等
    /inline-block;有 img、input 、td 等

CSS

布局

  • 盒子模型的宽度如何计算?
    问:某 div 的 offsetWidth 是多少。
    offsetWidth = (内容宽度 + 内边距 + 边框),无外边距
    补充:如果让 offsetWidth 值固定,该如何做?
    加 box-sizing: border-box;

  • margin 纵向重叠的问题
    相邻元素的 margin-top 和 margin-bottom 会发生重叠
    空白内容的 <p> </p> 也会重叠

  • margin 负值的问题
    margin-top 和 margin-left 负值,元素向上、向左移动
    margin-right 负值,右侧元素左移,自身不受影响
    margin-bottom 负值,下方元素上移,自身不受影响

BFC理解和应用

- Block Format context ,块级格式化上下文。是 CSS 布局的一个概念:一块独立渲染区域,内部元素的渲染不会影响边界以外的元素。
- 形成BFC的常见条件:[ float 不是 none(浮动元素);position 是 absolute 或 fixed(绝对定位元素);overflow 不是 visible 的块元素 (auto, scroll, hidden)];display 是flex inline-block 等
- BFC的常见应用:消除margin合并(父元素添加overflow:hidden);清除浮动;阻止元素被浮动元素覆盖。

BFC布局规则:
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素;外面的元素也不会影响到容器里面的子元素;
内部的块级元素会在垂直方向,一个接一个地放置;
块级元素垂直方向的距离由margin决定。属于同一个BFC的两个相邻的块级元素会发生margin合并,不属于同一个BFC的两个相邻的块级元素不会发生margin合并
每个元素的margin box的左边,与包含border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此;
BFC的区域不会与float box重叠;
计算BFC的高度时,浮动元素也参与计算。

.clearfix:after{
    content:"";
    display:block;
    visibility:hidden;
    clear:both;
    }
  • float 布局的问题,以及clearfix(手写)

~~- float 布局:圣杯布局和双飞翼布局
- 目的:
三栏布局,中间一栏最先加载和渲染(内容最重要)。
两侧内容固定,中间内容随着宽度自适应。
一般用于PC网页。
- 技术总结:
使用 float 布局
两侧使用margin负值,一遍和中间内容横向重叠
防止中间内容被两侧覆盖,一个用 padding 一个用 margin

  • flex 画色子
    • flex 实现一个三点的色子(代码)~~

定位

- absolute 和 relative 分别依据什么定位?
relative 依据自身定位
absolute 依据最近一层的定位元素定位
定位元素:absolute relative fixed body

- 居中对齐有哪些方式?
- 水平居中
inline行内元素:text-align: center
block元素:margin: auto
absolute元素:left: 50% + margin-left 自身宽度一半负值
- 垂直居中
inline元素:inlin-height 值 等于 height 值
absolute元素:top: 50% + margin-top 自身高度一半负值
absolute 元素:transform(-50%, -50%) css3,要考虑兼容性
absolute 元素:top, left, bottom, right = 0; margin: auto;(自动填充) [终极方案]

图文样式

line-height 的继承问题

  • 写具体数值,如30px,则继承该值
  • 写比例,如2/1.5,则继承该比例
  • 写百分比,如200%,则继承计算出来的值(考点)

响应式

  • rem 是什么?
    rem 是一个长度单位

    • px,绝对长度单位,最常用
    • em,相对长度单位,相对于父元素,不常用
    • rem,相对长度单位,相对于根元素,常用于响应式布局
  • 响应式布局的常见方案?

    • media-query,根据不同的屏幕宽度设置根元素font-size
    • rem,基于根元素的相对单位
  • vw/vh

    • rem的弊端
      阶梯性。
    • 网页视口尺寸
      window.screen.height // 屏幕高度
      window.innerHeight // 网页视口高度
      document.body.clientHeight // body 高度
    • vw/vh
      vh 网页视口高度的1/100
      vw 网页视口宽度的1/100
      vmax 取两者最大值;vmin 取两者最小值

CSS3

关于CSS3动画(不是重点)

2. JS 基础

2.1 变量类型和计算

  • 值类型和引用类型的区别(会用计算 某对象属性值 形式出)

    • 值类型:undefined, string, number, boolean, Symbol()
    • 引用类型:object、array、null、function(特殊,不用于数据存储),统称对象类型
  • 对象类型又分为内置对象、宿主对象、自定义对象

    • 宿主环境:一般宿主环境由外壳程序创建与维护。如:web浏览器,一些桌面应用系统等。
    • 宿主对象:由JavaScript宿主环境提供的对象,可以理解为:浏览器提供的对象。所有的BOM和DOM都是宿主对象。
    • 本地对象:独立于宿主环境的 ECMAScript 实现提供的对象。如Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError。就是 ECMA-262 定义的类(引用类型)
    • 内置对象(built-in object):由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现。是本地对象的一种。Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。Global对象是ECMAScript中最特别的对象,因为实际上它根本不存在,但大家要清楚,在ECMAScript中,不存在独立的函数,所有函数都必须是某个对象的方法。类似于isNaN()、parseInt()和parseFloat()方法等,看起来都是函数,而实际上,它们都是Global对象的方法。
const 定义变量必须要赋值,否则会报错。(let a; 是有效的,a 的值是 undefinednull 是特殊的引用类型(typeof null === 'object',但书上写是值类型),意思为 指针指向空地址,
null == undefined,

函数式特殊引用类型,但不用于存储数据,所以没有“拷贝、赋值函数”这一说
  • typeof 能判断哪些类型
    识别所有值类型、识别函数、判断是否是引用类型(不可再细分)

    • instanceOf,判断 A 是否为 B 的实例
    • object.property.toString.call()。对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。
    • constructor。(当一个函数 F被定义时,JS引擎会为F添加 prototype 原型,然后再在 prototype上添加一个 constructor 属性,并让其指向 F 的引用。当执行 var f = new F() 时,F 被当成了构造函数,f 是F的实例对象,此时 F 原型上的 constructor 传递到了 f 上,因此 f.constructor == F)
  • 手写深拷贝(代码)

/**
 * 深拷贝
 * @param {Object} obj 要拷贝的对象
 */
function deepClone(obj = {}) {
    if (typeof obj !== 'object' || obj == null) {
        // obj 是 null ,或者不是对象和数组,直接返回
        return obj
    }

    // 初始化返回结果
    let result
    if (obj instanceof Array) {
        result = []
    } else {
        result = {}
    }

    for (let key in obj) {
        // 保证 key 不是原型的属性
        if (obj.hasOwnProperty(key)) {
            // 递归调用!!!
            result[key] = deepClone(obj[key])
            console.log(key, result[key], '--------------');
        }
    }

    // 返回结果
    return result
}

循环引用解决

变量计算-类型转换

  • 字符串拼接
const b = 100 + '10';  // ''10010
const b = 100 + parseInt('10');
const c = true + '10';  // 'true10'
  • == 运算符
    会发生类型转换:
100 == '100'  //true
0 == false  // true
'' == '0' // false
0 == '' // true
0 == '0' // true
false == ''  // true
false == 'false' // false
false == '0' // true

false == undefined // false
false == null // false
null == undefined  // true

什么时候用==:

// 除了 == null 之外,其他一律用 === ,例:
const obj = { x: 100 }
if(obj.a == null) {}
// 相当于:
// if (obj.a === null || obj.a === undefined) {}
// 在比较相等性之前,null和undefined不能被转化为其他任何值。
  • if 语句和逻辑运算
truly 变量:!!a === true 的变量
falsely 变量:!!a === false 的变量

// 以下是 falsely 变量。除此之外都是 truly 变量
!!0 === false
!!NaN === false
!!'' === false
!!null === false
!!undefined === false
!!false === false

逻辑判断:

console.log(10 && 0)  // 0
console.log('' || 'abc')  // 'abc'
console.log(!window.abc)  // true

2.3 作用域和闭包(重要)

题目

1、this 的不同应用场景,如何取值?
多记
2、手写bind函数
代码见js-demo -> bind-demo

3、实际开发中闭包的应用场景,举例说明
隐藏数据;(set 和 get)
如做一个简单的cache缓存工具

知识点

1、作用域和自由变量
自由变量:一个变量在当前作用域没有定义,但被使用了。从函数被定义的地方,不是在执行的地方 向上级作用域,一层一层依次寻找,直至找到为止。如果到全局作用域都没找到,则报错xX is not defined。

2、闭包
本质是作用域应用的特殊情况,有两种表现:函数作为参数被传递;函数作为返回值被返回。
在这里插入图片描述
自由变量 从它定义的地方开始寻找,而不是执行的地方

常见的:防抖和节流函数。

隐藏数据,只提供API
在这里插入图片描述
私有变量
闭包定义局部变量(自执行函数)

var Pclass = (function(){
    const a = Symbol('a');
    const m = Symbol('m');
    class  Pclass {
        constructor(){
            this[a] = 'a这是私有变量';
            this.b = '变量B-外部可访问';
            this[m] = function(){
                console.log('私有方法');
            }
        }
        getA(){
            console.log(this[a]);
        }
        getM(){
            console.log(this[m]);
        }
    }
    return Pclass
}())
 
let pc = new Pclass() 
console.log(pc)   //打印 Pclass {b: "变量B-外部可访问", Symbol(a): "这是私有变量", Symbol(m): ƒ}

3、this
this 取值是在函数执行的时候确认的。
箭头函数永远取它上级作用域的this.
在这里插入图片描述
这里的function() {console.log(this)} 是被当做普通函数执行的,并不是因为setTimeout属于window。

作为普通函数 :直接返回window
使用call apply bind
作为对象方法被调用
在class方法中调用
箭头函数

4.4 ajax

题目:

  • 手写一个简易的ajax
const xhr = new XMLHttpRequest()
xhr.open('GET', '/data/test.json', true) // true 代表异步,默认。
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
        if (xhr.status === 200) {
            // console.log(
            //     JSON.parse(xhr.responseText)
            // )
            alert(xhr.responseText)
        } else if (xhr.status === 404) {
            console.log('404 not found')
        }
    }
}
xhr.send(null)
  • 跨域的常用实现方式
    JSONP , CORS

4.4.1 XMLHttpRequest

4.4.2 同源策略

ajax请求时,浏览器要求当前网页和server必须同源(安全)
同源:协议、域名、端口,三者必须–致

加载图片css js可无视同源策略:

<img src=跨域的图片地址/>
<link href=跨域的css地址/>
<script src=跨域的js地址> </script>

<img />可用于统计打点,可使用第三E方统计服务
<link /> <script> 可使用CDN,CDN-般都是外域
<script>可实现JSONP

所有的跨域,都必须经过server端允许和配合
未经server端允许就实现跨域,说明浏览器有漏洞,危险信号


前端发送跨域请求,可能会额外发送一次OPTIONS请求(可用于检测服务器允许的http方法),也就是预检请求(preflight request)。服务器若接受该跨域请求,浏览器才继续发起正式请求。
在请求中,会分为 简单请求 和 复杂请求 。
触发条件:

  1. (使用了PUT、DELETE等http方法)使用了下面任一HTTP 方法:
    PUT/DELETE/CONNECT/OPTIONS/TRACE/PATCH
  2. (人为设置了额外的首部字段)人为设置了以下集合之外首部字段:
    Accept/Accept-Language/Content-Language/Content-Type/DPR/Downlink/Save-Data/Viewport-Width/Width
  3. (Content-Type 不包含于指定的范围)Content-Type 的值不属于下列之一:
    application/x-www-form-urlencoded、multipart/form-data、text/plain

Access-Control-Max-Age这个响应首部表示 preflight request (预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存的最长时间,单位是秒。如果值为 -1,则表示禁用缓存,每一次请求都需要提供预检请求,即用OPTIONS请求进行检测。(MDN)

简单请求:
请求方法为:GET、POST、HEAD
请求头:Accept、Accept-Language、Content-Language、Content-Type

来源

4.4.3 跨域:同源策略,跨域解决方案

JSONP

访问https://imooc.com/ , 服务端一定返回一个 html 文件吗?
服务器可以任意动态拼接数据返回,只要符合html格式要求
同理于<script src= "https://imooc.com/getData.js” >

<script>可绕过跨域限制
服务器可以任意动态拼接数据返回
所以, <script>就可以获得跨域的数据,只要服务端愿意返回

注意。!!服务端要在返回的数据外层包裹一个客户端已经定义好的函数!! 如果不加,会报错 语法错误。

详细见 笔记

CORS - 服务器设置 http header

在这里插入图片描述
spring 4.2 以上支持了跨域接口

跨域请求中携带cookie

参考

  • 同域名下发送ajax请求,请求中默认会携带cookie
  • ajax在发送跨域请求时,默认情况下是不会携带cookie的
  • 前端设置
    • ajax在发送跨域请求时如果想携带cookie,必须将请求对象的withCredentials属性设置为true。
  • 后端设置
    • 此时服务端的响应头Access-Control-Allow-Origin不能为*(星号)了,必须是白名单样式,也就是必须设置允许哪些url才能访问,如:
      Access-Control-Allow-Origin: http://api.bob.com
    • 除了对响应头Access-Control-Allow-Origin的设置,还必须设置另外一个响应头:Access-Control-Allow-Credentials:true。
webpack 配置devserver 代理也可实现跨域

仅开发环境

devServer: {
    port: 8080,
    progress: true,  // 显示打包的进度条
    contentBase: distPath,  // 根目录
    open: true,  // 自动打开浏览器
    compress: true,  // 启动 gzip 压缩

    // 设置代理
    proxy: {
        // 将本地 /api/xxx 代理到 localhost:3000/api/xxx
        '/api': 'http://localhost:3000',

        // 将本地 /api2/xxx 代理到 localhost:3000/xxx
        '/api2': {
            target: 'http://localhost:3000',
            pathRewrite: {
                '/api2': ''
            }
        }
    }
}
Nginx 反向代理

反向代理代理的是服务端,可以隐藏真实数据。在这里充当一个代理服务器的角色,它会根据不同请求和配置规则,做相应的转发,然后将服务端返回的数据递交给客户端,来解决跨域的问题。

server {
        listen   80;
        server_name  localhost;
        ## 用户访问 localhost,则反向代理到https://api.shanbay.com
        location / {
            root   html;
            index  index.html index.htm;
            proxy_pass https://api.shanbay.com;
        }
        location /api {  // 前端就不需要再加http://...了
			root html;
			proxy_pass http://localhost:8101/;
			index index.html;
		}
}

location 匹配规则:
location 支持的语法location [=|~|~*|^~|@] pattern { ... }

  • 「=」 修饰符:要求路径完全匹配
  • 「~」修饰符:区分大小写的正则匹配
  • 「~*」不区分大小写的正则匹配
  • 「^~」修饰符:最大前缀匹配 如果该 location 是最佳的匹配,那么对于匹配这个 location 的字符串, 该修饰符不再进行正则表达式检测。注意,这不是一个正则表达式匹配,它的目的是优先于正则表达式的匹配。如location /a/{},location /a/b/ {},请求 http://a/b/c.html 匹配的是 location /a/b/ {}

匹配规则:

  • 先普通,再正则
  • 普通location之间的匹配顺序:按最大前缀匹配
    如location /a/{},location /a/b/ {},请求 http://a/b/c.html 匹配的是 location /a/b/ {}
  • 正则location之间的匹配顺序:按配置文件中的物理顺序匹配,只要匹配到一条正则,就不再考虑后面的
  • 若普通location匹配到 精确匹配= 或 非正则匹配 ^~, 则不再进行后续的正则匹配
  • 普通location与正则location之间的匹配结果选择
    • 普通location先匹配,匹配到了结果,只是一个临时结果;
    • 会继续正则location的匹配,
      • 如果匹配到正则,则用匹配到的正则结果;
      • 如果没有匹配到正则,则继续用普通匹配的那个结果
        综上,常规的顺序是匹配完普通location,还要继续匹配正则location,但是,也可以告诉nginx,匹配到了普通location,就不要再搜索匹配正则location了,通过在普通location前面加上~符号,表示非,表示正则,^就是表示不要继续匹配正则。

除了~,=也可阻止nginx继续匹配正则,区别在于~依然遵循最大前缀匹配规则,而=是严格匹配

参考

postMessage

postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:

  • 页面和其打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套的iframe消息传递
  • 上面三个场景的跨域数据传递

message: 将要发送到其他 window的数据。
targetOrigin:通过窗口的origin属性来指定哪些窗口能接收到消息事件,其值可以是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。
transfer(可选):是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

// a.html
  <iframe src="http://localhost:4000/b.html" frameborder="0" id="frame" onload="load()"></iframe> //等它加载完触发一个事件
  //内嵌在http://localhost:3000/a.html
    <script>
      function load() {
        let frame = document.getElementById('frame')
        frame.contentWindow.postMessage('我爱你', 'http://localhost:4000') //发送数据
        window.onmessage = function(e) { //接受返回数据
          console.log(e.data) //我不爱你
        }
      }
    </script>
// b.html
  window.onmessage = function(e) {
    console.log(e.data) //我爱你
    e.source.postMessage('我不爱你', e.origin)
 }

4.4.4 ajax 常用插件

Jquery(基于回调函数,没有promise) , fetch(promise 出错不报错,cookie) , axios(框架中用的多)

4.5 存储

4.5.1 题目

描述cookie localStorage sessionStorage区别:
容量
API易用性
是否跟随http请求发送出去

4.5.2 知识点

cookie

字符串,;分割

本身用于浏览器和server通讯
被“借用”到本地存储来
前端可用document.cookie = ‘…’ 来修改(同一个key会修改,不同的会追加),后端在HttpResponse响应中追加Set-Cookie的头部

缺点:
存储大小,最大4KB
http请求时需要发送到服务端,增加请求数据量
只能用document.cookie = ‘…’ 来修改,太过简陋

localStorage和sessionStorage

HTML5专门为存储而设计,最大可存5M
API简单易用setItem getItem
不会随着http 请求被发送出去

localStorage数据会永久存储,除非代码或手动删除
sessionStorage数据只存在于当前会话,浏览器关闭则清空
般用localStorage会更多- -些

cookie 和 session 区别

客户端第一次请求,服务端会在响应的时候在客户端种下一个cookie,下次请求时,客户端会自动带上这个cookie,服务端会根据这个cookie从服务端的session中取出登录状态和用户信息返回客户端或者用来用户认证,session本质上是服务端的一块数据可以存储在服务器或者redis中,所以说session登录验证方案基于cookie实现

关闭浏览器自动清除缓存

后来才猛然想起,如果我在后台添加cookie到响应头时,就不指定过期时间,那么这个cookie就是一个会话型cookie,当浏览器关闭时,这个cookie就会被浏览器自动删除。

但当时我就想不明白为什么使用js删除就不行,于是就跑到网上去问。终于有大神给出了答案,原来在后台添加cookie时,设置了cookie的HttpOnly属性为true,这样当前cookie就不能通过客户端浏览器的脚本来访问。我后来自己去试了一下,果然如此。当然js删除cookie失败的可能原因并不只于此,具体参考以下博文:http://www.cnblogs.com/gossip/archive/2011/12/06/2278282.html

https://blog.csdn.net/weixin_34252090/article/details/92142809

5. http

题目:
1、http常见的状态码有哪些?
2、http常见的header有哪些?
3、什么是Restful API
4、描述一下http的缓存机制(important)

5.1 http 状态码

5.1.1 状态码分类

1xx 服务器收到请求 ,接收的请求正在处理
2xx 请求成功,如200
3xx 重定向, 需要进行附加操作以完成请求,如302
4xx 客户端错误,如404 (客户端请求了一个服务端根本不存在的地址)
5xx 服务端错误,如500 (出bug)

5.1.2 常见状态码

  • 200 成功
  • 204 请求已成功处理,但在返回的响应报文中不含实体数据。一般在只需要从客户端往服务器发送信息,而对客户端不需要发送新信息内容的情况下使用。
  • 301 永久重定向(配合location , 浏览器自动处理。不会再访问老的地址)。表示请求的资源已被分配了新的URI,以后应使用资源现在所指的URI。也就是说,如果已经把资源对应的URI保存为书签了,这时应该按Location 首部字段提示的URI重新保存。比较常用的场景是使用域名跳转,比如,访问 http://www.baidu.com 会跳转到 https://www.baidu.com,发送请求之后,就会返回301状态码,然后返回一个location,提示新的地址,浏览器就会拿着这个新的地址去访问。
  • 302 临时重定向(配合location ,浏览器自动处理)。比如未登陆的用户访问用户中心重定向到登录页面。
  • 304 资源未被修改(缓存还有效)
  • 400 badRequest,请求报文存在语法错误。比如要填的表单项指定是number类型,但是用户填了string类型
  • 401 UnauthorizedError,认证失败,如请求头里没有携带指定的token,或者token失效
  • 403 没有权限
  • 404 资源未找到
  • 500 服务端执行请求时发生了错误
  • 503 服务器超载或正在停机维护
  • 504 网关超时(比如服务器在连接数据库时超时)

5.1.3 关于协议和规范

一个约定,跟着约定执行。

5.2 http methods

  • 传统的methods:get获取服务器的数据,post向服务器提交数据,简单的网页功能,就这两个操作

  • 现在的methods:
    get获取数据
    post新建数据
    patch/put更新数据
    delete删除数据

5.2.1 Restiful-API

一种新的 API设计方法(早已推广使用)
传统API设计:把每个url当做一个功能;
Restful API设计:把每个url当做一个唯一 的资源

如何设计成一个资源?
  • 尽量不用url参数
    传统API设计: /api/list?pageIndex=2
    Restful API设计: /api/list/2
  • 用method表示操作类型
    传统:
    post请求:/api/create-blog
    post请求:/api/update-blog?id=100 更新
    get请求:/api/get-blog?id=100
    RestifulAPI:
    post请求:/api/blog
    patch请求:/api/blog/100 更新
    get请求:/api/blog/100

5.3 http headers

5.3.1 常见的Request Headers

  • Accept浏览器可接收的数据格式
  • Accept-Encoding浏览器可接收的压缩算法,如gzip
  • Accept-Languange浏览器可接收的语言,如zh-CN
  • Connection: keep-alive 一次TCP连接重复使用
  • cookie:服务器将会受到的cookie信息
  • Host 请求的域名~~+端口号~~
  • User-Agent (简称UA )浏览器信息
  • Content-type发送数据的格式,一般用于设置 post 的参数格式。如application/json(json数据格式),application/x-www-form-urlencoded(表单默认的提数据格式),multipart/form-data(一般用于文件上传)

5.3.2 常见的Response Headers

  • Content-type 返回数据的格式,
    • text开头,text/html: HTML格式;text/plain:纯文本格式;text/xml: XML格式
    • application开头,application/json:JSON 数据格式;application/pdf:pdf 格式;application/xml:XML 数据格式
      Content-length返回数据的大小,多少字节
    • 图片格式,image/gif :gif 图片格式;image/jpeg :jpg 图片格式;image/png:png 图片格式
  • Content-Encoding返回数据的压缩算法,如gzip
  • Set-cookie 服务端需要改cookie
  • cache-Control 强制缓存

5.3.3 自定义header

5.4 http 缓存

5.4.1 关于缓存的介绍

14-6~最后 webpack 学完来看
目的是 减少网络请求的数量
哪些资源可以被缓存?-静态资源( js CSS img )

5.4.2 http缓存策略(强制缓存+协商缓存)

5.4.3 刷新操作方式,对缓存的影响

正常操作:地址栏输入url , 跳转链接,前进后退等
手动刷新: F5 ,点击刷新按钮,右击菜单刷新
强制刷新: ctrl + F5

7. 运行环境

运行环境即浏览器( server端有nodejs )
负责:下载网页代码,渲染出页面,期间会执行若干JS
要保证代码在浏览器中:稳定且高效

7.2 性能优化

是一个综合性问题,没有标准答案,但要求尽量全面
某些细节问题可能会单独提问:手写防抖、节流.

性能优化原则:
多使用内存、缓存或其他方法.
减少CPU计算量,减少网络加载耗时
(适用于所有编程的性能优化一空间换时间 )

从何入手:

  • 让加载更快:
    1、减少资源体积:压缩代码;
    2、减少访问次数:合并代码, SSR服务器端渲染(服务端把页面及页面要显示的内容一并发出),缓存;
    3、使用更快的网络:CDN

  • 让渲染更快:
    1、CSS放在head,JS放在body最下面;
    2、尽早开始执行JS ,用DOMContentLoaded触发;
    3、懒加载(图片懒加载,上滑加载更多)。
    4、对DOM查询进行缓存
    5、频繁DOM操作,合并到一起插入DOM结构
    6、节流throttle 防抖debounce

16-6 跳过,学过webpack再来看

7.2.1 防抖

监听一个输入框的,文字变化后触发change事件
直接用keyup事件,则会频发触发change事件
防抖:用户输入结束或暂停时,才会触发change事件

// 防抖
function debounce(fn, delay = 500) {
    // timer 是闭包中的
    let timer = null

    return function() {
        if (timer) {
            clearTimeout(timer)
        }
        timer = setTimeout(() => {
            console.log('this', this); // input1
            fn.apply(this, arguments)
            timer = null
        }, delay)
    }
}

input1.addEventListener('keyup', debounce(function(e) {
    console.log(e.target)
    console.log(input1.value)
}, 600))

7.2.2 节流

拖拽一个元素时,要随时拿到该元素被拖拽的位置
直接用drag事件,则会频发触发,很容易导致卡顿
节流:无论拖拽速度多快,都会每隔100ms触发一次

// 节流
function throttle(fn, delay = 100) {
    let timer = null

    return function() {
        if (timer) {
            return
        }
        timer = setTimeout(() => {
            fn.apply(this, arguments) // 箭头函数没有arguments,这里的arguments是上层作用域的。
            timer = null
        }, delay)
    }
}

div1.addEventListener('drag', throttle(function(e) {
    console.log(e.offsetX, e.offsetY)
}))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值