【前端面试】基础知识点js/css-查漏补缺

106 阅读10分钟

盒模型

box-sizing:  content-box
box-sizing:  (IE) border-box (width = content + border + padding)

BFC块级上下文

  1. 防止margin重叠
  2. 清除浮动,高度塌陷
让模块变BFC
  1、overflow不为visible
  2、绝对定位position:  absolute / fixed
  3、行内块元素display: inline-block table-cell table-caption
  4display: flex / grid
  5、float不为none

重排 重绘

重排:

  • 首次渲染
  • 浏览器窗口变化
  • 元素的 大小、内容、尺寸变化
  • 元素的删除、新增
  • css的伪类 hover active等属性

重绘:

  • color的改变
  • visibilty改变

除了重排重绘还有css3的硬件加速属性(GPU)

  • opcacity
  • transform
  • filter

减少重排的方案:

  1. html的操作class放在最里层的元素dom上
  2. 减少table属性的使用
  3. 减少css calc 计算属性
  4. 复杂的效果让元素脱离文档流:position
  5. 灵活使用display:none
  6. 事件节流:resize / scroll

DOM事件委托机制

用来监听事件的 document.addEventListener('事件名字', callback, boolean = false为默认值)

  • 捕获 -》从上到下,最后一个参数为true,表明监听捕获阶段
  • 冒泡 -》从内到外,最后一个参数为false,表明监听冒泡阶段,默认为冒泡

正常情况下可以使用冒泡来做事件委托:典型的例子是 ul li 的例子

不会冒泡的事件,如果需要处理则必须在捕获阶段进行处理(设置最后一个参数为true)

  1. scroll
  2. resize
  3. blur / focus
  4. mouserenter / mouseleave
  5. mouserover / mouseout 不会冒泡,因此可以不写e.stoppropagation
  6. media媒体相关的事件:video元素的playing、stop、load、pause等

BOM和DOM的区别

BOM: Window对象,浏览器对象模型,每一个浏览器的厂商都可以进行扩展,不同浏览器不一样

DOM:Window.document对象,文档对象模型,w3c制定的统一的规范,所有浏览器都需要遵守

常见的window上的对象

  • document
  • history
  • screen
  • frames
  • location

Async 和 Defer 的区别

功能:都用于异步加载脚本,不阻塞页面

defer的脚本会 等待页面准备完毕再执行,也就是 DOMContentLoaded函数之后 再执行。

浏览器缓存

Web缓存种类:  数据库缓存,CDN缓存,代理服务器缓存,浏览器缓存。

浏览器缓存其实就是指在本地使用的计算机中开辟一个内存区,同时也开辟一个硬盘区作为数据传输的缓冲区,然后用这个缓冲区来暂时保存用户以前访问过的信息。

一般的说的浏览器缓存,主要是2类 强缓存协商缓存。强缓存不会发起http请求,协商缓存会。

强缓存

不发请求,但是会返回200,直接从缓存中读取。 如何设置:

exipires:
cache-control:
    max-age:
    no-cache:
    no-store:
    private:
    public

协商缓存

强缓存失效之后,浏览器根据请求头的设置向服务器发送请求,服务器来返回是否使用缓存。

缓存生效会返回304。失效会返回200和请求的结果。如何设置

Last-Modified / If-Modified-Since

Etag / If-None-Match

浏览器缓存位置一般分为四类

Service Worker-->Memory Cache-->Disk Cache-->Push Cache: 这些缓存的存放位置一般由浏览器去根据当时的内存利用率进行分配:memory cache 和 dist cache。memory更快,一般存一些js(也不一定),dist里面存一些样式图片等更多。

缓存方案

  • HTML: 协商缓存;
  • css、js、图片:强缓存,文件名带上hash。

前端路由 hash 和 history

hash

  • location.hash => http://www.x.x#demo1
  • 修改hash路由,直接赋值。location.hash = demo2
  • 路由修改监听,hashChange事件
  • hash路由是客户端状态,不会发送到服务器server

history:HTML5的history API,不刷新页面可以操作浏览器

  • pushState
  • replaceState
  • popState
  • go
  • reload = go(0)
  • forward = go(1)
  • back = go(-1)

其中pushState和replaceState不会触发popState事件,并且除了safari浏览器之外,这2个方式设置的title不会生效。

场景:如果使用history路由,如何监听 pushState 和 replaceState事件呢。

思路:复写pushState方法,通过手动的触发一个原生的事件抛出去

  function wrapState(action){
      let raw = history[action]
      return function(){
          let wrapper = raw.apply(this, arguments)
          let event = new Event(action)  // 重要步骤
          event.info = {...arguments} // 重要步骤
          window.dispatchEvent(event) // 重要步骤
          return wrapper
      }
  }
  history.pushState = wrapState('pushState')
  history.replaceState = wrapState('replaceState')

JS垃圾回收机制

  • 引用技计数法
  • 标记清除法

GET和POST

  • post请求体大小不受限制,get受限,不同浏览器不一样
  • post参数在body体中,并且支持多种编码格式;get参数在URL上,使用url编码
  • get请求会被缓存,走cache的机制;post不会

网络安全

  • XSS跨站脚本攻击
  • CRSF伪造站点攻击

TCP

三次握手

四次挥手

域名发散 + 域名收敛

部署的站点的时候需要综合考虑域名的情况,机器以及路由等等的情况

发散:站点使用不同的域名,可以实现多线程下载,网站的速度更快

收敛:TCP有并发的限制,收敛域名也可以减少DNS的开销

css实现垂直居中

flex布局

    display:flex
    align-item:center
    justify-content:center

grid布局

   display: grid
   place-item: center

tranform tranlate方法

    .parent{
        position: relative
    }
    .child{
        top: 50%
        left: 50%
        transform: translate(-50%, -50%)  // 这个属性行类元素无效
    }

图片居中 方案

背景方案

   background: url("image") no-repeat center center;
   background-size: contain

object-fit属性

   object-fit: contain
  • contain:图片和容器不匹配时,保持图片的长宽比,因此会有一个黑边
  • cover: 保持长宽比,但是会被裁剪
  • fill: 填充,不保持图片的比例
  • none:原尺寸
  • scale-down: none和contain属性中尺寸较小的那个效果

img和video这种元素,有一个特定的生效属性object-position

   object-position: 50% 50%; // 默认值

使用css画一个三角型

   width: 0
   height: 0
   border: 50px solid transparent
   border-bottom: 50px solid red

节流throttle + 防抖debounce

应用场景:

节流throttle:间隔某个时间执行

  1. scroll事件
  2. mousedown mouseclick事件
实现方案一:timer
window.onscroll = throttle(fn, 1000)
function throttle(fn, delay){
     let timer = null
     return function(){
         if(timer)return
         timer = setTimeout(()=>{
             fn.call(this, ...arguments)  // 注意写法
             timer = null
         }, delay)
  
     }
}


实现方案二:时间戳
function throttle(fn, delay){
    let time = 0
    return function(){
        let now = new Date().getTime()
        if(now - time > delay){
            fn.apply(this, arguments)  // 注意写法
            time = now
        }
      
    }
}


防抖debounce:一段时间内只执行一次

  1. input输入
  2. resize事件
debounce方法的实现方案主要是清除定时器,只保留最后一次的执行,和上述节流方案对比

window.input = debounce(fn, 1000)
function debounce(fn, delay){
     let timer = null
     return function(){
         if(timer){
             clearTimeout(timer) // 区别,只保留最后一次最新的执行,其他都覆盖清空
           
         }
         timer = setTimeout(()=>{
             fn.call(this, ...arguments)  // 注意写法
             timer = null
         }, delay)
  
     }
}

JS基础

值类型7种:boolean string number undefined null bigint symbol

引用类型:object array

栈:先进后出,主要存放 值类型

堆:分配一个引用,并维护一个引用表,存放引用类型

队列:先进先出

数组常用方法:常用的Array.prototype方法

  • shift unshift // 数组头 删除 新增
  • pop push
  • concat
  • join
  • reverse 反转
  • sort 排序
  • flat 拍平
  • slice (start, end)不修改原数组,返回新数组
  • splice (start, length, new Array)改变原数组,删除并且插入一个新的元素,返回删除元素
  • indexof
  • map
  • forEach
  • filter
  • includes

数组去重

const arr = [1,2,3,1,3,2,1,2,3,4]
  • set方法:利用set的唯一特性
    [new Set(arr)]
  • filter方法:结合indexOf判断下标
    return arr.filter((item, index)=>{
        return arr.indexOf(item) === index
    })
  • reduce方法
    arr.reduce((prev, next)=>{
        if(!arr.inclues(prev)){
            prev.push(next)
        }
        return prev
    }, [])
  • map方法:作为key存储在map中
    map = new Map()
    arr.forEach((i)=>{
        return map.set(i, true)
    })
    Array.from(map.keys())

若数组中包含对象,整体的思路就是转化成string在去重

    const arr = [1,{a:1},{b:1},{a:1},{b:1}]
  • Set方法简写:把对象转成Json.stringify再去重
    Array.from(
        new Set(
            arr.map(JSON.stringify),  JSON.parse
            )
    )
  • Reduce和Map的方法可以同理

改变函数作用域 Call \Apply \Bind

用于修改函数作用域,也就是this的指向

  • bind: 优先于call和apply,不会立即执行。fn.call(this, arguments)
  • call: 参数为罗列显示传参,fn.call(this, ...argumnents)
  • apply: 参数为一个数组,fn.apply(this, argumnents)

js判断基础类型

typeof: 可以用来判断类型,但是null和Array不可用,都会返回'object'

通用方法:Object.prototype.toString.call()

  1. Array.isArray([])
  2. Object.prototype.toString.call([]) === '[Object Array]'

深拷贝 + 浅拷贝

浅拷贝: 直接使用赋值 等号=,拷贝引用

深拷贝:

  • JSON.parse(JSON.stringify(copys))
  1. 这种方法undefined类型会丢失
  2. 不可以拷贝Function
  3. 时间对象Date会变成字符串
  • Object.assign 和它的语法糖写法[...]
  1. 此方法一层对象是深拷贝,嵌套的二层是浅拷贝(引用)
  • 递归函数实现
    function copy(obj){
        let newObj = null
        if(typeof obj === 'object' &&  obj !== null){  // 如果是非null的对象
            newObj = obj instanceof Array ? [] : {}  // 分配一个新的对象或数组
            for(let key in obj){
                newObj[key] = copy(obj[key]) 
            }
        } else {
            newObj = obj
        }
        return newObj
    }

Map 和 Object类型的区别

  1. map是有序的
  2. map比较适合用来实现红黑树:这种数据量大,并且按照特定查找排序时更优
  3. object适合少量数据场景,直接操作属性名也更方便
  4. WeakMap类型的key键只能是引用对象,并且如果此类型没有使用,会被GC垃圾回收机制回收。
  5. weakmap不可以遍历,清空。可以防止内存泄露。

EventLoop JS单线程事件循环机制

同步任务:调用栈中执行

异步任务:队列中排队,等同步任务执行完毕之后再执行。如果异步任务里还有异步任务,在调用栈里面会继续排队进入队列。

异步任务:在当前循环中会优先执行微任务

  1. 宏任务:
  • 定时器:setTimeout setInterval
  • requestAnimationFrame
  • I/O操作:单独线程
  1. 微任务
  • Promise.then,catch,finally
  • MutationObserver
  • process.nextTick

执行顺序优先级:同步任务 > 微任务 > requestAnimationFrame > dom渲染 > 宏任务

export导出

一般来说支持一个默认导出,多个具名导出。重导出可以更换模块的导出名字等等。

  • 一个默认导出
    export default class A(){}
  • 多个具名导出
    export const a;
    export function fn;
    export {
        a,
        b,
        c as cName
    }

  • 重导出/聚合
    export A from './a.js'
    export { default as B } from './b.js'

一行css提升页面滚动性能

    point-event: none
    touch-action: manipulation  // 只允许滚动和持续缩放
  1. 原理:point-event可以阻止鼠标事件,在页面滚动的时候,页面的一些hover,scroll事件可以阻止,提升性能
    body{
        point-event: none
    }

2.html 设置触摸屏操作元素区域,禁止在移动端处理手势

    html{
        touch-action: manipulation
    }
  1. addEventListener: scroll或者touchmove事件可以设置 passive: true
    window.addEventListener('scroll', fn, option)
    // 如果第三个参数不是bool类型,而是一个对象
    window.addEventListener('scroll', fn, {
        passive: true // 告诉浏览器不用执行preventDefault方法,直接调用。从而提升性能
    })
    

window.open

window.open(*URL,name,specs,replace*) 
url: 不传会打开一个空白新窗口 
name: target属性或窗口的名称 
      _parent:加载url到父窗口 
      _top:使用当前url替换任意框架窗口  
      _self:替换当前url 
      _blank:新窗口打开url 
name: 窗口名称,指定之后不会重复打开窗口 
specs: 逗号分割的列表配置集合。 
      fullscreen=yes|no|1|0 : 是否展示全屏 
      height= {}px : 最小值100, 窗口的高度 
      width={}px:最小值100,窗口的宽度 
      left={}px:居左位置 top={}px:距上位置 
      location=yes|no|1|0:是否展示地址栏 
      menubar=yes|no|1|0:是否展示菜单栏 
      resizable=yes|no|1|0: 是否可以拖动变换 
      scrollbars=yes|no|1|0:是否展示滚动条 
      status=yes|no|1|0:是否展示状态栏 
      titlebar=yes|no|1|0:是否展示标题栏 
      toolbar=yes|no|1|0:是否展示工具栏 
  replace: 装载到窗口的 URL 是在窗口的浏览历史中创建一个新条目,还是替换浏览历史中的当前条目