复习笔记

html

什么是重绘?什么是回流?

  • 重绘: 当渲染树中的一些元素需要更新属性,而这些属性只是影响元素的外观、风格,而 不会影响布局的操作,比如 background color,我们将这样的操作称为重绘。

  • 回流:当渲染树中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重 新构建的操作,会影响到布局的操作,这样的操作我们称为回流。

H5有哪些新特性

  • 绘画 canvas;
  • 用于媒介回放的 video 和 audio 元素
  • 本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失; sessionStorage 的数据在浏览器关闭后自动删除
  • 语意化更好的内容元素,比如 article、footer、header、nav、section; 表单控件,calendar、date、time、email、url、search;
  • 新的技术 webworker, websocket;
  • 新的文档属性 document.visibilityState

css

说一下常见的盒子模型,如何切换两种盒子模型?

  • 标准(W3C)盒子模型:属性 width,height 只包含内容 content,不包含 border 和 padding
  • IE盒子模型:属性 width,height 包含 content、border 和 padding,指的是 content +padding+border。
  box-sizing:content-box;
  box-sizing:border-box;

如何解决margin塌陷/margin重叠?

  • 有时当我们设置子元素的margin-top,但是却发现子元素没有出现上外边距的效果,反而是父元素出现了上外边距的效果。第一个子元素设置margin-top父元素会跟着移动,这就是margin塌陷,解决方法:
    • 为父元素设置padding。---要设置padding,设置margin不行
    • 为父元素设置border。---设置border为0px不行,border要有值
    • 为父元素设置 overflow: hidden
    • 父级或子元素使用浮动或者绝对定位absolute

什么是BFCBFC是如何触发的?

  • 容器里面的元素不会在布局上影响到外面的元素

  • 只要元素满足下面任一条件即可触发BFC特性

    • body 根元素
    • 浮动元素:float 除 none 以外的值
    • 绝对定位元素:position (absolute、fixed)
    • display 为 inline-block、table-cells、flex
    • overflow 除了 visible 以外的值 (hidden、auto、scroll)【最常用】

如何实现垂直水平居中

  • flex布局
  .box{
    display: flex;
    align-items: center;
    justify-content: center;
  }
  • 定位
  .box{
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
  }

JavaScript

数据类型都有哪几种,有什么区别?

  • 数据类型分为原始数据类型对象数据类型

    • 原始数据类型:null、Boolean、Number、String、undefined、Symbol、BigInt
    • 对象数据类型:Object
  • 区别:原始数据类型存储在栈区,占用空间较小,存储的是值;对象类型同时存储在栈区和堆区,且大小不固定。

如何判断数据类型

  • typeOf:可以判断基本数据类型,除了null以外,因为null认为是空对象的引用。
  • instanceof:可以判断对象类型,内部机制是通过原型链来进行判断的。
  • constructor:利用原型上的prototype.constructor指向实例的构造函数来进行判断。如果中途改变类型,则判断不准确。
  • Object.prototype.toString.call:使用Object对象的原型方法toString,返回值是[object 类型]字符串。

说一下js类型转换规则

  • 转换为布尔值:除了undefinednullfalseNaN''0-0,剩下的都为true

  • 转化为数字:

    • null,返回0
    • undefined,返回NaN
    • 布尔值, true 转换为1, false 转换为0
    • 字符串:
      • 如果字符串包含数值字符,包括数值字符前面带加、减号的情况,则转换为一个十进制数值
      • 如果字符串包含有效的浮点值格式如 "1.1" ,则会转 换为相应的浮点值(同样,忽略前面的零)
      • 如果字符串包含有效的十六进制格式如 "0xf" ,则会 转换为与该十六进制值对应的十进制整数值。
      • 如果是空字符串(不包含字符),则返回0。
      • 如果字符串包含除上述情况之外的其他字符,则返回NaN。
      • 如果是对象,调用valueof()方法,并按照字符串的规则转换返回的值。如果转换结果是NaN,则调用toString()方法,再按照转换字符串的规则转换。
  • 转换为字符串,直接转化

如何正确判断this?箭头函数的this是什么?如何改变this指向

  • 在浏览器中,全局环境下,this指向window对象。
  • 在函数中,this指向最后调用它的那个对象。
  • 箭头函数的this始终指向其包裹箭头函数的第一个函数。
  • new操作符,指向new出来的那个对象。
  • callapplybind指向绑定的新对象上。

== 和 === 有什么区别?

  • ==如果类型不同,会进行隐式转化;再进行比较。
  • ===直接判断类型和值是否相等。

什么是闭包?

  • 函数A内部有函数B,函数B访问函数A的变量,函数B就是一个闭包。闭包就是为了我们能够间接访问内部变量,避免被垃圾机制回收。
  function a(){
    let a=0;
    function b(){
      a++;
      console.log(a)
    }
    return b
  }
  let n=a();
  n(); //1
  n(); //2

什么是浅拷贝?如何实现浅拷贝?什么是深拷贝?如何实现深拷贝?

  • 浅拷贝:拷贝所有的值到新对象中,如果属性值是对象,则拷贝对象的地址。
  //通过Object.assign
  let a={
    name:'tom',
    age:18
  };

  let b=Object.assign({},a)
  console.log(b);

  //通过展开运算符

  let c={
    name:'lonjin',
    age:18
  };

  let d={...c}
  console.log(d)
  • 深拷贝:拷贝所有的值到新对象中,如果属性值是对象,则拷贝对象的地址。
  // JSON.parse(JSON.stringify(object))实现
  /* 缺点:会忽略 undefined
          会忽略 symbol
          不能序列化函数
          不能解决循环引用的对象 */
  let a={
    name:'tom',
    fnc:{
      age:18
    }
  }

  let b=JSON.parse(JSON.stringify(a))

  a.fnc.age=19

  console.log(b.fnc)

如何理解原型?如何理解原型链?

  • 举个例子:当我们写一个构造函数时候,构造函数身上会有一个prototype属性,这就是该构造函数的原型对象;它可以存一些该构造函数公告的属性和方法,同时该属性身上有constructor属性,它指向创建它的构造函数。

  • 当我们访问一个对象的某个属性时候,如果在对象内部没有找到,就会通过**proto**沿着向上查找,这就是原型链。

w2zC4g.png

var、let 及 const 区别

  • var声明的变量会变量提升
  • let、const声明的变量不会进行变量提升,且有块级作用域
  • const声明时必须赋值

如何实现继承

  • ES5组合继承法:
    function Parent(){
        this.name='tom';
    };

    Parent.prototype.say=function(){
        console.log(this.name)
    };

    function Child(){
        Parent.call(this)
        this.age=18;
    };

    Child.prototype=Object.create(Parent.prototype);

    Child.prototype.constructor=Child;
  • ES6使用class:
  class Parent{
    constructor(name,age){
      this.name=name;
      this.age=age;
    }
  }

  class Child extends Parent{
    constructor(name,age,say){
      super(name,age);
      this.say=say;
    }
  }

  let c=new Child('bob',17,'say hi')

Proxy 可以实现什么功能?

  • Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。vue3中就是通过Proxy取代Object.defineProperty来实现数据响应式。

forEach、map、filter、find、reduce、every、some都适用于哪种场景?

  • forEach:进行遍历操作,可在当前遍历对象身上直接操作,不会产生新数组。

  • map:用于遍历操作,且需要返回值,如果没有返回值,则为undefined,map会返回一个新数组。

  • filter:进行一些筛选过滤,return符合条件的值产生新数组。

  • find:根据指定的条件找到数组中符合条件的值。

  • reduce:提取数组对象中某个值|数组求和

Promise 的特点是什么,分别有什么优缺点?什么是 Promise 链?Promise 构造函数执行和 then 函数执行有什么区别?

  • Promise本译就是承诺的意思,这个承诺会在未来有一个确切的答复,并且该承诺有三种状态:

    • 进行中:pending
    • 完成了:resolved
    • 失败了:rejected
  • 承诺状态一旦改变就不可更改,且在构造Promise时候,构造函数内部代码是立即执行的。

  new Promise((resolve, reject) => {
    console.log('Promise')
  })
  console.log('finifsh') //Promise -> finifsh
  • Promise可以进行链式调用,每次then()都是一个新Promise。如果在Promise中使用了return,也会被转化为Promise.resolve()

async 及 await 的特点,它们的优点和缺点分别是什么?await 原理是什么?

  • 在普通函数前面加上async,该函数返回就成了一个Promise,如果要使用其返回值,我们就可以使用then():
  async function fn(){
      console.log('fn');
      return 'i im fn'
  };

  fn().then((val)=>{
      console.log(val)
  })
  //fn ---> i im fn
  • await只能在async函数内使用

谈一谈js的执行机制

  • js是一种单线程异步非阻塞解释型脚本语言,它最大的特点就是单线程。在js执行时候,从上往下,先吧同步任务放到执行栈中执行,当遇到异步任务时候,会把异步任务放到异步队列,当执行栈为空的时候,会从异步队列中取出一条压入执行栈,这样一直循环,这就是Event Loop。异步任务又分为宏任务微任务微任务优先于宏任务

new操作符都干了什么?

  • 在内存中创建一个新对象
  • 这个新对象内部的[[prototype]]特性被赋值为构造函数的prototype属性
  • 构造函数内部的this被赋值为这个新对象(即this指向新对象)
  • 如果构造函数返回非空 对象,则返回该对象;否则,返回刚创建的新对象
  function _new(fn,...args){
      const newObj = Object.create(fn.prototype);
      const value = fn.apply(newObj,args);
      return value instanceof Object ? value : newObj;
  }

为什么 0.1 + 0.2 != 0.3?如何解决这个问题?

  • 因为精度问题导致的,解决方法如下:
   parseFloat((0.1 + 0.2).toFixed(10)) === 0.3 // true

说一说浏览器垃圾回收机制

  • 浏览器垃圾回收机制有好几种方案,之前大部分浏览器采用标记清理,还有一部分使用引用计数。V8新生代算法把内内存空间分为两部分:Fromto空间,这两个空间必定有一个是空的,当一个空间满了以后,就会检查当前空间存活的对象放到另外一个空间。

什么是防抖?什么是节流?

  • 防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
  function debounce(fn,wait){
    let timer=null;
    return function(){
        clearTimeout(timer);
        timer=setTimeout(function(){
            fn.apply(this)
        },wait)
    }
  }

  document.getElementById('btn').onclick=debounce(function(){console.log('触发'+Date.now());},1000)
  • 节流:规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
   function throttle(fn,wait){
        // 记录上一次函数执行的时间
        var lastTime=0;
        
        return function(){
             // 现在时间
            var nowTime=new Date();

            if(nowTime-lastTime>wait){
                fn.call(this);
                lastTime=nowTime; 
            }
        }
    };
    document.onscroll=throttle(function(){console.log('触发'+Date.now());},1000)

Vue

谈一谈Vue的生命周期,在哪个周期可以获取DOM?平时获取数据可以在哪个生命周期执行?

  • 简单来说,Vue的生命周期可以归为3类,创建阶段、运行阶段、销毁阶段。

  • 创建阶段

    • beforeCreate:实例刚在内存中创建出来,还没有初始化 data和 methods,只包含一些自带额生命周期函数。

    • created:实例已经在内存中创建完成,此时data和methods已经创建完成。

    • beforeMount:此时已经编译模版,但没有渲染到页面中。

    • mounted:渲染模版,创建阶段到此结束。这时候可以操作dom。

  • 运行阶段

    • beforeUpdate:界面中的数据还是旧的,但是data数据已经更新,页面中和data还没有同步。修改data数据就会触发这个函数。

    • updated:页面重新渲染完毕,页面中的数据和data保持一致。修改data数据就会触发这个函数。

  • 销毁阶段

    • beforeDestroy:执行该方法的时候,Vue的生命周期已经进入销毁阶段,但是实例上的各种数据还出于可用状态。

    • destroyed:组件已经全部销毁,Vue实例已经被销毁,Vue中的任何数据都不可用

  • keep-alive

    • activited:keep-alive 专属,组件被激活时调用

    • deactivated:keep-alive 专属,组件被销毁时调用

组件如何进行通信?

  • 父子组件

    • props/$emit:父组件通过props来给子组件传递数据,子组件可以通过$emit发送事件给父组件。但这种父子直接传递数据是单向数据流

    • $$parent/$children:通过$parent$children就可以访问组件的实例

    • ref/refs:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据

  • 兄弟组件

    • this.$parent.$children:在$children 中可以通过组件name查询到需要的组件实例。
  • 任意组件

    • Vuex
    • Event Bus:eventBus又称为事件总线,在vue中可以使用它来作为沟通桥梁的概念, 就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件, 所以组件都可以通知其他组件。eventBus也有不方便之处, 当项目较大,就容易造成难以维护的灾难。

vue2双向绑定的原理是什么?vue3和vue2双向绑定有什么区别?

  • vue2是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。Object.defineProperty()只能对属性进行数据劫持,不能对整个对象进行劫持,同理无法对数组进行劫持。vue3中则采用Proxy,它可以监听到数组内的数据变化。

为什么 Vue 组件中 data 必须是一个函数?

  • 如果 data 是一个对象,当复用组件时,因为 data 都会指向同一个引用类型地址,其中一个组件的 data 一旦发生修改,则其他重用的组件中的 data 也会被一并修改。
    如果 data 是一个返回对象的函数,因为每次重用组件时返回的都是一个新对象,引用地址不同,便不会出现如上问题。

Vue 中 computed 和 watch 有什么区别?

  • 计算属性computed
    (1)支持缓存,只有依赖数据发生变化时,才会重新进行计算函数;
    (2)计算属性内不支持异步操作;
    (3)计算属性的函数中都有一个 get(默认具有,获取计算属性)和 set(手动添加,设置计算属性)方法;
    (4)计算属性是自动监听依赖值的变化,从而动态返回内容。

  • 侦听属性 watch:
    (1) 不支持缓存,只要数据发生变化,就会执行侦听函数;
    (2) 侦听属性内支持异步操作;
    (3) 侦听属性的值可以是一个对象,接收 handler 回调,deep,immediate 三个属性;
    (3) 监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些其他事情。

vuex 都有哪些部分组成?

  • state:用来存储数据
  • Getter:用来获取state中的值
  • Mutation:唯一可以改变state中的值,且必须是同步函数
  • Action:用于提交mutation,而不是直接变更状态,可以包含任意异步操作
  • Module:许将单一的Store拆分为多个store且同时保存在单一的状态树中。

浏览器相关

输入URL到页面渲染中都发生了什么?

1.URL 解析
2.DNS 查询
3.TCP 连接
4.处理请求
5.接受响应
6.渲染页面