首页 > 万字前端面试八股文,建议打印出来放床头
头像
牛雪碧
发布于 2021-11-17 21:53
+ 关注

万字前端面试八股文,建议打印出来放床头

万字前端面试八股文,建议打印出来放床头

众所周知啊,前端是一个要求你啥都会的岗位。不会算法的前端一定开发不出一个好的后台。

话不多说,直接上干货前端知识点干货。

不知道牛客上这个导航好使不。

JavaScript HTML CSS browser

JavaScript

基本数据类型

js 一共有7种基本数据类型,分别是 Undefined、Null、Boolean、Number、String。
(注意大写字母开头)(大写字母开头)(大写字母开头)
ES6 中新增的 Symbol 类型,代表创建后独一无二且不可变的数据类型,主要是为了解决可能出现的全局变量冲突的问题。

ES2020新增BigInt,用于处理任意精度整数的新数字基元n,比如3n。

ES5中有6种数据类型:(另一个说法,注意没有基本2字)
null,undefined,number,string,boolean,object。

  • 复杂类型是指object即广义的对象类型,可由多个简单类型的值的合成,可以看作是一个存放各种值的容器。包括Array,Math,Date,RegExp,Function等
  • 基础类型指number,string,boolean,null,undefined。

基础类型和复杂类型的区别:

  • 基础类型将内容直接存储在中(大小固定位置连续的存储空间),记录的是该数据类型的值,即直接访问,基础类型赋值是复制(copy);
  • 复杂类型将内容存储在堆中,堆所对应的栈中记录的是指针(堆的地址),外部访问时先引出地址,再通过地址去找到值所存放的位置。复杂类型赋值是地址引用。
//经典考题1地址引用
let a = {name:'du',age:19};
let b =a;
console.log(b.name);//du
b.name = 'lee';
console.log(b.name);//lee
console.log(a.name);//lee a中的属性改变,说明a和b指向同一地址
//经典考题2
let a = {name:'du',age:19};
function change (obj){
 obj.age=29;  //obj作为对象参数,引用地址传入,修改age属性影响了原对象
 obj = {   //赋值操作,相当新建了一个对象让obj指向他
     name:'lee',
     age:39
 }
 return obj;  //返回新对象
}
let b=change(a);
console.log(a.age);//29,a中已改变
console.log(b.age);//39,b为新对象

js是一种解释性:不用编译;动态:不用声明类型,弱类型:类型转换,语言

JavaScript数字全部是浮点数。 根据 IEEE 754标准中的64位二进制(binary64), 也称作双精度规范(double precision)来储存。这些字节按照以下规则分配:

0 - 51 位是 分数f(fraction )
52 - 62 位是 指数(exponent )
63 位 是 标志位 (sign),结果二进制形式为是+- 1.f * 2e,最大精确的整数为2**53

//经典考题
0.1+0.1===0.2 //true
0.1+0.2===0.3 //false

原理解析见本文,帮助理解。

null 和 undefined 的区别

  • Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null。
  • undefined 代表的含义是未定义,null 代表的含义是空对象。一般变量声明了但还没有定义的时候会返回 undefined,null主要用于赋值给一些可能会返回对象的变量,作为初始化。
  • undefined 在 js 中不是一个保留字,这意味着我们可以使用 undefined 来作为一个变量名,这样的做法是非常危险的,它会影响我们对 undefined 值的判断。但是我们可以通过一些方法获得安全的 undefined 值,比如说 void 0。
  • 当我们对两种类型使用 typeof 进行判断的时候,null 类型化会返回 “object”,这是一个历史遗留的问题。
  • undefined==null(true) undefined===null(false)

判断数据类型的方式

  1. typeof 缺陷:可以判断null以外的基础类型,复杂类型除funiton以外均判断为object

    // typeof(null)===‘’object’;typeof (()=>{} ))===‘function’;

  2. instanceof 可以准确判断复杂引用类型,但不能判断基础类型

    //Object instanceof Object//true

  3. Object.prototype.toString.call() ;可以判断所有类型,返回示例 ''[object Array]"

    注意后面的类型一定是大写字母开头。

    Object.prototype.toString.call(null);
    //"[object Null]"
  4. .constructor=== //返回构造器,例如(2.1).constructor === Number//true

一些隐式转换规则(选择题爱考这个)

字符串转换 .toString()或者String():

​ null 和 undefined 类型 ,null 转换为 "null",undefined 转换为 "undefined",
Boolean 类型,true 转换为 "true",false 转换为 "false"。
Number 类型的值直接转换,不过那些极小和极大的数字会使用指数形式。

数字转换:

(1)undefined 类型的值转换为 NaN。
(2)null 类型的值转换为 0。
(3)Boolean 类型的值,true 转换为 1,false 转换为 0。
(4)String 类型的值转换如同使用 Number() 函数进行转换,包含非数字值则转换为 NaN,空字符串为 0,"-Infinity"转化为-Infinity
{}转换为NaN。[]转为0.

布尔值转换:

以下均为false,除外都为true 例如Boolen(' ')为true,Boolen([])为true

• undefined
• null
• false
• +0、-0 和 NaN
• ""

如何将字符串转化为数字,例如 '12.3b'

(1)使用 Number() 方法,前提是所包含的字符串不包含不合法字符。

(2)使用 parseInt() 方法,parseInt() 函数可解析一个字符串,并返回一个整数。还可以设置要解析的数字的基数。当基数的值为 0,或没有设置该参数时,parseInt() 会根据 string 来判断数字的基数。

经典题:[1,2,3].map(parseInt) ===[1,NaN,NaN]

(3)使用 parseFloat() 方法,该函数解析一个字符串参数并返回一个浮点数。

内容有点多,做一个html的隐藏折叠显示

遍历对象

<details> <summary>点击展开</summary>
- Object.keys()

返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性).数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。

let obj = {name: 'lee',sex: 'male',age: 18}
Object.keys(obj).forEach(key => {
    console.log(key, obj[key]);
})
  • for...in

循环遍历对象自身的和继承的可枚举属性(不含Symbol属性).

  • Object.getOwnPropertyNames()

返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性).

  • Reflect.ownKeys()

返回一个数组,包含对象自身的所有属性(包括Symbol属性和不可枚举属性).

</details> <details> <summary>点击展开</summary>
### 遍历数组
  • forEach()
let arr = [1,2,,3];
arr.forEach((v,k) => {
    console.log(v);
})//跳过空
  • for...in
> 注意for...in遍历的是索引
let arr = [1,2,,3];
for(let ele in arr) {
    console.log(ele);
}
//0 1 3
  • for...of
let arr = [1,2,,3];
for(let ele of arr) {
    console.log(ele);
}
//1,2,undefined,3
</details>

js的对象的常用的方法

<details> <summary>点击展开</summary>
Object.assign() //浅复制对象

Object.entries() //返回自身可枚举的[key,value]
Object.keys(),Object.values()
Object.hasOwnProperty(key)//是否有这个属性 true/false
Object.getOwnPropertyNames() //取得对象自身可枚举的属性名
//for in 对对象进行遍历,可以拿到自身以及原型链上的可枚举的属性
Object.freeze()//冻结一个对象,不可修改,不可删除。不可添加新的属性
Object.prototype.toString()// 返回数组[object,object/array/function等]
//判断是数组还是对象就是用的这个方法

</details>

js的字符串的常用的方法

<details> <summary>点击展开</summary>
str.concat()//拼接

str.includes()//判断字符串是否包含在另外一个字符串中
str.indexOf(),str.lastIndexOf()
str.split() //按特定的符号分割成字符串数组!
str.toLowerCase() //转换成小写的形式
str.toUpperCase() //转换成大写的形式
str.trim()//去空格

</details>

js的数组的常用的方法

<details> <summary>点击展开</summary>
arr.push(),arr.pop(), arr.shift(),arr.unshift(),arr.reverse(),arr.every(),arr.some()

arr.forEach()不会迭代空元素,arr.filter()实现过滤,arr.map()返回数组,arr.reduce()前后
arr.includes(),arr.indexOf(),arr.lastIndexOf() //索引正序,但是从后往前找
arr.findIndex() //找索引,
arr.find() //找满足条件的元素
arr.join()//默认以逗号隔开
arr.splice(3,1,'o','i')//从索引3开始,删除1个,添加两个字符串。
arr.flat() //数组降维 ,返回新数组
arr.flat(1)
arr.entries() //将数组返回一个对象,包含对象索引的键值对

  • push()将一个或多个元素添加到数组的末尾,并返回该数组的新长度
  • pop()方法从数组中删除最后一个元素,并返回该元素的值
    • substring(star,stop) ,star>stop时会交换两者;相等时返回空串;为负数时会将负数变为0,奇怪点较多。
  • substr(star,length),star为负数时,表示倒数位置;length<=0时,返回空串
  • slice(star,stop), 可以应用在数组和字符串;star>=stop时返回空串/数组;为负数时代表倒数位置
  • splice(start,length,items,只能用于数组,会改变原始数组;satr<0代表倒数,length<0返回空,length过大时截取全部。
</details>

JS中的深拷贝与浅拷贝

<details> <summary>点击展开</summary>
浅copy复制,创建一个新对象,接受原对象的值或者地址,改变新对象会引起原对象的变。

深拷贝完全是另一个对象,
Object.assign(newobj,obj)//ES6浅拷贝,遍历所有可枚举属性,然后赋值。把obj的可枚举属性拷贝给newobj,如果属性的值是复杂对象,则会指向同一地址,因此是浅拷贝

let newobj = {...obj} //浅拷贝 同上

Object.create(obj)//不能算是拷贝?该是继承,此方法使用指定的原型对象及其属性去创建一个新的对象

let newObj = JSON.parse(JSON.stringify(oldObj));//不完全的深拷贝

</details>

js垃圾回收机制

基本类型:栈空间,引用类型:堆空间;池:常量

回收方法/:标记清除法和引用计数法

js 原型,原型链以及特点

<details> <summary>点击展开</summary>
JavaScript 只有一种结构:对象。例子:

function Class(){
this.name='name';
}
class = new Class();//小写class为Class类的实例;Class为构造函数

每个实例对象(object)都有一个私有属性(称之为 proto )指向它的构造函数的原型对象(prototype)。

即class.proto === Class.prototype; //true

prototype中一般包含2个属性,一个是constructor,指向Class函数自身;一个是proto,指向更高一级的原型对象。可以在prototype中添加新的属性方法,实例上也能访问到。

原型对象也有一个自己的原型对象(proto),层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

ES5 中Object.getPrototypeOf() 方法来获取对象的原型。
当访问一个实例对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。

特点:
JavaScript 对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。

</details>

JavaScript 继承的方式

<details> <summary>点击展开</summary>
- 原型链继承,分清构造函数,原型,实例:1,每一个构造函数都有一个原型对象;2,原型对象包含一个指向构造函数的指针;3,实例中包含一个原型对象的指针。缺点,在包含有引用类型的数据时,会被所有的实例对象所共享,容易造成修改的混乱。
  • 使用构造函数的方式。

  • 组合继承。

  • 原型式继承。

  • 寄生式继承。

  • 寄生组合继承。

</details>

new 运算符的过程

<details> <summary>点击展开</summary>
1. 创建一个空对象{};
  1. 构造函数中的 this 指向该空对象
  2. 执行构造函数为这个空对象添加属性
  3. 判断构造函数有没有返回值,如果返回值是个对象,则返回这个对象;否则返回创建的对象
function Child1(){this.name='child1';}

var p = new Child1();

p//Child1 {name: "child1"} 一个Child1的实例

var p = Child1()  //不使用new

p  //undefined 因为Chilid1函数结果返回值为undefined
name  // child1方法中this指向window,所以window由了一个全局属性name
</details>

JS 作用域

<details> <summary>点击展开</summary>
ES5 只有全局作用域和函数作用域
  • 全局作用域:代码在程序的任何地方都能被访问,window 对象的内置属性都存在全局作用域

  • 函数作用域:在固定的代码片段才能被访问

  • 末定义直接赋值的变量自动声明为拥有全局作用域

    var num1 = 1;
    function fun1 (){
        num2 = 2;
    }
    num2;//报错
    fun1();
    num2;//2 需先调用函数后才能完成num2的定义和赋值
var num1 = 1;
function fun1 (num1){
    console.log(num1);
    num1 = 2;
    console.log(num1);
}
fun1();//undefined,2  未传递参数
num1;//1,

var num1 = 1;
function fun1 (){
    console.log(num1);num1 = 2;console.log(num1);
}
fun1();//1,2  访问全局变量
num1;//2  num1被改变

var num1 = 1;
function fun1 (){
    console.log(num1); var num1 = 2;console.log(num1);
}
fun1();//undefined,2  函数内作用域,尚未赋值
num1;//1 全局num1不改变

var num1 = 1;
function fun1 (){
    console.log(num1); let num1 = 2;console.log(num1);
}
fun1();//报错,暂时性死区,let不提升

ES6 有块级作用域

</details>

ES6 新特性

<details> <summary>点击展开</summary>
- let const 块级作用域
  • 模板字符串
  • 解构赋值
  • 箭头函数,函数参数默认值
  • 扩展运算符(...)
  • forEach for...of for...in
  • 数组方法map reduce includes
  • map和set
  • 模块化
  • promise proxy
  • async
  • class
</details>

let 和 var 的区别

  • let 是块级作用域,var 是函数作用域
  • var 存在变量提升,而 let 没有
  • let变量不能覆盖作用域中已定义的变量,const变量定义同时必须赋值
  • 在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区” (TDZ)

闭包的特性以及优缺点

<details> <summary>点击展开</summary>
闭包有三个特性:
  • 函数嵌套函数;
  • 内部函数使用外部函数的参数和变量;
  • 参数和变量不会被垃圾回收机制回收。

闭包的优点:

  • 希望一个变量长期保存内存中;
  • 避免全局变量污染;
  • 私有成员的存在。

闭包的缺点:

  • 常驻内存,增加内存使用量;
  • 使用不当造成内存泄漏。
</details>

箭头函数与普通函数的区别

<details> <summary>点击展开</summary>
1. 箭头函数是匿名函数,不能作为构造函数,不能使用new
  1. 箭头函数不能绑定arguments,取而代之用...解决

    let C = (...c) => {
      console.log(c);
    }
    C(3,82,32,11323);
    // [3, 82, 32, 11323]
  2. 箭头函数没有原型属性

  3. 箭头函数的this永远指向其上下文的this,没有办改变其指向,
    普通函数的this指向调用它的对象

</details>

ES6 中箭头函数 VS 普通函数的 this 指向

<details> <summary>点击展开</summary>
普通函数中 this
  1. 查看函数在哪被调用。
  2. 点左侧有没有对象?如果有,它就是 “this” 的引用。如果没有,继续第 3 步。
  3. 该函数是不是用 “call”、“apply” 或者 “bind” 调用的?如果是,它会显式地指明 “this” 的引用。如果不是,继续第 4 步。
  4. 该函数是不是用 “new” 调用的?如果是,“this” 指向的就是 JavaScript 解释器新创建的对象。如果不是,继续第 5 步。
  5. 是否在“严格模式”下?如果是,“this” 就是 undefined,如果不是,继续第 6 步。
  6. JavaScript 很奇怪,“this” 会指向 “window” 对象。

ES6 箭头函数中 this

  1. 默认指向定义它时,所处上下文的对象的 this 指向;
    偶尔没有上下文对象,this 就指向 window
// 例1
function hello() {
  console.log(this) // window
}
hello()

// 例2
function hello() {
  'use strict'
  console.log(this) // undefined
}
hello()

// 例3
const obj = {
  num: 10,
  hello: function () {
    console.log(this) // obj
    setTimeout(function () {
      console.log(this) // window
    })
  },
}
obj.hello()

// 例4
const obj = {
  num: 10,
  hello: function () {
    console.log(this) // obj
    setTimeout(() => {
      console.log(this) // obj
    })
  },
}
obj.hello()

// 例5
const obj = {
  radius: 10,
  diameter() {
    return this.radius * 2//diameter是普通函数,里面的this指向直接调用它的对象obj。
  },
  perimeter: () => 2 * Math.PI * this.radius,//这里上下文没有函数对象,就默认为window。
}
console.log(obj.diameter()) // 20
console.log(obj.perimeter()) // NaN
</details>

Event Loop 事件循环

<details> <summary>点击展开</summary>
微任务: promise.then(不是promise,promise里是立即执行)   MutationObserver  process.nextTick(Node.js 环境)

宏任务: script(整体代码) setTimeout setInterval I/O setImmediate(Node.js 环境) UI 交互事件
同一次事件循环中: 微任务永远在宏任务之前执行
事件循环的过程:

首先script脚本整体是一个大的异步任务,先执行script脚本。这个script脚本会包含同步任务和异步任务,同步任务会先在主线程上执行,异步任务(分为宏任务和微任务)会添加到任务队列中,任务队列分为宏任务队列和微任务队列。

当同步任务执行完毕后,此时的执行栈已经被清空,会去执行异步任务。此时会先从微任务队列中取一个微任务放到执行栈中执行,若有新的微任务或宏任务产生,添加到相应的任务队列中,循环往复,直至微任务队列清空。

紧接着会从宏任务队列取一个宏任务放到执行栈中执行,此时可能会产生新的微任务,将微任务放到微任务队列中,当这个宏任务执行完后会继续执行微任务队列,如果没有产生就继续执行下一个宏任务。循环往复,直至所有任务执行完毕。

</details>

HTML

HTML5 的新特性

<details> <summary>点击展开</summary>
1. 语义化标签:header、footer、section、nav、aside、article
  1. 增强型表单:input的多个type(color, date, datetime, email, month, number, range, search, tel, time, url, week)

  2. 新增表单元素:

    • datalist 定义选项列表。请与 input 元素配合使用该元素,来定义 input 可能的值。
    • keygen 规定用于表单的密钥对生成器字段。
    • output 定义不同类型的输出,比如脚本的输出。
  3. 新增表单属性:placehoder, required, min和max, step, height 和 width, autofocus, multiple

  4. 音频视频:

    • audio 定义音频内容
    • video 定义视频(video 或者 movie)
    • source 定义多媒体资源 video 和 audio
    • embed 定义嵌入的内容,比如插件。
    • track 为诸如 video 和 audio 元素之类的媒介规定外部文本轨道。
  5. canvas:

  6. 拖拽:drag

  7. 本地存储:localStorage、sessionStorage

  8. 新事件:onresize、ondrag、onscroll、onmousewheel、onerror、onplay、onpause

  9. WebSocket

  10. 移除元素
    acronym,applet,basefont ,big ,center,dir,font,frame,frameset,noframes,strike,tt

</details>

DOCTYPE的作用是什么

(1) 作用:告诉浏览器以什么样的模式来解析文档。DOCTYPE 不存在或格式不正确会导致文档以兼容模式呈现。
(2) 一般指定了之后会以标准模式来进行文档解析,否则就以兼容模式进行解析。

语义化标签的作用

  • 去掉或样式丢失的时候能让页面呈现清晰的结构
  • 方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页
  • 有利于SEO
  • 便于团队开发和维护,遵循W3C标准,可以减少差异化

事件模型以及三种事件绑定方法

<details> <summary>点击展开</summary>
现代浏览器事件模型二个过程:捕获;冒泡

事件捕获阶段。捕获指的是事件从html根元素向下传播到实际点击的目标元素(指在dom文档树中向下层),依次检查经过的节点是否绑定了该事件监听函数,如果有且该事件是设定在捕获阶段执行,便执行。

冒泡阶段:捕获阶段结束后,反向再检查一次,冒泡回根元素

现代浏览器中,默认情况下,所有事件处理程序都在冒泡阶段执行。

事件绑定方法:

  • 行内事件,过时了,不建议使用,缺点行为与结构不分离
<button onclick="alert('ok')">Press me</button> 
  • js中在元素节点上添加事件属性,缺点:重复定义后者会覆盖前者

     document.querySelector('button').onclick=alert('ok')
  • addEventListener(eventName,function,useCaptrue),常用,可取消

    const btn = document.querySelector('button');
    
    function bgChange() {
      const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
      document.body.style.backgroundColor = rndCol;
    }
    
    btn.addEventListener('click', bgChange);
    btn.removeEventListener('click', bgChange);

    addEventListener,其中第三个参数可以指定事件是否在捕获阶段执行。默认是false,在冒泡阶段执行。

</details>

事件代理/事件委托 以及 优缺点

<details> <summary>点击展开</summary>
> 事件委托本质上是利用了浏览器事件冒泡的机制。因为事件在冒泡过程中会上传到父节点,并且父节点可以通过事件对象获取到目标节点,因此可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方式称为事件代理。

使用事件代理我们可以不必要为每一个子元素都绑定一个监听事件,这样减少了内存上的消耗。并且使用事件代理我们还可以实现事件的动态绑定,比如说新增了一个子节点,我们并不需要单独地为它添加一个监听事件,它所发生的事件会交给父元素中的监听函数来处理。

事件委托的优点:

  1. 减少内存消耗,不必为大量元素绑定事件
  2. 为动态添加的元素绑定事件

事件委托的缺点:

  1. 部分事件如 focus、blur 等无冒泡机制,所以无法委托。
  2. 事件委托有对子元素的查找过程,委托层级过深,可能会有性能问题
  3. 频繁触发的事件如 mousemove、mouseout、mouseover等,不适合事件委托
</details>

如何阻止事件冒泡:e.stopPropagation()
如何阻止事件默认行为:e.preventDefault();

js 延迟加载的方式有哪些

<details> <summary>点击展开</summary>
> js 延迟加载,也就是等页面加载完成之后再加载 JavaScript 文件。 js 延迟加载有助于提高页面加载速度。

一般有以下几种方式:

  • defer 属性
  • async 属性
  • 动态创建 DOM 方式
  • 使用 setTimeout 延迟方法
  • 让 JS 最后加载
</details>

defer 和 async 的区别

<details> <summary>点击展开</summary>
- defer 属性表示延迟执行引入的 JavaScript,即这段 JavaScript 加载时 HTML 并未停止解析,这两个过程是并行的。当整个 document 解析完毕后再执行脚本文件,在 DOMContentLoaded 事件触发之前完成。

多个脚本按顺序执行。

  • async 属性表示异步执行引入的 JavaScript,与 defer 的区别在于,如果已经加载好,就会开始执行,也就是说它的执行仍然会阻塞文档的解析,只是它的加载过程不会阻塞。

    多个脚本的执行顺序无法保证。

</details>

broswer

OSI七层模型

<details> <summary>点击展开</summary>
物理层:通过媒介传输比特,确定机械及电气规范(比特Bit)

数据链路层:将比特组装成帧和点到点的传递(帧Frame)
网络层:负责数据包从源到宿的传递和网际互连(包PackeT)
传输层:提供端到端的可靠报文传递和错误恢复(段Segment)
会话层:建立、管理和终止会话(会话协议数据单元SPDU)
表示层:对数据进行翻译、加密和压缩(表示协议数据单元PPDU)
应用层:允许访问OSI环境的手段(应用协议数据单元APDU)

</details>

HTTP 状态码

<details> <summary>点击展开</summary>
1. 1XX 信息性状态码
  • 100 继续
  • 101 切换协议
  1. 2XX 成功状态码
    • 200 OK 成功处理了请求
    • 204 No Content 请求处理成功,但没有资源可返回
    • 206 Partial Content 请求资源的某一部分
  2. 3XX 重定向状态码
    • 301 永久性重定向,表示请求的资源已被分配了新的 URI
    • 302 临时性重定向,资源的 URL 已临时定位到其他位置
    • 303 告诉客户端应该用另一个 URL 获取资源
    • 304 表示客户端发送附带条件的请求时,服务器端允许请求访问资源,但未满足条件的情况
  3. 4XX 客户端错误状态码
    • 400 表示请求报文中存在语法错误
    • 401 未授权
    • 403 服务器拒绝了请求
    • 404 服务器无法找到所请求的 URL
  4. 5XX 服务器错误状态码
    • 500 内部服务器错误
    • 502 错误网关
    • 503 服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。
    • 504 响应超时
</details>

HTTP 与 HTTPS 的区别

<details> <summary>点击展开</summary>
1. HTTP 传输的数据都是未加密的,也就是明文的,HTTPS 协议是由 HTTP 和 SSL 协议构建的可进行加密传输和身份认证的网络协议,比 HTTP 协议的安全性更高。
  1. HTTPS 协议需要 CA 证书,费用较高;
  2. 使用不同的链接方式,端口也不同,一般而言,HTTP 协议的端口为 80,HTTPS 的端口为 443;
</details>

HTTP/2.0 特性:

  1. 首部压缩
  2. 多路复用
  3. 二进制分帧
  4. 服务端推送

TCP 和 UDP 之间的区别

<details> <summary>点击展开</summary>
TCP:传输控制协议 UDP:用户数据报协议
  1. TCP 是面向连接的,UDP 是无连接的即发送数据前不需要先建立链接;
  2. TCP 提供可靠的服务。也就是说,通过 TCP 连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP 尽最大努力交付,即不保证可靠交付。
  3. TCP 是面向字节流,UDP 面向报文;
  4. TCP 只能是 1 对 1 的,UDP 支持 1 对 1,1 对多;
  5. TCP 的首部较大为 20 字节,而 UDP 只有 8 字节;
</details>

TCP 的三次握手和四次挥手

<details> <summary>点击展开</summary>
三次握手:

第一次握手:客户端发送syn包(syn=1,seq=x)到服务器,并进入SYN_SENT状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
四次挥手
与建立连接的“三次握手”类似,断开一个TCP连接则需要“四次挥手”。
第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不 会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可 以接受数据。
第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。
第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。
第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。

</details>

HTTP 请求的方式

<details> <summary>点击展开</summary>
1. GET:请求指定的页面信息,并返回实体主体。
  1. HEAD:类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
  2. POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。
  3. PUT:从客户端向服务器传送的数据取代指定的文档的内容。
  4. DELETE:请求服务器删除指定的页面。
  5. CONNECT:HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
  6. OPTIONS:允许客户端查看服务器的性能。
  7. TRACE:回显服务器收到的请求,主要用于测试或诊断。
</details>

GET 和 POST 的区别

<details> <summary>点击展开</summary>
两者本质上都是 TCP 链接
  1. get 参数通过 url 传递,post 放在请求体 (request body) 中。
  2. get 请求在 url 中传递的参数是有长度限制的,而 post 没有。
  3. get 比 post 更不安全,因为参数直接暴露在 url 中,所以不能用来传递敏感信息。
  4. get 请求只能进行 url 编码,而 post 支持多种编码方式。
  5. get 请求参数会被完整保留在浏览历史记录里,而 post 中的参数不会被保留。
  6. get 产生一个 TCP 数据包;post 产生两个 TCP 数据包。
    对于 get 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200(返回数据);
    而对于 post,浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 ok(返回数据)。
</details>

浏览器输入 URL 之后发生了什么

<details> <summary>点击展开</summary>
> 参考链接:[在浏览器输入 URL 回车之后发生了什么(超详细版)](https://4ark.me/post/b6c7c0a2.html)
  1. DNS 解析
  2. TCP 连接
  3. 发送 HTTP 请求
  4. 服务器处理请求并返回 HTTP 报文
  5. 浏览器解析渲染页面
  6. 连接结束
</details>

localStorage,sessionStorage,cookie 的区别

<details> <summary>点击展开</summary>
共同点:都是保存在浏览器端,同源限制。

区别:
(1) cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递
sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存
(2) 存储大小限制也不同
cookie数据不能超过4k
sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大(实际上指键值与键共10M)
(3) 数据有效期不同
sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;
localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;
cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭;
(4) 作用域不同
sessionStorage不在不同的浏览器窗口***享,即使是同一个页面;
localStorage 在所有同源窗口中都是共享的;
cookie也是在所有同源窗口中都是共享的

</details>

浏览器的同源政策

<details> <summary>点击展开</summary>
一个域下的 js 脚本在未经允许的情况下,不能够访问另一个域的内容。这里的同源的指的是两个

域的协议、域名、端口号必须相同,否则则不属于同一个域。

同源政策主要限制了三个方面
第一当前域下的 js 脚本不能够访问其他域下的 cookie、localStorage 和 indexDB。
第二当前域下的 js 脚本不能够操作访问其他域下的 DOM。
第三当前域下 ajax 无法发送跨域请求。

</details>

跨域方法全

<details> <summary>点击展开</summary>
1、 通过jsonp跨域

2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域资源共享(CORS)
7、 nginx代理跨域
8、 nodejs中间件代理跨域
9、 WebSocket协议跨域

</details>

前端攻击

<details> <summary>点击展开</summary>

XSS攻击(cross-site script)

  1. XSS攻击形式:

    主要是通过html标签注入,篡改网页,插入恶意的脚本,前端可能没有经过严格的校验直接就进到数据库,数据库又通过前端程序又回显到浏览器

  2. 攻击的目的:

    攻击者可通过这种方式拿到用户的一些信息,例如cookie 获取敏感信息,甚至自己建网站,做一些非法的操作等;或者,拿到数据后以用户的身份进行勒索,发一下不好的信息等。

  3. 攻击防御

    方法1:cookie中设置 HttpOnly 属性

    方法2:首先前端要对用户输入的信息进行过滤,可以用正则,通过替换标签的方式进行转码或解码,例如<> 空格 & '' ""等替换成html编码

CSRF攻击(cross site request forgery,跨站请求伪造)

  1. CSRF攻击形式:

    CSRF也是一种网络攻击方式,通过伪装成站点用户进行攻击,

    csrf攻击形式:攻击者盗用用户的身份信息,并以用户的名义进行发送恶意的请求等,例如发邮件,盗取账号等非法手段

  1. 攻击防御:
  • 验证HTTP Referer字段
  • 在请求地址中添加token并验证
  • 在HTTP头中自定义属性并验证
</details>

浏览器缓存机制

<details> <summary>点击展开</summary>
浏览器缓存分为:强缓存和协商缓存

在浏览器第一次发起请求时,本地无缓存,向 web 服务器发送请求,服务器端响应请求,浏览器端缓存。在第一次请求时,服务器会将页面最后修改时间通过 Last-Modified 标识由服务器发送给客户端,客户端记录修改时间;服务器还会生成一个 Etag,并发送给客户端。

强缓存 Expires 和 Cache-Control 的使用

强缓存是利用 http 头中的 Expires 和 Cache-Control 两个字段来控制的,用来表示资源的缓存时间。强缓存中,普通刷新会忽略它,但不会清除它,需要强制刷新。浏览器强制刷新,请求会带上Cache-Control:no-cachePragma:no-cache

Expires

Expires 的值是一个绝对时间的 GMT 格式的时间字符串。比如 Expires 值是:expires:Fri, 14 Apr 2017 10:47:02 GMT。这个时间代表这这个资源的失效时间,只要发送请求时间是在 Expires 之前,那么本地缓存始终有效,则在缓存中读取数据。

缺点:
由于失效的时间是一个绝对时间,所以当服务器与客户端时间偏差较大时,误差很大,就会导致缓存混乱。

Cache-Control

Cache-Control 主要是利用该字段的 max-age 值来进行判断,它是一个相对时间,例如Cache-Control:max-age=3600,代表着资源的有效期是 3600 秒。

Cache-Control 与 Expires 可以在服务端配置同时启用,同时启用的时候 Cache-Control 优先级高。

协商缓存

协商缓存就是由服务器来确定缓存资源是否可用,所以客户端与服务器端要通过某种标识来进行通信,从而让服务器判断请求资源是否可以缓存访问。

Etag 和 If-None-Match

Etag/If-None-Match返回的是一个校验码。Etag可以保证每一个资源是唯一的,资源变化都会导致Etag变化。服务器根据浏览器发送的If-None-Match值来判断是否命中缓存。

Last-Modified不一样的是,当服务器返回 304 (Not Modified) 的响应时,由于Etag重新生成过,response header 中还会把这个Etag返回,即使这个Etag跟之前的没有变化。

Last-Modify / If-Modify-Since

浏览器第一次请求一个资源的时候,服务器返回的header中会加上Last-Modify,Last-Modify是一个时间标识该资源的最后修改时间,例如Last-Modify: Thu,31 Dec 2037 23:59:59 GMT。当浏览器再次请求该资源时,request的请求头中会包含If-Modify-Since,该值为缓存之前返回Last-Modify。服务器收到If-Modify-Since后,根据资源的最后修改时间判断是否命中缓存。如果命中缓存,则返回304,并且不会返回资源内容,并且不会返回Last-Modify。

</details>

CSS

CSS 盒模型

<details> <summary>点击展开</summary>
盒模型总共包括4个部分:
  • content:内容,容纳着元素的”真实“内容,例如文本,图像或是视频播放器
  • padding:内边距
  • border:边框
  • margin:外边距

两种盒模型的区别:

  • W3C盒模型 box-sizing: content-box (常用的是这种)

    W3C盒模型中,通过CSS样式设置的width的大小只是content的大小

  • IE盒模型 box-sizing: border-box

    IE盒模型中,通过CSS样式设置的width的大小是content + padding + border的和

</details>

设置一个元素的背景颜色,背景颜色会填充哪些区域

border + padding + content

margin/padding 设置百分比是相对谁的

margin/padding设置百分比都是相对于父盒子的宽度(width属性)来计算量的

CSS 选择器优先级

<details> <summary>点击展开</summary>
选择器按优先级先后排列:!important>内联>id>class = 属性 = 伪类 >标签 = 伪元素 > 通配符 \*
  • important 声明 1,0,0,0
  • ID 选择器 0,1,0,0
  • 类选择器 0,0,1,0
  • 伪类选择器 0,0,1,0
  • 属性选择器 0,0,1,0
  • 标签选择器 0,0,0,1
  • 伪元素选择器 0,0,0,1
  • 通配符选择器 0,0,0,0
</details>

伪类与伪元素的区别

<details> <summary>点击展开</summary>
一般在css3中使用单冒号来表示伪类,用双冒号来表示伪元素。

伪类一般匹配的是元素的一些特殊状态,如hover、link ,active等,而伪元素一般匹配的特殊的位置,比如after、before等。 伪元素默认行内元素,css中其必须有content属性,就算是content:""也必须写,否则无效。伪元素可以用于添加文字,或者小图标。
box::before {
content:'';
}

</details>

CSS 中哪些属性可以继承

<details> <summary>点击展开</summary>
每一个属性在定义中都给出了这个属性是否具有继承性,一个具有继承性的属性会在没有指定值的时候,会使用父元素的同属性的值来作为自己的值。

一般具有继承性的属性有,字体相关的属性,font-size和font-weight等。文本相关的属性,color和text-align等。
表格的一些布局属性、列表属性如list-style等。还有光标属性cursor、元素可见性visibility。

当一个属性不是继承属性的时候,通过将它的值设置为inherit来使它从父元素那获取同名的属性值来继承。

</details>

BFC的概念,

BFC 即 Block Formatting Context (块格式化上下文), 是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。

简单来说就是一个封闭的黑盒子,里面元素的布局不会影响外部。

float 的元素,display 是block

visibility: hidden, opacity: 0display: none

opacity: 0,该元素隐藏起来了,但不会改变页面布局,并且,如果该元素已经绑定一些事件,如 click 事件,那么点击该区域,也能触发点击事件的;

visibility: hidden,该元素隐藏起来了,不会改变页面布局,但是不会触发该元素已经绑定的事件;

display: none,把元素隐藏起来,并且会改变页面布局,可以理解成在页面中把该元素删除掉一样。

CSS 实现垂直居中

<details> <summary>点击展开</summary>
- 定位 + 负边距 元素绝对定位,top:50%,margin-top:-(高度/2)
  • 高度不确定用transform:translateY(-50%)

  • 父元素display:flex,align-items:center;

  • display: table-cell+vertical-align:middle;

  • div {

    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    }

</details>

margin塌陷问题

是在父级相对于浏览器进行定位时但子级没有相对于父级定位,子级相对于父级就像塌陷了一样,父子嵌套元素垂直方向的margin,父子元素是结合在一起的,他们两个会取其中最大的值

或者兄弟元素上下边距会重叠在一起,取较大值。

解决方法:触发bfc,绝对定位,float,overflow:hidden,display:inline-block

图片底部与父容器之间有一段空隙

原因:行内块级元素会和文字的基线对齐。

解决方法:
(1)给图片添加 vertical-align middle | top | bottom
(2) font-size:0

响应式设计

<details> <summary>点击展开</summary>
- 媒体查询:@media screen and (min-width:800px){}
  • 多列布局:column-count:3;flex布局;网格布局

  • 响应式图像使用了picture元素的srcset和sizes 特性提供多种资源

  • 使用百分号单位,或视口单位,或者vw加上绝对单位

  • <meta name="viewport" content="width=device-width,initial-scale=1">
</details>

常用单位px 像素 % 百分比 rem 和em vw和vh

<details> <summary>点击展开</summary>
  • em

    子元素字体大小的 em 是相对于父元素字体大小
    元素的width/height/padding/margin用em的话是相对于该元素的font-size
  • rem

    rem 是全部的长度都相对于根元素,根元素是谁?<html>元素。
    通常做法是给html元素设置一个字体大小,然后其他元素的长度单位就为rem。

vw(Viewport Width)、vh(Viewport Height)是基于视图窗口的单位,是css3的一部分,基于视图窗口的单位,除了vw、vh还有vmin、vmax。

  • vw:1vw 等于视口宽度的1%
  • vh:1vh 等于视口高度的1%
  • vmin: 选取 vw 和 vh 中最小的那个,即在手机竖屏时,1vmin=1vw
  • vmax:选取 vw 和 vh 中最大的那个 ,即在手机竖屏时,1vmax=1vh
</details>

不得不说牛客这个编辑器只能显示1w字了。
还有一些js高级问题,react框架内容就不放上来了。

想要完整原项目,评论区给地址。

求个收藏不过分吧!

inline-block、inline 和 block 的区别;可替换元素

<details> <summary>点击展开</summary>
Block 是块级元素,独占一行,能设置宽度,高度,margin/padding 水平垂直方向都有效。

Inline:设置 width 和 height 无效,margin 在竖直方向上无效,padding 在水平方向垂直方向都有效,前后无换行符

Inline-block:能设置宽度高度,margin/padding 水平垂直方向 都有效,前后无换行符

img 是可替换元素。

在 CSS 中,可替换元素(replaced element)的展现效果不是由 CSS 来控制的。一种外部对象,它们外观的渲染,是独立于 CSS 的。

例如 <iframe> 元素,可能具有自己的样式表,但它们不会继承父文档的样式。

典型的可替换元素有: iframe> video> embed> img>

</details>

全部评论

(8) 回帖
加载中...
话题 回帖