type
status
date
slug
tags
category
icon
password
😀
本篇文章主要是八股文面试题整理
 

对原型链的理解

  • 原型链是JavaScript中实现继承的一种机制,每个实例对象(Object)都有一个私有属性(__proto__)指向它的构造函数的原型对象(prototype),这个原型对象又有自己的原型对象,层层向上,直到一个对象的原型对象为null,这就是原型链。
  • 如果在当前对象中查找某个属性和方法时,当前对象不存在该属性和方法,就会沿着原型链向上查找,直到找到该属性或方法为止,或者查找到原型链的顶端。
  • 试图访问不存在的属性时会遍历整个原型链。

实现寄生组合继承

  • 定义一个父类,同时给它添加一些共有属性和方法;
  • 定义一个子类的构造函数,然后通过父类的call方法来继承父类的属性,并把子类构造函数中的this指向当前的子类。
  • 使用Object.create构建一个以父类原型为原型对象并赋值给子类的原型,这样子类就能够共享父类原型中的方法和属性。
  • 给子类原型添加一些方法和属性,这些方法和属性既不在父类原型中也不在子类构造函数中,这样子类就能够拥有自己的方法和属性。

instanceof原理

  • instanceof运算符用于判断构造函数的prototype属性是否出现在对象的原型链中的任何位置。

new操作符原理

  • 设置一个空对象,让对象的原型等于构造函数的prototype对象
  • 让函数的this指向这个对象,执行构造函数的代码(为这个新对象添加属性)
  • 判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,则返回这个引用类型的对象。

map和Object的区别

键的类型
  • Map中的键是任意数据类型,包括对象数组函数等
  • 对象中的键必须是字符串或Symbol类型
键值对的顺序
  • Map中的键值对是按照插入的顺序储存的
  • Object中的键值对则是没有顺序
大小的获取
  • Map提供了Size属性来获取其大小
  • Object则需要手动遍历键值对来获取大小
原型链
  • Map中的键值对不受原型链的影响
  • Object中的键值对可能会存在于原型链中
迭代器
  • Map提供了迭代器来遍历其键值对
  • 而Object则需要手动遍历键值对

this指向

  • 默认绑定(全局环境)
  • 隐士绑定(上下文对象)
  • 显示绑定(call,apply,bind)
  • new绑定(构造函数)
  • 特殊的this指向
    • 箭头函数
    • 数组方法
    • 立即执行函数
    • setTimeout和setInterval

let、const 和 var 的区别

  • 块级作用域
    • 块级作用域由{}包括,let和const具有块级作用域,var不存在块级作用域。块级作用域解决了ES5中的两个问题
      • 内层变量可能覆盖外层变量
      • 用来计数的循环变量泄露为全局变量
  • 变量提升
    • var存在变量提升,let和const不存在变量提升,即变量只能在声明之后使用,否则会报错。
  • 给全局添加属性
    • 浏览器的全局对象是window,Node的全局对象是global。var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会。
  • 重复声明
    • var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的变量。const和let不允许重复声明变量。
  • 暂时性死区
    • 在使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区。使用var声明的变量不存在暂时性死区。
  • 初始值设置
    • 在声明变量时,var和let可以不用设置初始值。而const声明变量必须设置初始值。
  • 指针指向
    • let和const都是ES6新增的用于创建变量的语法。let创建的变量是可以更改指针指向(可以重新赋值)。而const声明的变量不允许改变指针的指向。

闭包的作用和原理及使用场景

  • 闭包是指有权访问另一个函数作用域中变量的函数,优点是私有化数据,在私有化数据的基础上保持数据,缺点是不恰当的使用会造成内存泄漏,在不需要用到的时候及时将变量设置为null
  • 闭包可以将变量和函数私有化,从而可以避免命名冲突和环境污染。当函数执行完毕后,该函数内部定义的变量和函数依然存在与内存中,不会被内存回收,因此可以被其他函数继续访问和使用。这个机制成为闭包。
  • 闭包的原理是在内存中创建一个包含函数和变量的函数,当函数返回后,该环境仍然存在于内存中,因此可以被其他函数访问和使用,闭包中的变量和函数可以被多次调用和修改,因此可以实现许多高级功能。
  • 闭包一定可以造成内存泄漏吗
    • 不是所有闭包都会造成内存泄漏,只有在使用不当的情况下才会造成内存泄漏。
    • 当一个函数返回另一个内部函数,而该内部函数持有外部函数的变量时,就会形成闭包,如果该内部函数在外部函数执行完毕后仍然存在,那么他会一直持有外部函数的变量,导致这写变量无法被垃圾回收机制回收,从而造成内存泄漏。
  • 哪些方式可以防止造成内存泄漏
    • 避免创建不必要的闭包
    • 及时释放闭包
    • 使用模块模式
    • 使用箭头函数
    • 避免循环引用

JavaScript垃圾回收机制

  • V8是Google开发的一款高性能JavaScript引擎,它采用了先进的垃圾回收技术,主要包括两个垃圾回收器:新生代垃圾回收器和老生代垃圾回收器。
  • 新生代垃圾回收器
    • 新生代是指存活时间较短的对象,通常是通过JavaScript创建的临时对象。新生代垃圾回收器将新生代对象分为两个等大小的空间:From空间和To空间。当From空间被占满时,新生代垃圾回收器会将From空间中的存活对象复制到To空间中,同时对From空间进行垃圾回收。经过多轮复制和垃圾回收,仍然存活的对象会被移动到老生代。
  • 老生代垃圾回收器
    • 老生代是指存活时间较长的对象,通常是通过JavaScript创建的大型对象或全局对象,然后将未标记对象进行回收。标记压缩是指先标记所有存活对象,然后将存活对象向内存的一端移动,形成连续的内存空间,最后将另一端的内存空间进行回收。
  • 除了以上两个垃圾回收器,V8还采用了增量标记和并发标记等技术,以在不影响程序运行性能的前提下进行垃圾回收。增量标记是指将标记过程分为多个阶段,让垃圾回收与程序执行交替进行,以减少垃圾回收对程序性能的影响。并发标记是指在程序执行的同时进行垃圾回收,以进一步减少垃圾回收对程序性能的影响。

对作用域的理解

  • 在JavaScript中,作用域是指程序中定义变量的可见范围。
  • Javascript中作用域分为全局作用域和函数作用域。
    • 全局作用域是指代码中任何地方都可以访问到变量,他们在整个应用程序中都是可见的。
    • 函数作用域是指在函数内部定义的变量,它们只能在该函数内部被访问,函数外部无法访问这些变量。
    • js中还有一个特殊作用域,即块级作用域,在es6中,使用let、const关键字可以创建块级作用域,是指在代码块中定义的变量,它们只能在该代码块中被访问。
    • 在js中,变量的作用域是由他们在代码块中声明的位置所决定的。当程序执行时,js引擎会根据变量声明的位置来确定变量的作用域。通常,变量在声明位置上方的代码可以被访问到,下方的不能被访问到。

apply、call和bind的作用、区别、实现

  • call、apply、bind相同点
    • 都是改变this的指向,传入的第一个参数都是绑定this的指向,在非严格模式中,如果第一个参数是null或者undefined,会把全局对象(浏览器是window)作为this的值,要注意的是,在严格模式种,null就是null,undefined就是undefined。
  • call和apply唯一的区别是
    • call传入的是参数列表,apply传入的是数组,也可以是类数组。
  • bind和call、apply的区别
    • bind返回的是一个改变了this指向的函数,便于稍后调用,不像call和apply会立即调用;bind和call很像,传入的也是参数列表,但是可以多次传入,不需要像call,一次传入。
  • 手写call
    • 使用myCall方法调用函数时,将函数对象绑定到传入的对象中,使函数内的this关键字指向传入的对象。可以通过调用context.fn(…args)来执行函数,返回函数返回的值即可。在函数执行完毕后,需要将添加的属性从传入的对象上删除,以避免对对象造成影响。
    • 手写apply
      • myApply方法的实现基本上和myCall方法的实现类似。主要的区别在于,在执行函数时,需要根据是否传入了参数来决定是使用context.fn()还是context.fn(…args)来调用函数。
    • 手写bind
      • myBind方法返回了一个新的函数,可以在后续的调用中使用。在内部实现中,首先需要保存当前的函数对象fn,然会返回一个新的函数newFn。在调用newFn函数时,首先需要判断该函数是否是作为构造函数调用,如果是,则将this指向实例对象,并传递args和newArgs参数;否则,将fn函数作为普通函数来调用,将context作为this,并传递args和newArgs参数。需要注意的是,在调用fn函数时,需要将args和newArgs两个参数数组合并成一个新的数组传递给函数。

    连续多个bind,最后this指向的是什么?

    • 在JavaScript中,连续多次调用bind方法,最终函数的this上下文是由第一次调用bind方法的参数决定的。

    正向代理和反向代理的区别

    • 正向代理和反向代理都是代理服务器的使用方式,它们的主要区别在于代理服务器的位置和作用。
    • 正向代理
      • 正向代理(Forward Proxy)是代理服务器位于客户端和目标服务器之间的一种代理方式。在正向代理模式中,客户端无法直接访问目标服务器,而是通过正向代理服务器访问目标服务器。正向代理服务器可以帮助客户端隐藏真实IP地址,并提供一些安全性和隐私性保护,还可以帮助客户端访问受限制的内容。
      • 举个例子,如果公司内部有一个代理服务器,员工需要访问外网时,就需要通过该代理服务器访问。代理服务器会将员工的请求转发到外网服务器,并将响应结果返回给员工。在这个过程中,外网服务器无法直接获得员工的真实IP地址,因为所有的请求都是通过代理服务器转发的。
    • 反向代理(Reverse Proxy)
      • 反向代理(Reverse Proxy)是代理服务器位于目标服务器和客户端之间的一种代理方式。在反向代理模式中,客户端无法直接访问目标服务器,而是通过反向代理服务器访问目标服务器。反向代理服务器可以帮助目标服务器隐藏真实IP地址,并提供一些安全性和负载均衡的功能,还可以根据请求的内容进行路由,将请求转发到不同的后端服务器。
      • 举个例子,如果有一个网站使用了反向代理服务器,客户端访问该网站时,请求会首先发送到反向代理服务器,然后反向代理服务器会将请求转发到一个或多个后端服务器进行处理。在这个过程中,客户端无法直接获取后端服务器的真实IP地址,因为所有的请求都是通过反向代理服务器转发的。此外,反向代理服务器还可以根据请求的内容,将请求转发到不同的后端服务器,以实现负载均衡的功能。
    • 因此,正向代理和反向代理的主要区别在于代理服务器的位置和作用,正向代理是代理服务器位于客户端和目标服务器之间,反向代理是代理服务器位于目标服务器和客户端之间。

    箭头函数和普通函数有啥区别

    • 箭头函数比普通函数更简洁
    • 箭头函数没有自己的this
    • 箭头函数继承来的this指向永远不会改变
    • call()、apply()、bind()等方法不能改变箭头函数中this的指向
    • 箭头函数不能作为构造函数使用
    • 箭头函数没有自己的arguments
    • 箭头函数没有prototype
    • 箭头函数不能用作Generator函数,不能使用yeild关键字

    es6有哪些新特性

    • let和const
      • 块级作用域声明变量的关键字
    • 解构赋值
      • 可以方便的从数组或对象中提取值,赋给变量
    • 模板字符串
      • 使用反引号(``)和${}插值实现更方便的字符串拼接
    • 箭头函数
      • 更简洁的函数定义方式,可以解决this指向问题
    • 默认参数
      • 定义函数时,可以为参数提供默认值
    • Rest和Spread运算符
      • 可以将多个参数或数组/对象合并或拆分
    • 对象字面量的增强
      • 可以使用变量作为对象的键名,简化对象的定义。
    • 类和继承
      • 提供了更接近传统面向对象编程的写法,定义类和继承
    • Promise
      • 更好的异步编程方式,解决了回调地狱的问题。
    • Generators和Iterators
      • 实现更加灵活和可控的迭代器,更容易实现异步操作
    • 模块化
      • 引入了import和export关键字,实现更加模块化的代码组织方式。

    promise.all和promise.allsettled区别

    • Promise.all()和Promise.allSettled()都是用于并行处理多个Promise对象的方法,它们的区别在于对于Promise数组中的元素状态不同的处理方式不同。
    • Promise.all()方法将多个Promise对象包装成一个新的Promise对象,只有所有的promise对象都变为resolved状态时,该新的Promise对象才会被resolved,返回值是一个包含所有Promise对象结果的数组。如果其中任何一个Promise对象变为rejected状态,该新的Promise对象就会被rejected,返回值是一个被rejected的Promise对象的值。
    • Promise.allSettled()方法也将多个Promise对象包装成一个新的Promise对象,不同的是,该新的Promise对象只有所有的Promise对象都已经settled(即fulfilled或rejected)时,才会被resolved,返回值是一个包含所有Promise对象结果的对象数组。对象数组的每个元素包含了每个Promise对象的状态和结果值(如果已经settled)或原因(如果被rejected)。
    • 因此,Promise.all()和Promise.allSettled()的区别在于对于Promise数组中的元素状态不同的处理方式不同。Promise.all()会在任何一个Promise对象变为rejected状态时就被rejected,而Promise.allSettled()则会等所有Promise对象settled后才会resolved。

    substring和substr的区别

    • substr(start,length)
      • start,提取字符的位置。如果为负值,则被看作a.length+start,其中a.length为字符串的长度(例如,如果start为-3,则被看作a.length+(-3))。
      • length,可选可不选。选择则输入要提取的字符数,不选就是全部
    • substring(start,end)
      • start:为需要截取的第一个字符的索引,该索引位置的字符作为返回的字符串的首字母
      • end:可选,一个0到字符串长度之间的整数,以该数字为索引的字符不包含在截取的字符串内。

    symbol的作用和使用场景

    • Symbol是ES6中引入的新数据类型,它表示一个唯一的常量,通过Symbol函数来创建对应的数据类型,创建时可以添加变量描述,该变量描述在传入时会被强行转换成字符串进行存储:
      • 避免常量值重复
      • 避免对象属性覆盖

    JavaScript脚本异步加载如何实现,有什么区别

    • 动态创建Script标签
      • 可以通过在HTML页面上动态创建script标签来异步加载JavaScript脚本,例如:
      • 这里的async属性设置为true,表示该JavaScript脚本的加载和执行不会阻塞页面其他资源的加载和执行。
    • 使用defer属性
      • 另一种方式是使用defer属性,它也可以在异步加载JavaScript脚本的同时,不阻塞页面其他资源的加载和执行。与async属性不同的是,defer属性会保证JavaScript脚本按照页面中出现的顺序执行,即使它们的加载完成时间不同。
    • 两种方式的区别在于,async属性不保证JavaScript脚本按照它们在页面中出现的顺序执行,而defer属性保证JavaScript脚本按照它们在页面中出现的顺序执行,但是它们的执行时机不确定
    • 使用动态加载器
      • 还可以使用动态加载器库,如RequireJS、SystemJS和webpack等。这些库可以异步加载JavaScript模块,实现按需加载,提高应用的性能。区别在于,动态加载器通常会将多个JavaScript模块打包成一个文件,可以减少网络请求次数,但是会增加文件的体积。
    • 总的来说,通过动态创建script标签或者使用动态加载器库,可以实现JavaScript脚本的异步加载,提高应用程序的性能。而async属性和defer属性可以控制JavaScript脚本的执行顺序和执行时机。

    typeof和instanceof的区别

    • typeof会返回一个运算符的基本类型,instanceof返回的是布尔值。
    • instanceof可以准确判断引用数据类型,但是不能正确判断原始数据类型。
    • typeof虽然可以判断原始数据类型(null除外),但是无法判断引用数据类型(function除外)

    for…in和for…of的区别

    • for…of遍历获取的是对象的键值,for…in获取的是对象的键名;
    • for…in会遍历对象的整个原型链,性能非常差,不推荐使用,而for…of只遍历当前对象不会遍历原型链。
    • 对于数组的遍历,for…in会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for…of只返回数组的下标对应的属性值;
    • for…in循环主要是为了遍历对象而生,不适用于遍历数组;for…of循环可以用来遍历数组、类数组对象,字符串、Set、Map以及Generator对象。

    map和forEach可以通过break跳出吗

    • map和forEach无法使用return或break跳出循环,但是可以用抛出throw new Error(),通过try catch去捕获这个错误去终止循环。

    如何判断数组类型

    • 通过Object.prototype.toString.call()做判断
    • 通过原型链判断
    • 通过ES6的Array.isArray()做判断
    • 通过instanceof做判断
    • 通过Array.prototype.isPrototypeOf

    操作数组元素的方法

    • 改变原数组的方法
      • fill(),pop(),push(),shift(),splice(),unshift(),reverse(),sort()
    • 不改变原数组的方法
      • concat(),every(),filter(),find(),findIndex(),forEach(),indexOf(),join(),lastIndexOf(),map(),reduce(),reduceRight(),slice(),some()

    数组的sort排序算法的原理

    • 在V8引擎中,对sort方法提供了2种排序算法:插入排序及快排序。
    • 当数组长度小于等于10的时候,采用插入排序,大于10的时候,采用快排。

    如何实现深浅拷贝

    • 浅拷贝
      • 浅拷贝指的是将一个对象的属性值复制到另一个对象,如果有的属性的值为引用类型的话,那么会将这个引用的地址复制给对象,因此两个对象会有同一个引用类型的引用。浅拷贝可以使用Object.assign和展开运算符来实现。
      • 直接赋值
      • Object.assign()
      • 扩展运算符
      • 数组方法实现数组浅拷贝
        • Array.prototype.slice
        • Array.prototype.concat
      • 手写实现浅拷贝
      • 深拷贝
        • 深拷贝相对于浅拷贝而言,如果遇到属性值为引用类型的时候,它新建一个引用类型并将对应的值赋值给它,因此对象获得的一个新的引用类型而不是一个原有类型的引用。深拷贝对于一些对象可以使用JSON的两个函数来实现,但是由于JSON的对象格式比js的对象格式更加严格,所以如果属性值里边出现函数或者Symbol类型的值时,会转换失败。
        • Object.assign()
        • JSON两种类型
        • 函数库lodash的_cloneDeep方法
        • 手写实现深拷贝函数

      splice和slice会改变原数组吗?如何删除数组最后一个元素?

      • splice()会改变原数组,返回的是改变的内容;slice()不会改变原数组,会返回一个新的数组。
      • slice()方法可从已有的数组中返回选定的元素。返回一个新的数组,包含从start到end(不包含该元素)的数组元素。方法并不会修改数组,而是返回一个子数组。

      0.1+0.2为什么不等于0.3

      • 在js中,浮点数是以IEEE 754标准的二进制浮点数表示的,它采用二进制的形式来表示实数,而二进制无法精确的表示某些十进制的小数,因此它们在二进制下是无限循环小数,而浮点数只有64位的精度。
      • 因此,在执行0.1+0.2的计算时,由于无法精确表示这两小数,它们会被转换成最接近的可表示二进制数,然后再进行计算。
      • 可以使用toFixed()方法将结果四舍五入到指定位数。

      == 和 === 的区别

      • 使用双等号(==)进行相等判断时,如果两边的类型不一致,则会进行强制类型转换后进行比较。
      • 使用三等号(===)进行相等判断时,如果两边的类型不一致,不会做强制类型转换,直接返回false。

      解释 requestAnimationFrame/requestIdleCallback,分别有什么用?

      • requestAnimationFrame和requestIdIeCallback都是用于在浏览器中实现动画和其他视觉效果的API。
      • requestAnimationFrame是一个由浏览器提供的函数,可以将函数注册为在下一次浏览器重绘之前运行。这使得在动画中更新UI的性能更好,因为它允许浏览器在最佳实际进行渲染,避免在关键渲染路径上造成阻塞。这意味着,在优化资源加载和性能的同时,可以提供更快的感知速度。
      • 总之,requestAnimationFrame用于动画和其他实时更新UI的操作,而requestIdIeCall用于延迟加载和其他非关键渲染路径操作。

      对事件循环机制的理解

      • 事件循环(Event Loop)是JavaScript运行时的一个重要概念,它是一种异步编程模型,用于处理JavaScript程序中的异步事件。事件循环机制使得JavaScript可以执行非阻塞I/O操作,并处理用户交互事件等异步操作。
      • 事件循环的核心是一个事件队列(Event Queue),它维护着所有的异步事件和它们对应的回调函数。当一个异步事件完成时,它会被添加到事件队列中等待执行。事件循环不断地从事件队列中取出事件,并将它们对应的回调函数放到调用栈中执行,直到事件队列为空。
      • 事件循环机制分为两个主要阶段:宏任务(Macro Task)和微任务(Micro Task)。每个宏任务可以包含多个微任务。
      • 宏任务包括:
        • setTimeout和setInterval回调函数
        • DOM事件回调函数
        • Node.js I/O回调函数
        • setTmmediate(Node环境下)
      • 微任务包括:
        • Promise回调函数
        • process.nextTick(Node环境下)
        • Object.observe和MutationObserver回调函数
      • 在每个宏任务执行完毕后,会立即执行当前微任务队列中的所有微任务,直到任务队列为空。然后再从事件队列中取出下一个宏任务执行。这样依次循环,就构成了事件循环机制。
      • 需要注意的是,事件循环机制是单线程的,意味着JavaScript运行时只有一个主线程,所有任务都必须在主线程上执行。因此,长时间运行的项目会阻塞事件循环,导致应用程序无响应。为了避免这种情况,可以将长时间运行的任务切分成多个小任务,并使用setTimeout或setInterval将他们分散在多个宏任务中执行,从而让事件循环有足够的时间处理其他事件。

      介绍一下防抖和节流

      • 防抖(Debounce)
        • 防抖的原理是在事件被触发n秒后再执行回调函数,如果在这n秒内又触发了该事件,则重新开始计时。这样可以确保只有最后一次触发事件后的n秒后才会执行回调函数,从而减少了回调函数的执行次数,达到防抖的效果。
      • 节流(Throttle)
        • 节流的原理是在一段时间内只执行一次事件回调函数,如果在这段时间内又触发了该事件,则忽略该事件。这样可以确保在一段时间内只执行一次回调函数,从而减少了回调函数的执行次数,达到节流的效果。

      事件冒泡和捕获的区别?默认是冒泡还是捕获

      • 事件冒泡和事件捕获是两种不同的事件传播方式,默认是冒泡,它们的区别在于传播方向不同:
      • 事件冒泡(Bubbling)
        • 事件从最具体的元素(文档中嵌套层次最深的那个节点)开始向外传播,知道最不具体的节点(文档)。例如,当用户点击一个子元素时,该元素上的事件处理程序会先执行,然后该事件会向上传播,执行父元素上的事件处理程序,直到文档中的根元素为止。
      • 事件捕获(Capturing)
        • 事件从最不具体的元素开始向内传播,知道最具体的节点。例如,当用户点击一个子元素时,该事件会从文档中的根元素开始,先执行根元素上的事件处理程序,然后该事件会向下传播,执行子元素上的事件处理程序。
      • 默认情况下,事件处理程序采用的是事件冒泡方式。但是,可以通过在事件处理程序中调用event.stopPropagation()方法来阻止事件的冒泡或捕获的过程。需要注意的是,在某些浏览器中,事件捕获的支持不太友好,因此在实践中应该根据实际情况选择合适的事件传播方式。

      什么是事件代理?

      • 事件代理(Event Delegation)是一种常见的事件处理方式,它通过将事件处理程序添加到父元素上,来管理子元素的事件处理。具体来说,事件代理是将事件绑定到父元素上,当子元素触发事件时,该事件会冒泡到父元素,由父元素来处理该事件。这样做的好处是可以减少事件处理程序的数量,减轻页面的负担,提高代码的性能和可维护性。事件代理的应用场景包括:
      • 动态添加元素
        • 当需要动态添加子元素时,如果每个子元素都添加事件处理程序,会使得代码变得冗长且难以维护。此时,可以将事件处理程序添加到父元素上,由父元素来管理子元素的事件处理。
      • 性能优化
        • 当页面中有大量的元素需要添加事件处理程序时,使用事件代理可以减少事件处理程序的数量,从而提高页面的性能。
      • 代码简洁
        • 使用事件代理可以减少冗长的代码,使代码更加简洁易懂。需要注意的是,事件代理也有一些限制,例如不能处理一些需要特定事件目标的事件(如鼠标位置相关的事件),也不能处理一些需要事件捕获的事件。在实际使用时,应该根据场景选择合适的事件处理方式。

      mouseover和mouseenter的区别?

      • 触发条件不同
        • mouseover在鼠标指针进入元素或元素的子元素时会触发,即当鼠标指针从元素外部移入元素边界时触发;而mouseenter只在鼠标指针进入元素时触发,不会进入元素的子元素时触发。
      • 事件冒泡不同
        • mouseover会冒泡,即当鼠标指针从子元素移出到父元素时也会触发;而mouseenter不会冒泡,即只在进入元素时触发,不影响其他元素事件。
      • 因此,当需要在鼠标指针进入元素或其子元素时都触发事件时,应该使用mouseover;当需要只在鼠标指针进入元素时触发事件时,应该使用mouseenter。需要注意的是,由于mouseenter不会冒泡,因此可能会出现在子元素上触发mouseenter,但在父元素上并没有触发的情况,需要根据实际情况进行处理。

      浏览器缓存机制

      • 概述
        • 浏览器缓存机制是指浏览器对于已经请求过的资源进行缓存,以便下次再次请求资源时,可以直接从缓存中读取,避免重复的网络请求,从而提升网站的性能和用户体验。
      • 强缓存
        • 强缓存是指浏览器在第一次请求资源时,会将该资源缓存起来并在一定的时间内(通过设置响应头中的Cache-Control或Expires字段)不再向服务器请求该资源,直接从缓存中获取,这种方式的优点在于快速加载,节省了网络资源,但缺点是无法及时的更新资源,如果资源发生变化,浏览器可能无法获取到最新的版本。
      • 协商缓存
        • 协商缓存是指浏览器在第一次请求资源时,会将该资源的缓存标识(通过设置响应头中的ETag或Last-Modified)记录下来,并在下一次请求该资源时,带上这个标识发送给服务器,服务器根据这个标识判断资源是否发生了变化,如果没有发生变化,返回304状态码,告诉浏览器可以继续使用缓存中的资源,否则返回最新的资源,这种方式的优点是及时更新资源,缺点是需要向服务器发送请求,增加了网络开销。
      • 收敛
        • 在使用缓存策略时,需要根据实际情况选择合适的方式,并适当调整缓存时间,以达到最优的缓存效果。

      浏览器内核是什么?包含什么?常见的有哪些?

      • 浏览器内核是指浏览器用于解析和渲染网页的核心组件,包含了多个模块,如HTML解析器、CSS解析器、JavaScript引擎、渲染引擎等。
      • Trident内核
        • IE浏览器所采用的内核,目前已停止更新
      • Gecko内核
        • Mozilla Firefox浏览器所采用的内核,也被多个其他浏览器所采用
      • WebKit内核
        • Apple Safari浏览器所采用的内核,也被多个其他浏览器所采用
      • Blink内核
        • Google Chrome浏览器所采用的内核,基于WebKit内核的一个分支
      • EdgeHTML内核
        • Microsoft Edge浏览器曾采用的内核
      • 浏览器内核的不同,会对页面的渲染、性能、兼容性等方面产生影响。因此,在开发网页时,需要注意各种浏览器的内核特点和差异,以便达到更好的兼容性和性能表现。

      打开了两个标签页是进程还是线程?

      • 进程,每个标签页都会在浏览器中独立运行,有自己的渲染过程、JavaScript引擎。

      浏览器从输入网址到页面加载的整个过程

      • 解析URL
        • 首先会对URL进行解析,分析所需要使用的传输协议和请求的资源的路径。如果输入的URL中的协议或者主机名不合法,将会把地址栏中输入的内容传递给搜索引擎。如果没有问题,浏览器会检查URL中是否出现了非法字符,如果存在非法字符,则对非法字符进行转义后再进行下一程。
      • 缓存判断
        • 浏览器会判断所请求的资源是否在缓存里,如果请求的资源在缓存里并且没有失效,那么就直接使用,否则向服务器发起新的请求。
      • DNS解析
        • 下一步首先需要获取的是输入的URL中的域名的IP地址,首先会判断是否有该域名的IP地址的缓存,如果有则使用,如果没有则向本地DNS服务器发起请求。本地DNS服务器会首先检查是否存在缓存,如果没有就会先向根域名服务器发起请求,获得负责的顶级域名服务器的地址后,再向顶级域名服务器请求,然后获得负责的权威域名服务器的地址后,再向权威域名服务器发起请求,最终获得域名的IP地址后,本地DNS服务器再将这个IP地址返回给请求的用户。用户向本地DNS服务器发起请求属于递归请求,本地DNS服务器向各级域名服务器发起请求属于迭代请求。
      • 获取MAC地址
        • 当浏览器得到IP地址后,数据传输还需要知道目的主机MAC地址,因为应用层下发数据给传输层,TCP协议会指定源端口号和目的端口号,然后下发给网络层。网络层会将本机地址作为源地址,获取的IP地址作为目的地址。然后将下发给数据链路层,数据链路层的发送需求加入通信双方的MAC地址,本机的MAC地址作为源MAC地址,目的MAC地址需要分情况处理。通过将IP地址与本机的子网掩码相与,可以判断是否与请求主机在同一子网里,如果在同一子网里,可以使用ARP协议获取到目的主机的MAC地址,如果不在一个子网里,那么请求应该转发给网关,由它代为转发,此时同样可以通过ARP协议来获取网关的MAC地址,此时目的主机的MAC地址应该为网关的地址。
      • TCP三次握手
        • 下面是 TCP 建立连接的三次握手的过程,首先客户端向服务器发送一个 SYN 连接请求报文段和一个随机序号,服务端接收到请求后向服务器端发送一个 SYN ACK报文段,确认连接请求,并且也向客户端发送一个随机序号。客户端接收服务器的确认应答后,进入连接建立的状态,同时向服务器也发送一个ACK 确认报文段,服务器端接收到确认后,也进入连接建立状态,此时双方的连接就建立起来了。
      • HTTPS握手
        • 如果使用的是 HTTPS 协议,在通信前还存在 TLS 的一个四次握手的过程。首先由客户端向服务器端发送使用的协议的版本号、一个随机数和可以使用的加密方法。服务器端收到后,确认加密的方法,也向客户端发送一个随机数和自己的数字证书。客户端收到后,首先检查数字证书是否有效,如果有效,则再生成一个随机数,并使用证书中的公钥对随机数加密,然后发送给服务器端,并且还会提供一个前面所有内容的 hash 值供服务器端检验。服务器端接收后,使用自己的私钥对数据解密,同时向客户端发送一个前面所有内容的 hash 值供客户端检验。这个时候双方都有了三个随机数,按照之前所约定的加密方法,使用这三个随机数生成一把秘钥,以后双方通信前,就使用这个秘钥对数据进行加密后再传输。
      • 返回数据
        • 当页面请求发送到服务器端后,服务器端会返回一个 html 文件作为响应,浏览器接收到响应后,开始对 html 文件进行解析,开始页面的渲染过程。
      • 页面渲染
        • 浏览器首先会根据 html 文件构建 DOM 树,根据解析到的 css 文件构建 CSSOM 树,如果遇到 script 标签,则判端是否含有 defer 或者 async 属性,要不然 script 的加载和执行会造成页面的渲染的阻塞。当 DOM 树和 CSSOM 树建立好后,根据它们来构建渲染树。渲染树构建好后,会根据渲染树来进行布局。布局完成后,最后使用浏览器的 UI 接口对页面进行绘制。这个时候整个页面就显示出来了。
      • TCP四次握手
        • 最后一步是 TCP 断开连接的四次挥手过程。若客户端认为数据发送完成,则它需要向服务端发送连接释放请求。服务端收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明客户端到服务端的连接已经释放,不再接收客户端发的数据了。但是因为 TCP 连接是双向的,所以服务端仍旧可以发送数据给客户端。服务端如果此时还有没发完的数据会继续发送,完毕后会向客户端发送连接释放请求,然后服务端便进入 LAST-ACK 状态。客户端收到释放请求后,向服务端发送确认应答,此时客户端进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有服务端的重发请求的话,就进入 CLOSED 状态。当服务端收到确认应答后,也便进入 CLOSED 状态。

      前端模块化机制

      • 前端模块化是指将代码分割成不同的模块,以便于组织和管理。在前端开发中,常见的模块化机制有以下几种:
      • CommonJS
        • CommonJS是Node.js使用的模块化规范,可以在服务端使用。但是浏览器端需要使用打包工具如Webpack、Browserify等。通过module.exports导出模块,通过require引入模块。
      • AMD
        • AMD(AsyncChronous Module Definition)是一种异步模块定义规范,通过define定义模块,通过require异步加载模块。常见的实现有RequireJS等。
      • ES6模块化
        • ES6(ES2015)引入了原生的模块化机制,通过export导出模块,通过import引入模块。浏览器支持程度逐渐提高,可以直接在浏览器中使用,但需要打包工具对代码进行转换。
      • UMD
        • UMD(Universal Module Definition)是一种通用的模块定义规范,可以同时支持CommonJS、AMD和全局变量的形式,可以在浏览器和Node.js环境中使用。
      • 模块化机制可以让代码更加模块化、可维护和可复用,同时也可以提高代码的加载速度和性能。

      ES Module、CommonJS的区别

      • 语法不同
        • ES Module是在JavaScript语言层面上实现的模块化,使用import和export关键字来导入和导出模块。
        • CommonJS使用require()和module.exports来导入和到处模块
      • 加载方式不同
        • ES Module是异步加载的
        • CommonJS是同步加载的
      • 作用域不同
        • ES module是在模块级别上实现作用域的,每个模块都有自己的作用域,不同模块之间的变量互不影响。
        • CommonJS是在文件级别上实现作用域的,每个文件都有自己的作用域,不同文件之间的变量可以互相访问和修改。
      • 变量类型不同
        • ES Module导出的是一个值得引用
        • CommonJS导出的是值的拷贝

      cookie、localStorage、sessionStorage的区别

      • 储存大小
        • cookie存储量是4kb
        • 5MB
      • 数据存储时效
        • cookie可以设置过期时间
        • localStorage永久有效
        • sessionStorage会话窗口关闭
      • 与服务端通信
        • cookie会在HTTP中携带存储和传输数据
        • 只在客户端
      • 数据库存储范围
        • cookie可以被同源所有页面访问
        • 只能被创建窗口访问
      • 存储方式
        • cookie字符串、键值对
        • 键值对、JSON对象

      cookie里面都包含什么属性?

      • 名称(Name)
        • Cookie的名称。名称是区分大小写的
      • 值(value)
        • Cookie储存的值。值可以是任何字符串。如果值包含逗号、分号和空格等特殊字符,需要将其编码后在进行存储。
      • 域(Domain)
        • 可以访问该Cookie的域名,如果未指定域名,则默认为设置的Cookie的页面的域名。
      • 路径(Path)
        • 可以访问该Cookie的路径。如果未指定路径,则默认设置Cookie的页面路径。
      • 过期时间(Expires)
        • Cookie的过期时间。可以通过Expires属性或Max-Age属性指定,如果不指定过期时间,则默认为会话Cookie,即浏览器关闭时会自动删除Cookie。
      • 安全标志(Secure)
        • 指示浏览器是否只能通过安全连接(如HTTPS)发送Cookie
      • HttpOnly标志(HttpOnly)
        • 指示浏览器是否可以通过JavaScript访问Cookie,如果将HttpOnly标志设置为true,则脚本将无法访问该Cookie从而可以提高安全性。
      • 注意:在Cookie中存储的值是以字符串形式保存的,如果需要存储对象或数组等非字符串类型的数据,需要将其序列化为字符串,例如使用JSON.Stringify()方法。在读取Cookie时,需要将其反序列化,例如使用JSON.parse()方法。

      Cookie能跨域吗,如何设置

      • 在同一域名下,不用页面之间可以共享Cookie;而在不同域名下,默认情况下不能共享Cookie的,跨域设置Cookie需要满足以下条件:
        • 响应头设置Access-Control-Allow-Credentials:true:表示允许发送Cookie,需要与前端请求中的withCredentials字段配合使用。
        • 响应头设置Access-Control-Allow-Origin:请求域名,表示允许该域名下的请求访问资源,而不仅仅是在同一域名下的请求。
        • 前端请求中需要设置withCredentials:true:表示允许发送Cookie,需要与响应头中的Access-Control-Allow-Credentials配合使用。

      对CORS的理解

      • CORS(Cross-Origin Resource Sharing)是一种浏览器的安全策略,用于限制跨院资源的访问。跨源资源指的是在一个域名下的网页获取另一个域名下的资源,比如通过Ajax访问不同域名下的API接口。
      • 在默认情况下,浏览器限制了跨源请求的访问,就是为了保护用户的隐私和防止跨站攻击。但是,有时候我们需要跨域访问资源,比如在前端页面中通过Ajax请求后端的API接口,这时候就需要使用CORS技术来解决跨域问题。
      • CORS通过在服务器端设置响应头信息来控制跨域资源的访问权限。当浏览器发起跨域请求时,服务器可以在响应头中设置Access-Control-Allow-Origin字段来指定允许的来源域名或者使用通配符*来允许任意来源的访问。同时,还可以通过其他字段来控制请求的方法,头信息等。
      • 需要注意的是,使用CORS技术需要服务端的支持,而且浏览器对于CORS的实现也可能有所不同,开发者应该仔细阅读相关文档并进行调试,同时,CORS可能会带来一些风险,比如CSRF攻击等,需要开发者注意安全规范。

      如何检查内存泄漏?

      • 内存泄漏是指程序在运行时分配了内存空间,但在使用完毕后未能及时释放,导致内存空间不能再次被分配和使用的问题。长时间运行的应用程序,尤其是Web应用程序,容易出现内存泄漏问题,以下是一些检查内存泄漏的方法:
        • 使用浏览器的开发者工具
          • 现代浏览器都内置了开发者工具,可以用来检查页面中的内存使用情况,在Chrome中,可以使用Performance和Memory面板来监测页面的内存使用情况,定位可能的内存泄漏问题。
        • 手动观察程序的内存使用情况
          • 可以通过手动观察程序在运行时的内存使用情况来判断是否存在内存泄漏。在Chrome开发者工具的Memory中,可以手动进行内存快照,并进行比较,以确定是否内存泄漏。
        • 使用第三方工具
          • 还可以使用一些第三方工具来检查内存泄漏,比如Node.js中的heapdump和memwatch工具,以及Chrome的devtools-extension工具等。
        • 代码审查
          • 最后,可以通过代码审查来发现潜在的内存泄漏问题。比如,在程序中未能及时释放不再使用的对象,未关闭文件句柄等,都可能导致内存泄漏问题。因此,在编写代码时应该注意及时释放资源,避免内存泄漏的发生。

      HTTPS加密是怎么样的?

      • 超文本传输安全协议(Hypertext Transfer Protocal Secure,简称:HTTPS)是一种通过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,利用SSL/TLS来加密数据包。HTTPS的主要目的是提供对网站服务器的身份认证,保护交换数据的隐私与安全性。
      • SSL/TLS全程安全传输层协议(Transport Layer Security),是介于TCP和HTTP之间的一层安全协议,不影响原有的TCP协议和HTTP协议,所以使用HTTPS基本上不需要对HTTP页面进行太多的改造。
      • SSL/TLS的功能实现主要依赖三类基本算法:散列函数hash、对称加密、非对称加密。这三类算法的作用如下:
        • 基于散列函数验证信息的完整性
        • 对称加密算法采用协商的密钥对称加密
        • 非对称加密实现身份认证和密钥协商
      • 散列函数hash
        • 常见的散列函数有MD5、SHA1、SHA256。该函数的特点是单向不可逆,对输入数据非常敏感,输出的长度固定,任何数据的修改都会改变散列函数的结果,可以用于防止信息篡改并验证数据的完整性。
      • 对称加密
        • 对称加密是指加密和解密使用相同的密钥,通信双方需要通信前约定密钥,在报文传输过程中,发送方使用密钥对报文进行加密,接收方使用统一密钥对报文进行解密,常见的对称加密有AES、DES等。
      • 非对称加密
        • 非对称加密是指加密和解密使用不同的密钥,包括公钥和私钥,在通信前接收方生成一对密钥,其中一个是公钥,另一个是私钥,将公钥发送给发送方,发送方使用接收方的公钥对报文进行解密,常见的非对称加密有SPA、ECC等。
      • 综合上述算法特点,TLS/SSL的工作方式就是客户端使用非对称加密与服务端进行通信,实现身份的验证并协商对称加密使用的密钥。对称加密算法采用协商密钥对信息以及信息摘要进行加密通信,不同节点之间采用的对称加密不同,从而保证信息只能通信双方获取,这样就解决了两个方法各自存在的问题。

      HTML文档的生命周期有哪些?

      • 加载阶段(loading)
        • 浏览器根据URL请求HTML文档,并解析HTML文档的字节流。在解析过程中,如果遇到外部资源(如CSS、JS、图片等),则继续加载这些资源。
      • 解析阶段(parsing)
        • 浏览器对HTML文档进行解析,生成DOM树,CSSOM树和渲染树。
      • 渲染阶段(rendering)
        • 浏览器根据渲染树和视口信息将页面渲染出来
      • 交互阶段(interaction)
        • 用户可以对页面进行交互,如点击、滚动、输入等操作。
      • 卸载阶段(unloading)
        • 用户关闭当前页面或者跳转到其他页面时,浏览器会销毁当前页面的所有资源,包括DOM、CSSOM、JS对象等。

      如何解决跨域问题

      • 概述
        • 在前端开发中,跨域问题是一个比较常见的问题,但浏览器在访问一个网站时,如果该网站所在的域名、协议、端口号不一致,就会跨域。
      • JSONP
        • 通过动态创建script标签,像跨域的发送请求,接口返回一个JSONP格式的回调函数,并把数据作为参数传递给该函数,从而实现跨域请求数据的一种方式。
      • CORS
        • 是一种跨域资源共享的机制,它允许浏览器像跨域服务器发送请求,从而解决了AJAX不能跨域请求的问题,在服务端配置一些响应头信息,就可以支持cors
      • 代理
        • 在同源策略的限制下,我们可以在同一域名下设置一个代理服务器,将要请求的地址发送到该代理服务器,再由代理服务器去请求接口数据,然后将请求结果返回给前端页面。
      • postMessage
        • HTML5中引入的跨文档消息传递机制,postMessage可以实现在不同的窗口之间,甚至不同的域之间进行通信,从而实现跨域通信。
      • WebSocket
        • WebSocket是HTML5新增的协议,它可以在浏览器和服务器之间建立一条持久化的链接,可以实现双向通信,并且不受同源策略的限制,因此可以用来解决跨域问题。

      Content-Type值有哪些

      • application/x-www-form-urlencoded
        • 最常见的POST提交数据的方式。浏览器的原生form表单,如果不设置enctype属性,那么最终就会以application/x-www-form-urlencoded方式提交数据
      • multipart/form-data
        • 表单数据格式,通常用于上传文件
      • application/json
        • JSON格式
      • text/xml
        • HTML格式

      常见状态码的含义?

      • 1xx Informational
        • 1xx状态码是在HTTP/1.1中引入的,它们是信息性的状态码,是临时的,表示请求已被接受,需要继续处理,这些状态码并没有提供太多有用的信息,我们可能永远看不到1xx相关的状态码。
      • 2xx Success
        • 2xx状态码表示客户端的请求被成功接收、理解和接受
        • 200 OK
          • 表示客户端发来的请求被服务器端正常处理了,从SEO的角度来看,200 OK状态码是功能页面的完美状态码,所有链接页面都在正常工作,200表示搜索引擎爬虫可以成功爬取该页面并将其放入其搜索引擎中。
        • 201 Created
          • 服务器完成了浏览器的请求,因此创建了一个或多个新资源
        • 202 Accepted
          • 服务器已接受浏览器的请求,但仍在处理中,该请求最终可能会也可能不会进行响应。
        • 203 Non-authoritative Information
          • 使用代理时可能会出现此状态码,这意味着代理服务器从源服务器收到了200状态码,但是将响应传递给浏览器之前已经对其进行了修改。
        • 204 No Content
          • 该状态码表示客户端发送的请求已经在服务器端正常处理过了,但是没有返回的内容,响应报文中不包含实体的主体部分。一般在只需要从客户端往服务端发送消息,而服务端不需要往客户端发送内容时使用。
        • 205 Reset Content
          • 服务端成功处理了请求,且没有返回任何内容,但是与204响应不同,返回此状态码的响应要求请求者重置文档视图,该响应主要是被用于接受用户输入后,立即重置表单,以便用户能够轻松地开始另一次输入。
        • 206 Partial Content
          • 该状态码表示客户端进行了范围请求,而服务端执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。
        • 226 IM Used
          • 服务器已成功处理浏览器的GET方法,以检索已缓存资源的更新版本,通常,当请求的资源有一个或多个轻微修改时返回响应。
      • 3xx Redirection
        • 3xx 响应结果表面浏览器需要执行某些特殊的处理以正确处理请求
        • 300 Multiple Choices
          • 有时,服务器可能会影响多种可能的资源来满足浏览器的请求。300状态码意味着浏览器现在需要在它们之间进行选择,当有多个可用的文件类型扩展名时,可能会发生这种情况。
        • 301 Moved Permanently
          • 永久重定向,已为目标资源分配一个新的永久URL。新的URL会在HTTP响应头的Location首部字段指定。若用户已经把原来的URL保存为书签,此时会按照Location中的新URL重新保存该书签,同时,搜索引擎在爬取新内容的同时也将旧的网址替换为重定向之后的网址。
        • 302 Found
          • 临时重定向,请求的资源被分配到了新的URL,希望用户(本次)能使用新的URL访问资源,和301 Moved Permanently状态码相似,但是302代表的资源不是被永久重定向,只是临时性质的,也就是说已移动的资源对应的URL将来还有可能发生变化。
        • 303 See Other
          • 由于请求对应的资源存在另一个URL,应使用GET方法定向获取请求的资源。
            • 303 状态码和 302 Found 状态码有着相似的功能,但是 303 状态码明确表示客户端应当采用 GET 方法获取资源。303 状态码通常作为 PUT 或 POST 操作的返回结果,它表示重定向链接指向的不是新上传的资源,而是另外一个页面,比如消息确认页面或上传进度页面。而请求重定向页面的方法要总是使用 GET。
        • 304 Not Modified
          • 浏览器缓存相关。该状态码表示客户端发送附带条件的请求时,服务器端允许请求访问资源,但未满足条件的情况。304 状态码返回时,不包含任何响应的主体部分。304 虽然被划分在 3XX 类别中,但是和重定向没有关系。
        • 307 Temporary Redirect
          • 临时重定向。该状态码与 302 Found 有着相同含义,尽管 302 标准禁止 POST 变成 GET,但是实际使用时还是用了。307 会遵守浏览器标准,不会从 POST 变成 GET。但是对于处理请求的行为时,不同浏览器还是会出现不同的情况。规范要求浏览器继续向 Location 的地址 POST 内容。规范要求浏览器继续向 Location 的地址 POST 内容。
        • 308 Permanent Redirect
          • 永久重定向,当前及未来的请求重定向到了新的 URL。
      • 4xx Client Error
        • 4xx 表示客户端有错误
        • 400 Bad Request
          • 请求报文中存在语法错误。当错误发生时,需修改请求的内容后再次发送请求。
        • 401 Unauthorized
          • 发送的请求需要有通过 HTTP 认证(BASIC 认证、DIGEST 认证)的认证信息。若之前已进行过一次请求,则表示用户认证失败。返回含有 401 的响应必须包含一个适用于被请求资源的 WWW-Authenticate 首部用以质询(challenge)用户信息。当浏览器初次接收到 401 响应,会弹出认证用的对话窗口。
        • 402 Payment Required
          • 为数字支付系统保留的。不过,它并没有被广泛使用。
        • 403 Forbidden
          • 客户端请求已被拒绝,因为客户端无权访问内容。与 401 不同,服务器知道客户端的身份,但由于他们无权查看内容,因此服务器拒绝提供正确的响应。
        • 404 Not Found
          • 服务器上无法找到请求的资源,但将来可能可用。除此之外,也可以在服务器端拒绝请求且不想说明理由时使用。
        • 405 Method Not Allowed
          • 服务器识别到浏览器使用的 HTTP 请求方法,但需要使用不同的方法才能提供所需的资源。服务器应该总是允许客户端使用 GET 和 HEAD 方法进行访问。
      • 5xx Server Error
        • 5XX 的响应结果表明服务器本身发生错误。
        • 500 Internal Server Error
          • 服务器端在执行请求时发生了错误。也有可能是应用存在 bug 或某些临时的故障。
        • 501 Not Implemented
          • 请求无法处理,因为服务器不支持。
        • 502 Bad Gateway
          • 该扮演网关或代理角色的服务器从上游服务器中接收到的响应是无效的。注意,502 错误通常不是客户端能够修复的,而是需要由途经的服务器或者代理服务器对其进行修复
        • 503 Service Unavailable
          • 服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。

      GET和POST请求的区别

      • 请求参数位置
        • GET请求的参数会附加在url的后面
        • POST请求的参数会放在请求体中
      • 请求参数长度
        • GET请求的参数长度有限制,通常为url的最大长度(2KB)
        • POST请求的参数长度没有限制,可以传输较大的数据
      • 安全性
        • GET请求的参数会暴露在url中,因此不适合传输敏感信息
        • POST请求的参数会放在请求体中,相对安全。
      • 缓存
        • GET请求会被浏览器缓存下来,因此可以重复使用
        • POST请求不会被缓存
      • 幂等性
        • GET请求是幂等的,无论调用多少次,结果都相同,不会产生副作用
        • POST请求不是幂等的,调用多次可能会产生不同的结果,产生副作用

      http2.0新增了哪些属性

      • HTTP/2.0 是 HTTP 协议的第二个正式版本,相较于 HTTP/1.x,它引入了一些新的特性和属性,包括:
      • 二进制传输
        • HTTP/2.0把请求和响应都分割成小的二进制帧,通过多路复用进行传输,提高了传输效率
      • 头部压缩
        • HTTP/2.0采用新的HPACK压缩算法,对头部信息进行压缩,减少了数据传输量,增加了性能
      • 服务器推送
        • HTTP/2.0允许服务器在客户端请求之前主动向客户端推送资源,提高了性能和用户体验
      • 流量控制
        • HTTP/2.0引入了流量控制机制,允许客户端和服务端控制数据流的速率,避免了网络拥塞
      • 多路复用
        • HTTP/2.0支持多路复用,允许多个请求和相应在同一个TCP连接上进行传输,提高了传输效率
      • 总的来说,HTTP/2.0主要是为了提高性能和效率,减少了网络传输的开销

      XSS和CSRF是什么?如何防御?

      • 什么事xss攻击
        • 概述
          • xss攻击(跨站脚本攻击)是一种常见的web安全漏洞,攻击者通过向web应用程序注入恶意脚本,使得用户在访问页面时执行这些脚本,从而实现攻击目的,xss攻击可以分为存储型攻击类型、反射型攻击类型、DOM型攻击类型。
        • 存储型攻击
          • 存储型xss攻击是指攻击者将恶意脚本存储在web应用程序的服务端,当用户发起请求访问这些页面时,服务端会从数据库中取出带有恶意脚本的内容并返回给客户端浏览器,用户在浏览器端执行这些恶意脚本,从而造成安全问题。
        • 反射型攻击
          • 反射性xss攻击是指攻击者将恶意脚本作为参数传递给web应用程序,wen应用程序将恶意脚本反射回浏览器端,用户在浏览器端执行这些恶意脚本,从而造成安全问题。
        • DOM型攻击
          • DOM型xss攻击是指攻击者利用web应用程序中的漏洞,将恶意脚本插入到页面中,当用户访问页面时,浏览器解析脚本并执行,从而实现攻击目的。
        • 防范xss攻击
          • 输入内容进行过滤
          • 输出内容进行编码
          • 使用安全DOM
      • 什么是csrf攻击
        • 概述
          • csrf(跨站请求伪造)攻击是一种常见的web攻击方式,指攻击者通过设置陷阱,强制对已完成认证的用户在不知情的情况下执行某些操作,比如在用户已经登录了银行网站后,攻击者诱骗用户点击一个链接或图片,使得用户在没有察觉的情况下进行了银行转账或修改密码等操作。
        • 攻击流程
            1. 用户在已登录的银行网站上浏览页面,因此该网站会为该用户设置cookie保存用户的信息
            1. 攻击者诱骗用户点击一个链接或打开一个图片等,这个链接或图片会发起一个对银行网站的请求,但是这个请求并不是用户的意愿,而是攻击者构造的。
            1. 银行网站接收到这个请求,以为是用户发出的请求,由于已经保存了用户的认证信息,就会执行该请求对应的操作,比如转账。
        • 预防csrf攻击
            1. 使用验证码,确保请求是由人类发出的而不是自动脚本发出的。
            1. 检查refer头,确保请求是从正确的页面发出的,而不是从其他页面发出的。
            1. 在请求中添加一个token,这个token会在服务器端生成,并在页面上放置一个隐藏字段,每次请求都需要带上这个token才能完成。

      回流和重绘是什么,有什么却别?

      • 回流
        • 当渲染树中部分或者全部元素的尺寸、结构或者属性发生变化时,浏览器会重新渲染部分或者全部文档的过程就称为回流。
        • 下面这些操作或导致回流:
          • 页面的首次渲染
          • 浏览器的窗口大小发生变化
          • 元素的内容发生变化
          • 元素的尺寸大小或者位置发生变化
          • 元素的字体大小发生变化
          • 激活css伪类
          • 查询某些属性或者调用某些方法
          • 添加或者删除可见的DOM元素
      • 重绘
        • 当页面中某些元素的样式发生变化,但是不会影响其在文档流中的位置时,浏览器就会对元素进行重新绘制,这个过程就是重绘。
        • 下面这些操作会导致重绘:
          • color、background相关属性:background-color、background-image等
          • outline相关属性:outline-color、outline-width、text-decoration
          • border-radius、visibility、box-shadow
      • 如何避免回流和重绘
        • 操作DOM时,尽量在低层级的DOM节点进行操作
        • 不要使用table布局,一个小的改动可能会使整个table进行重新布局
        • 使用css的表达式
        • 不要频繁操作元素的样式,对于静态页面,可以修改类名,而不是样式
        • 使用absolute或者fixed,使元素脱离文档流,这样他们发生变化就不会影响其他元素
        • 避免频繁操作DOM,可以创建一个文档片段documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中
        • 将元素先设置display:none,操作结束后再把它显示出来,因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。
        • 将DOM的多个读操作(或者写操作)放在一起,而不是读写操作穿插着写,这得益于浏览器的渲染队列机制。

      对盒子模型的理解

      • 标准盒模型
        • box-sizing:content-box
        • 标准盒模型的width和height属性的范围包含了content
      • IE盒模型
        • box-sizing:border-box
        • IE盒模型的width和height属性的范围包含了border、padding、content

      CSS选择器有哪些

      • 元素选择器(Element Selector)
        • 根据元素的标签名匹配元素,例如p、h1、div等
      • ID选择器(ID Selector)
        • 根据元素的id属性值匹配元素,id值是唯一的,每个元素只有一个id,例如#header
      • 类选择器(Class Selector)
        • 根据元素的class属性值匹配元素,class值可以重复使用,一个元素可以有多个class,例如 .nav、.box
      • 属性选择器(Attribute Selector)
        • 根据元素的属性值匹配元素,例如[type=”text”]、[href^=”https://”]等
      • 伪类选择器(Pseudo-class Selector)
        • 根据元素的状态匹配元素,例如 :hover、:active、:first-child等
      • 伪元素选择器(Pseudo-element Selector)
        • 用来匹配元素的某些部分,例如::before、::after
      • 后代选择器(Descendant Selector)
        • 选择某个元素下的所有后代元素,例如#header p
      • 子元素选择器(Child Selector)
        • 选择某个元素下的直接元素,例如 ul>li
      • 相邻兄弟选择器(Adjacent Sibling Selector)
        • 选择某个元素后面的相邻兄弟元素,例如h1+p
      • 通用选择器(Universal Selector)
        • 匹配所有元素,例如 *

      伪类和伪元素的区别

      • 伪元素
        • 在内容元素的前后插入额外的元素或样式,但是这些元素实际上并不在文档中生成,他们只在外部显示可见,但不会在文档的源代码中找到它们,因此,称为”伪”元素
      • 伪类
        • 将特殊的效果添加到特定选择器上,它是已有元素上添加类型的,不会添加新的元素。

      如何计算css优先级

      • 对于选择器的优先级
        • 标签选择器、伪元素选择器:1;
        • 类选择器、伪类选择器、属性选择器:10;
        • id选择器:100;
        • 内联样式:1000;
      • !important声明的样式的优先级最高;
      • 如果优先级相同,则最后出现的样式生效;
      • 继承得到的样式的优先级最低;
      • 样式表的来源不同时,优先级顺序为:内联样式>内部样式>外部样式>浏览器用户自定义样式>浏览器默认样式

      预处理器(scss、less)与css的区别

      • 预处理器则是在css基础上进行扩展,提供了更强大、更灵活的样式编写方式,以下是CSS与预处理器的区别:
      • 语法不同
        • CSS使用大括号和分括号来组织样式,而预处理器使用类似编程语言的语法来组织样式,如使用变量、函数、循环等。
      • 可以使用变量
        • 在CSS中不支持使用变量,而预处理器可以使用变量来存储和复用样式值,提高了代码的复用性和可维护性。
      • 可以使用函数和混合(Mixin)
        • 预处理器可以定义函数和混合,让样式的编写更加灵活。例如可以定义一个用于生成渐变背景的函数,或者定义一个用于生成常用样式的混合。
      • 支持嵌套
        • 预处理器支持嵌套选择器,可以更加清晰地表达样式之间的关系,减少了代码的层级。
      • 自动添加前缀
        • 预处理器可以自动添加浏览器前缀,减少了样式编写的繁琐性。
      • 需要编译
        • 预处理器需要通过编译将预处理器的语法转换为标准的CSS代码,才能在浏览器中使用。
      • 总之,预处理器相对于CSS更加灵活、可维护、可以提高样式编写的效率和质量。但是使用预处理器需要学习和掌握额外的语法和工具,增加了学习和使用成本。

      position有哪些值,作用分别是什么?

      • static
        • 默认值,元素按照正常文档流的方式进行排列,不会受到top、bottom、left、right等属性的影响。
      • relative
        • 元素相对于其正常位置进行定位,不会影响其他元素的位置,可以通过top、bottom、left、right属性来指定元素的偏移量
      • absolute
        • 元素相对于其最近的已定位祖先元素(position属性不为static的元素)进行定位,没有已定位祖先元素则相对于文档进行定位,可以通过top、bottom、left、right属性来指定元素的偏移量。
      • fixed
        • 元素相对于视口进行定位,即无论页面滚动与否,元素始终在同一位置,可以通过top、bottom、left、right属性来指定元素偏移量。
      • sticky
        • 元素根据用户的滚动位置进行定位,当元素滚动到某个阈值时,元素将变为fixed定位,例如position:sticky;top:0;会使元素在离开视口前固定在顶部。

      flex布局的好处?

      • 简单易用
        • 相比其他传统的布局方式,Flex布局更为简单,易于理解和使用,可以通过少量的css代码就能实现复杂的布局效果。
      • 适应性强
        • Flex布局非常适合响应式设计,可以实现页面在不同尺寸的屏幕上自适应,避免了在不同设备上出现布局混乱的问题。
      • 省去float和clear
        • Flex布局可以轻松的实现水平和垂直居中,省去了使用float和clear等传统布局方式的繁琐操作。
      • 支持多种方向
        • Flex布局支持多种方向,包括水平方向、垂直方向和混合方向,可以非常方便地实现各种布局效果。
      • 支持对齐和分布
        • flex布局支持对其和分布,包括项目对齐、内容对齐、空间分布等,可以轻松实现各种各样的布局方案。
      • 总之,CSS Flex布局是一种非常强大、灵活和易于使用的布局方式,可以提高开发效率,减少代码量,同时还能够实现响应式设计和自适应布局等功能,非常适合现代web开发。

      Flex:1是什么意思

      • 表示子元素的伸缩比例为1,即子元素可以根据剩余空间进行分配,并且在分配时所有子元素的扩展比例相同,这意味着所有子元素都会平均分配容器的剩余空间,从而实现弹性布局。
      • flex-grow
        • 用于设置弹性盒子容器的子元素在空间分配时的扩展比例,默认值为0,即不会分配剩余空间;
      • flex-shrink
        • 用于设置弹性盒子容器的子元素在空间不足时的收缩比例,默认值为1,即缩小的比例与容器空间不足的空间大小成正比;
      • flex-basis
        • 用于设置弹性盒子容器的子元素在分配多余空间前的初始大小,默认值为auto,即由子元素的内容决定。

      CSS实现三角形

      • border
        • linear-gradient
          • clip-path

            如何在浏览器可视区域画一个最大的正方形

            • 获取浏览器窗口的宽度和高度 const width = window.innerWidth; const height = window.innerHeight;
            • 取宽度和高度的最小值,即为正方形的边长 const size = Math.min(width, height);
            • 获取 <div> 元素 const square = document.querySelector('.square');
            • 设置 <div> 元素为正方形 square.style.width = ${size}px; square.style.height = ${size}px;

            CSS3 有哪些新特性?

            • 边框和背景
              • CSS3 增加了更多的边框和背景样式,包括圆角边框(border-radius)、阴影(box-shadow)、渐变背景(background-image)、多重背景(background-image)等。
            • 文字和字体
              • CSS3 支持更多的字体和文字效果,包括自定义字体(@font-face)、文本阴影(text-shadow)、文本渐变(background-clip)等。
            • 选择器
              • CSS3 引入了更多的选择器,例如通用选择器(*)、属性选择器([attr])、子元素选择器(>)、相邻兄弟选择器(+)等,增强了 CSS 的选择能力。
            • 盒模型
              • CSS3 引入了更多的盒模型特性,例如盒阴影(box-shadow)、盒模糊(filter: blur())等,可以更加灵活地控制元素的样式。
            • 变形和动画
              • CSS3 支持更多的变形和动画效果,例如旋转(transform:rotate())、缩放(transform:scale())、位移(transform:translate())、动画(@keyframes)等,可以为页面增加更多的交互和动态效果。
            • 媒体查询
              • CSS3 引入了媒体查询(@media),可以根据设备的不同特性(如屏幕尺寸、分辨率等)为不同的设备提供不同的样式。
            • 弹性盒子布局
              • CSS3 引入了弹性盒子布局(Flexbox),可以更加方便地实现响应式布局和自适应布局。

            如何设置一个 0.5px 的线?

            • 采用 transform: scale()的方式
            • 采用 meta viewport 的方式
            Vue复习计算机网络
            SuHanqin
            SuHanqin
            一个普通的干饭人🍚
            公告
            type
            status
            date
            slug
            tags
            category
            icon
            password
            🎉NotionNext 4.0即将到来🎉
            -- 感谢您的支持 ---
            👏欢迎更新体验👏