2023年Web前端面试题(持续更新中ing。。。)

html + css

盒模型

分为两种:W3C标准盒模型和IE怪异盒模型

WC3: width + height

IE: width + height+padding+border

content-box和border-box区别

content-box(默认):宽度和高度之外绘制内边距和边框

border-box:宽度和高度之内绘制设定元素的边框及内边距

行元素、块级元素、行内块元素有哪些

行元素:span、strong、input、a、b、i、em、img等

块元素:div、h1~h6、hr、ul、p、li、table

行内块元素:img、input、td

怎么让Chrome支持小于12px的文字

1.zoom:可以改变页面上元素的尺寸,属于真实尺寸



    测试10px
    测试12px

-webkit-transform:scale()只对可以定义宽高的元素生效,如果是行内元素的话,应该先转为行内块元素。



    测试10px
    测试12px

说说 HTML5 有哪些新特性?
 

1.语义化标签

2.增强型表单包括属性以及元素

3.新增视频

4.Canvas 图形

5.地理定位

6.拖放API

7.SVG绘图

css3特性

animation // 动画

transition // 动画过度

text-shadow // 文字阴影

box-shadow // 盒子阴影

border-radius // 圆角

border-image // 图片边框

color: rgba(0,0,0,0.1) // 透明度设置

background-clip // 背景绘制

flex //布局

// 媒体查询

// 多列布局

语义化标签有哪些

header   头部

nav         导航栏

section    区块

main        主要区域

article      主要内容

aside       侧边栏

footer      底部

px、rpx 、em、rem、vh/vw的区别

px: px是显示器屏幕分辨率而言的尺寸单位

rpx:是微信小程序独有的、解决屏幕自适应的尺寸单位

em: 相对于父元素的字体尺寸
rem: 相对于根元素的字体大小
vh\vw: 相对于视口的高度和宽度。1vh = 1/100 的浏览窗口高度,1vw = 1/100 的浏览器窗口宽度

css选择器有哪些

标签选择器、类选择器、层级选择器(后代选择器)、id选择器、组选择器、伪类选择器

!important >内联 > ID选择器 > 类选择器 > 标签选择器

清除浮动

1、父元素使用overflow:hidden、auto

2、使用伪元素清除浮动

伪类和伪元素

a:link      // 未访问
a:hover     //  悬停
a:visited   // 已访问
a:active    // 已选择

常用的伪元素:

span::before {  // 内容前面插入新内容
    content:'';
}
span::after{  // 内容之后插入新内容
    content:'';
}

伪类与伪元素的特性及其区别


1、伪类本质上是为了弥补常规CSS选择器的不足,以便获取到更多信息

2、伪元素本质上是创建了一个有内容的虚拟容器

3、CSS3中伪类和伪元素的语法不同

  伪类  :link  :hover              单冒号

  伪元素  ::before    ::after   双冒号

4、可以同时使用多个伪类,而只能同时使用一个伪元素

5、其中伪类和伪元素的根本区别在于:它们是否创造了新的元素,这个新创造的元素就叫  "伪元素"

6、伪元素/伪对象:不存在在DOM文档中,是虚拟的元素,是创建新元素。

   这个新元素(伪元素)是某个元素的子元素,这个子元素虽然在逻辑上存在,但却并不实际存在于文档树中

7、伪类:存在dom文档中标签,在伪类时改变样式

8、因为伪类是类似于添加类所以可以是多个,而伪元素在一个选择器中只能出现一次,并且只能出现在末尾

写一个左中右布局占满屏幕,其中左右两块是固定宽度200 ,中间自适应宽

第一种:使用flex 

    
    

第二种:使用绝对定位

.left,
      .right {
        width: 200px;
        height: 200px;
        background-color: #ccc;
        position: absolute;
      }
      .left {
        left: 0;
      }
      .right {
        right: 0;
      }
      .center {
        height: 200px;
        margin: 0 200px;
        background-color: burlywood;
      }

如何画一条0.5的线?

transfrom:scale(0.5)

css绘制三角形

普通三角形

2023年Web前端面试题(持续更新中ing。。。)_第1张图片

div {
    width: 0;
    height: 0;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom: 100px solid red;
   }

右上角角标的三角形 

2023年Web前端面试题(持续更新中ing。。。)_第2张图片

div {
    width: 0;
    height: 0;
    border-top: 100px solid red;
    border-left: 100px solid transparent;
   }

分别写出3种垂直居中的方法

      /* 第一种 */
      div{
            width: 200px;
            height: 200px;
            background-color: bisque;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%,-50%);
        }

      /* 第二种 */
      div{
            width: 200px;
            height: 200px;
            background-color: bisque;
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            margin: auto;
        }

      /* 第三种 */
      div {
        width: 200px;
        height: 200px;
        background-color: bisque;
        position: absolute;
        top: 50%;
        left: 50%;
        margin: -100px 0 0 -100px;
      }

 js部分

 数据类型

基础数据类型:Undefined、Null、Boolean、Number、String、Symbol【ES6】、Bigint【ES10】
复杂数据类型(三大引用类型):Object、Array、Function 【Arrar和Function都属于Object类型】

symbol数据类型

  • Symbol()是一个内置全局函数,生成一个独一无二的的数据。
  • 每一个属性名都是独一无二的,从根本上防止属性名的冲突。
  • symbol 的值是通过 Symbol() 函数生成
  • 相同参数的Symbol函数的返回值是不相等的

typeof和instanceof的区别

同:判断一个变量是否为空, 或者是什么类型的

异:

typeof返回值是一个字符串, number, boolean, string, function, object, undefined

typeof缺点:null的值object,无法分辨是null还是object

instanceof返回值是boolean,只能识别object,function,Array

ES6新特性

(1)变量声明

(2)解构赋值

(3)模板字符串(template string)

(4)ES6 提供了新的语法规则来定义函数 —— 箭头函数

(5)数据结构Set

(6)数据结构 Map

(7)for...of 循环

(8)Promise对象

(9)async/await


axios跟proimse有什么区别?

axios 是由 promise 封装的一个 http 的库,可以用于在浏览器和Node.js中对HTTP请求进行简单的封装,支持拦截器、并发请求等功能,适用于各种类型的HTTP请求,例如GET、POST等。

promise同步

promise是一个对象,用于获取异步操作的数据

优点:避免回调地狱

      简介的api,操作更加容易

      容易理解,便于维护

      容易操作相互依赖的异步请求

缺点:一旦执行,没办法取消

      如果不设置回调函数,内部的错误,没办法抛到外部

      不知道当前的状态

promise有三个状态:正在请求,成功,失败

async await


async 和await两种语法 ,可以让异步代码像同步代码一样

async函数

async函数的返回值为promise对象
promise对象的结果由async函数执行的返回值决定

await表达式

await必须写在async函数中
await右侧的表达式一般为promise对象
await返回的是promise成功的值
await的promise失败了,就会抛出异常,需要通过try…catch捕获处理
 

Set集合

只能去重简单数据类型,不能引用数据类型

原因:存储机制不同,基本数据类型是存储在栈中,引用数据类型存储在堆中,指向它们的具体内容,每个具体对象就有一个具体的地址指向它,所以去重不了。null也属于对象,但是没有地址可以指向,存的就是null,所以就被去重掉了。

        const arr = [1, 2, 3, 4, 5, 5, 5, 5, 5]
        console.log(... new Set(arr)) //1,2,3,4,5

map集合

  • Map是一种新的数据结构,它可以用来存储键值对,并且键可以是任何类型,而不仅仅是字符串类型。Map的作用如下:
  • 存储键值对:Map可以存储任意类型的键值对,包括对象、函数、布尔值等。
  • 快速查找:Map提供了快速查找键值对的方法,可以通过键来获取对应的值,而不需要遍历整个Map。
  • 迭代器:Map提供了迭代器,可以遍历所有的键值对。
  • 易于操作:Map提供了多种操作方法,如添加、删除、获取、清空等。
  • 与数组的转换:Map可以与数组相互转换,可以通过Array.from方法将Map转换为数组,也可以通过new Map()方法将数组转换为Map。
  • 解决键冲突问题:Map使用严格相等运算符(===)来判断键是否相等,因此不会出现键冲突的问题。
  • 可以作为缓存:由于Map的键可以是任何类型,因此可以将函数的参数作为键,将函数的返回值作为值,从而实现一个简单的缓存功能。

注意:map的key只能用基础数据类型,不能用引用数据类型,否则返回的值是undefined 

一、创建

    let map = new Map([[1, 2, 3], [4, 5], ['name', 'zs']])
    console.log(map);  // Map(3) {1 => 2, 4 => 5, 'name' => 'zs'}
    console.log(typeof map);  // object


二、用法
1.set()方法

    // 1.set() 给实例设置一对键值对,返回map实例,有两个参数,第一个key,第二个value
    map.set(5, 6)  // Map(4) {1 => 2, 4 => 5, 'name' => 'zs', 5 => 6}
    map.set([1], [2])  // Map(5) {1 => 2, 4 => 5, 'name' => 'zs', 5 => 6, Array(1) => Array(1)}
    map.set(function () { }, [2])  // Map(6) {1 => 2, 4 => 5, 'name' => 'zs', 5 => 6, Array(1) => Array(1), …}
    console.log(map);  // Map(6) {1 => 2, 4 => 5, 'name' => 'zs', 5 => 6, Array(1) => Array(1), …}


2.get()方法

    // 2.get() 获取指定键名的键值,返回键值
    console.log(map.get([1]));  // undefined
    console.log(map.get(5));  // 6


3.delete()方法

    // 3.delete() 删除指定键值对,成功返回true,失败返回false
    console.log(map);  // Map(6) {1 => 2, 4 => 5, 'name' => 'zs', 5 => 6, Array(1) => Array(1), …}
    map.delete(5)
    console.log(map);  // Map(5) {1 => 2, 4 => 5, 'name' => 'zs', Array(1) => Array(1), ƒ => Array(1)}


4.clear()方法

    // 4.clear()  清空Map中所有的键值对
    map.clear()
    console.log(map);  // Map(0) {size: 0}


5.has()方法

    // 5.has()  判断Map中是否包含对应的键,返回布尔类型的值
    console.log(map.has([1, 2, 3]));  // false
    console.log(map.has('name', 'zs'));  // true


6.entries()方法

    // 6.entries()  返回实例的键值对遍历器
    for (let [key, value] of map.entries()) {
        console.log(key);  // 1 4 name [1] ƒ () { }
        console.log(value);  // 2 5 zs [2] [2]
    }


7.keys()方法 values()方法

    // 7.keys()  values()
    /* 
        keys( )方法:返回实例所有键名的遍历器。
        values( ) 方法:返回实例所有键值的遍历器。
     */
    for (let x of map.keys()) {
        console.log(x);  // 1 4 name [1] ƒ () { }
    }
    for (let y of map.values()) {
        console.log(y);  // 2 5 zs [2] [2]
    }


8.forEach()方法

    // 8.forEach()  循环遍历Map中的所有键值对
    map.forEach((key, value) => {
        console.log(key + ':' + value);  // 2:1 5:4 zs:name 2:1 2:function () { }
    })


9.size属性

    // 9.size属性  获取Map中键值对的数量
    console.log(map.size);  // 5

变量和函数声明的提升

  • 在js中声明变量和函数会提升到最顶部执行
  • 函数的提升高于变量的提升
  • 匿名函数不会提升。

数组常用的方法 

添加:

arr.unshift() 从前面添加元素, 返回值是添加完后的数组的长度

arr.push() 从后面添加元素,返回值为添加完后的数组的长度

删除:

arr.shift() 从前面删除元素,只能删除一个 返回值是删除的元素

arr.pop() 从后面删除元素,只能是一个,返回值是删除的元素

arr.splice(i,n) 删除从i(索引值)开始之后的那个元素。返回值是删除的元素

arr.slice(start,end) 切去索引值start到索引值end的数组,不包含end索引的值,返回值是切出来的数组

遍历:

arr.forEach() 遍历数组,无return  即使有return,也不会返回任何值,并且会影响原来的数组

arr.map() 映射数组(遍历数组),有return 返回一个新数组 。

过滤:

arr.filter() 过滤数组,返回一个满足要求的数组 

转化:

str.split() 将字符串转化为数组

排序:

 arr.sort() 将数组进行排序,返回值是排好的数组,默认是按照最左边的数字进行排序,不是按照数字大小排序的

arr.reverse() 将数组反转,返回值是反转后的数组

slice和splice区别?

1.splice改变原数组,slice不改变原数组。

2.splice除了可以删除之外,还可以插入。

3.splice可传入3个参数,slice接受2个参数。
 

判断数据是NaN

isNaN();

注意:isNaN(undefined)也是return true,所以,外层要先判断不是undefined

var a = NaN
if(a !== undefined ){
   console.log(isNaN(a));
}

iframe的优缺点有哪些

优点:

  • iframe能够原封不动地把嵌入的网页展示出来;
  • 提高页面代码的复用性;
  • 解决加载第三方内容缓慢,如图标和广告等的加载问题;
  • 在处理上传或局部刷新时,避免了页面整体刷新;
  • iframe解决部分跨域问题;

缺点:

  • iframe会阻塞主页面的 onload 事件;
  • 页面会增加服务器的http请求;
  • 会产生很多页面,不便于管理;
  • 会出现区域的上下、左右滚动条,滚动条会挤占页面空间;
  • 无法被一些搜索引擎索引到;
  • 很多移动设备无法完全显示框架,设备兼容性差;
  • 使用框架时,要保证正确的使用导航链接,容易造成链接死循环;

$nextTick

更新完data数据后,需要及时渲染视图层

普通函数和构造函数的区别

1创建.构造函数也是一个普通函数,创建方式和普通函数一样,但是构造函数习惯上首字母大写

2.调用:普通函数直接调用,构造函数要用关键字new来调用

3.this:构造函数内部的this指向实例,普通函数内部的this指向调用函数的对象(如果没有对象调用,默认为window)

4.return:构造函数默认的返回值是创建的对象(也就是实例),普通函数的返回值由return语句决定

5.构造函数内部会创建一个新对象,就是实例,普通函数不会创建新对象

6.构造函数的函数名与类名相同

谈谈this对象的理解

1.直接输入this指向window(全局)

  • 在非严格模式下,this指向window
  • 在严格模式下,this指向undefined
      function fun(){
        console.log(this);   //window
      }
      fun()

      function fun1(){
        'use strict'
        console.log(this);  //undefined
      }
      fun1()

2.作为方法被调用,谁调用方法,this就指向谁

      let obj = {
        name:'lxy',
        fun(){
          console.log(this);  //指向obj
        }
      }

      obj.fun()

3.元素绑定事件,this指向DOM对象 

    测试10px
    

4. 构造函数

  • 构造函数:名称规范用大驼峰模式
  • new关键字做了什么?
  1. 创建了一个空对象
  2. 将空对象的原型,指向构造函数的原型
  3. this指向空对象
  4. 如果构造函数返回一个基本类型的值 则返回结果没有变化

    如果返回一个对象 则结果就是你返回的对象

      // 构造函数:名称规范用大驼峰模式
      // new关键字做了什么?
      // new会创建对象,将构造函数(Dog)的this指向创建出来的对象--->dog
      function Dog(){
        this.name = "lxy",
        this.fun = function(){
          console.log(this);  //dog
        }
      }
      let dog = new Dog()
      dog.fun()

      console.log(Dog.prototype == dog.__proto__);  //将空对象的原型,指向构造函数的原型

 5.箭头函数,this指向它的父级

防抖和节流

防抖(debounce):事件被触发后,延迟n秒后再执行事件,如果在这n秒内事件被再次触发,则重新计时

防抖的概念:如果有人进电梯(触发事件),那电梯将在10秒钟后出发(执行事件监听器),这时如果又有人进电梯了(在10秒内再次触发该事件),我们又得等10秒再出发(重新计时)。

防抖的应用场景:

用户在输入框连续输入一串字符时,可以通过防抖策略,只在输入完后,才执行查询的请求,这样可以有效减少请求次数,节约请求资源.

例子:点击了按钮,需要两秒触发,还没两秒又点击了按钮,则需要又等两秒才能触发(重新计时)




    
    
    Document


    
    


节流(throttle):可以减少一段时间内事件的触发频率

节流阀的概念:

高铁的卫生间是否被占用,由红绿灯控制,假设一个每个人上洗手间要五分钟,则五分钟之内别人不可以使用,上一个使用完毕之后,将红灯设置为绿灯,表示下一个人可以使用了.下一个人在使用洗手间时需要先判断控制灯是否为绿色,来知晓洗手间是否可用.

节流策略的应用场景:

  • 鼠标不断触发某事件时,如点击,只在单位事件内触发一次.
  • 懒加载时要监听计算滚动条的位置,但不必要每次滑动都触发,可以降低计算频率,而不必要浪费CPU资源. 

例子:

点击了按钮,触发时间需要两秒,无论中途点击了多少次都不会再触发,也不会重新计算触发时间;只能等两秒后,再重新被触发




    
    
    Document


    


区别

防抖:如果事件被频繁触发,防抖保证只能有一次触发生效,前面N多次触发都会被忽略.

节流:如果时间被频繁触发,节流能减少事件触发的频率,因此,节流是有选择性的执行一部分事件. 

总结:函数节流(throttle)与 函数防抖(debounce)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。

从输入url到展示页面加载的过程

  • 通过DNS解析获得网址的对应IP地址
  • 浏览器与远程web服务器 通过TCP三次握手协商来建立一个 TCP/IP 连接
  • 浏览器 通过TCP/IP连接 向web服务器 发送一个 HTTP 请求
  • 服务器的永久重定向响应
  • 浏览器跟踪重定向地址
  • 服务器处理请求
  • 服务器返回一个 HTTP 响应
  • 浏览器渲染:解析HTML、解析CSS、解析JS、Render树

三次握手和四次挥手

总结:三次握手是建立连接,四次挥手是关闭连接

握手

  • 客户端发送syn数据包表示请求连接
  • 服务器收到syn,发送ack的数据包表示同意建立连接
  • 客户端再发送ack数据包表示成功连接

2023年Web前端面试题(持续更新中ing。。。)_第3张图片

 挥手

  • 客户端发送FIN表示关闭连接
  • 服务端收到FIN,发送ACK,表示等待关闭
  • 服务端还可以发送未发送数据,客户端还可以接收数据,等服务端发送完数据后,发送FIN进入最后确认状态
  • 客户端收到FIN,发送ACK进入超时等待状态,服务端收到ACK后,立即关闭连接

2023年Web前端面试题(持续更新中ing。。。)_第4张图片

 
为什么是三次握手不是两次握手?

服务端发送完syn/ack之后就建立连接,为了防止已失效的请求报文,突然又传到服务器引起错误

为什么js是单线程的?

单线程 :只有一个线程,只能做一件事

js里面有可视的DOM,如果是多线程的话,这个线程正在删除DOM节点,另一个线程在编辑DOM节点,导致浏览器不知道听谁的

如何实现异步编程?

  • 1、定时器都是异步操作
  • 2、事件绑定都是异步操作
  • 3、AJAX中一般我们都采取异步操作(也可以同步)
  • 4、回调函数可以理解为异步(不是严谨的异步操作)

宏任务和微任务

宏任务:script(整体代码)、setTimeout、setInterval、setlmmediate、l/O/UI rendering

微任务:promise、Object.observe、MutationObserver

优先级:process.nextTick > promise.then>setTimeout>setlmmediate

回流和重绘

回流:当render tree中的元素结构或尺寸发生改变,浏览器重新渲染的过程叫做回流

比如:

  • 页面首次渲染
  • 浏览器窗口大小变化
  • 内容变换
  • 添加或删除节点
  • 激活css伪类

重绘:当页面元素的样式发生改变,不影响文档流中的位置,这个过程叫做重绘

总结:回流一定会引起重绘,重绘不一定会引起回流

网页中有大量的图片加载很慢

  • 图片懒加载,滚动到某个位置再加载图片
  • 图片预加载,预先加载图片的前一张和后一张

DOM和BOM 

DOM:document,获取元素得文档对象类型,可以设置标签的属性,跟浏览器没有关系 

BOM:browser object model,浏览器对象模型,提供浏览器窗口进行交互的对象,管理页面与页面之间的通讯,核心对象是window

常用有:location(url相关的操作)、history(历史相关的操作)、navigator(浏览器相关的信息)

事件冒泡

一个事件触发后,会在子元素和父元素之间传播,这种传播分为三个阶段,

捕获阶段(从window对象传导到目标节点(从外到里),这个阶段不会响应任何事件),目标阶段,(在目标节点上触发),冒泡阶段(从目标节点传导回window对象(从里到外)),事件委托/事件代理就是利用事件冒泡的机制把里层需要响应的事件绑定到外层

事件捕获和事件冒泡

  • 事件捕获:事件从document对象到目标事件的顺序触发,从上至下执行
  • 事件冒泡:事件从目标事件到document对象的顺序触发,从下至上执行

优先级:事件捕获 > 事件冒泡 

内存泄露

内存泄漏是指一块被分配的内存既不能使用又不能回收,直到浏览器进程结束

JS垃圾回收机制是怎样的?

垃圾回收机制是为了防止内存泄漏,寻找没用的变量,释放它所指向的内存

JS垃圾回收方式

有两种方式: 标记清除、引用计数

标记清除:大部分浏览器使用这个方法,当变量进入执行环境时,垃圾回收器将该变量进行了标记,当该变量离开环境的时候,再度标记,进行删除。

引用计数:这种方式常常会引起内存泄露,主要存在于低版本浏览器。跟踪某一个变量的使用次数,当变量赋值给另一个变量的时,引用次数加;如果该变量又赋值另一个变量,引用次数减1,当引用次数为0时,进行删除

事件委托

事件代理(Event Delegation),又称之为事件委托。“事件代理”即是把原本需要绑定在子元素的响应事件(click、keydown......)委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。
 

什么是浏览器缓存?

浏览器缓存就是把一个已经请求过的web资源(如html页面,图片,JS,数据)拷贝一份放在浏览器中。缓存会根据进来的请求保存输入内容的副本。当下一个请求到来的时候,如果是相同的URL,浏览器会根据缓存机制决定是直接使用副本响应访问请求还是向源服务器再次发起请求。

使用缓存的原因

(1)减少网络带宽消耗

(2)减少网络延迟

(3)减少服务器压力

面向对象

概念:面向对象是一种编程思想

特点:1. 封装,属性和方法定义在对象里面。

           2.继承,子对象可以使用父对象的属性和方法

           3.多态,分别有两种形式。

              重载:同一方法名,根据传入的参数不同,而执行不同操作

              重写:子对象重新定义一个新的属性或方法覆盖父对象中继承的属性或方法。

Map 跟 forEach区别

相同点:

1) 都是循环遍历数组中的每一项。

2) 每次执行匿名函数都支持三个参数,参数分别为item(当前每一项),index(索引值),arr(原数组)。

3)只能遍历数组。

不同点

1) map()返回新数组,有返回值

2)forEach()在原数组修改,没有返回值

性能优化

1.减少http请求

2.减少DOM的操作

3.使用浏览器缓存

4.压缩css和js文件

5.css放在页面的最上面,js放在页面的最下面

6.使用CDN

7.避免重定向

8.避免图片 src 为空

'=='跟'==='的区别

'=='值相等即可(判断之前会做类型转换)

'==='类型和值都要相等

var let const的区别

var变量提升

let,const都是块级作用域,var是函数作用域

const只能赋值一次,不能重新赋值,声明必须赋值

同一作用域下let和const不能声明同名变量,而var可以

转换为Boolean类型的值时,都会转换为false

undefined和null

  • 变量被声明了,但没有赋值时,就等于undefined。
  • 调用函数时,应该提供的参数没有提供,该参数等于undefined。
  • undefined 转化为数字类型为NaN
  • 非严格相等的比较下,两者是相等的(null==undefined //true)
  • Undefined类型的值会返回undefined.而Null类型的值返回为object
  • undefined会转换为NaN,无法参与计算,而null会转换为0,
  • null表示一个特殊的空对象

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

箭头函数

1、匿名函数,this指向的是父级,也就是谁创建它,this就指向谁

2、不能进行函数提升

3、不能new

4、不能改变this指向

普通函数this,谁调用,this就指向谁

作用域和作用域链

  • 作用域就是代码的执行环境,全局执行环境就是全局作用域,函数的执行环境就是私有作用域,它们都是栈内存
  • 当代码在一个环境中执行时,会创建变量对象的一个作用域链(作用域形成的链条)
  • 内部环境可以通过作用域链访问所有外部环境,但外部环境不能访问内部环境的任何变量和函数
  • 当在内部函数中,需要访问一个变量的时候,首先会访问函数本身的变量对象,是否有这个变量,如果没有,那么会继续沿作用域链往上查找,直到全局作用域。

原型与原型链

谈谈你对原型的理解?
每当定义一个对象(函数也是对象),对象中都会有一些预定义属性。其中每个函数对象都有一个prototype 属性,这个属性指向函数的原型对象,使用原型对象的好处是,所有对象实例共享它的属性和方法

什么是原型链?原型链解决的是什么问题?
1)原型链解决的主要是继承问题
2)每个对象拥有一个原型对象,通过 proto 指针指向其原型对象,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向 null(Object.proptotype.__proto__指向的是null)。这种关系被称为原型链(prototype chain),通过原型链一个对象可以拥有定义在其他对象中的属性和方法

prototype 和 proto 区别是什么

1)prototype是构造函数的属性
2)__proto__是每个实例都有的属性,可以访问 [[prototype]] 属性
3)实例的__proto__与其构造函数的prototype指向的是同一个对象

cookies sessionStorage和localstorage区别

存储大小:Cookies不能超过4k, sessionStorage、localstorage,可以达到5m甚 至更大

存储时间:cookies设置有效时间

                  sessionStorage浏览器关闭,自动清除

                  localstorage除非删除,否则一直存在

apply,bind,call的区别

相同:

修改this指向

不同:

1.执行方法:call和apply是同步,bind是异步 

2.传参不同

  • apply(obj,[1,2]) //以数组方式
  • bind(obj,1,2)() //以逗号隔开,返回函数
  • call(obj,1,2) //以逗号隔开

3. 修改this: call、apply是临时的修改一次,也就是call和apply方法的那一次;当再次调用原函数的时候,它的指向还是原来的指向, bind是永久修改函数this指向

4. call和apply可以调用函数,bind返回值是一个函数

闭包

概念:函数嵌套函数

作用:内部函数可以访问外部函数的参数和变量

          变量保存在内存中

缺点:使用不当,会导致内存泄漏

解决:在退出函数之前,将不适用的变量全部删除

数组去重

      // 第一种
      var arr = [1,2,1,2,1]
      arr = [...new Set(arr)]
        
      // 第二种
      var arr = [1,2,1,2,1]
      var arr1 = arr.map((item,index) => {
        if(arr1.indexOf(item) < 0){
          arr1.push(item)
        }
      })

      // 第三种
      var arr = [1,2,4,3,1,1,2,2,21]
      var arr1 = arr.filter((item,index,arr) => {
          return arr.indexOf(item) === index
      })

数组对象去重

    let arr = [
      {
        key: "1",
        name: "林青霞",
      },
      {
        key: "2",
        name: "张三丰",
      },
      {
        key: "1",
        name: "段誉",
      },
    ];
    let obj = {};
    let arr1 = arr.reduce(function (preValue, item) {
      obj[item.key] ? "" : (obj[item.key] = true && preValue.push(item));
      return preValue;
    }, []); 

同步和异步

同步: 只有前一个任务执行完毕,才能执行下一个任务

异步:不会阻塞下面代码执行,前一个任务还没执行完毕,下一个任务依然执行

比如:定时器(setTimeout、setInterval) 、ajax的异步请求、promise

 深拷贝和浅拷贝的方法

  • 浅拷贝:如果原地址改变,那么拷贝的对象也会改变,新旧对象共享内存,修改其中一个,另一个也会影响
  • 深拷贝:内存中开辟一块新的地址存放赋值的对象,新旧对象不会共享内存,修改其中一个,不会影响另一个

浅拷贝:

  1. Object.assign
    var obj1 = {
        name:'zangsan',
        age: 18
    }
    var obj2 = Object.assign(obj1);
    
  2. 扩展运算符(...)
    var obj1 = {
        name:'zangsan',
        age: 18
    }
    var obj2 = {...obj1};
    

 深拷贝

     1、JSON对象来实现深拷贝【缺点:函数无法拷贝,会显示undefined】

      let str = {}
      let obj = JSON.parse(JSON.stringify(str))

   2.递归

function deepClone(obj){
    015 objClone = Array.isArray(obj) ? [] : {};
    if(obj && typeof obj=== "object"){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                if(obj[key]&&typeof obj[key] ==="object"){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}

var obj1 = {
    name:'zangsan',
    age: 18,
    hobby:{
        motion: new Array('篮球','足球')
    }
}
var obj2 = deepClone(obj1);
console.log(obj1, obj2);

vue部分

Vue的优点

  • 低耦合(结构分离):view和model可以相互独立
  • 前后端分离
  • 组件化:保留了 react 的优点,实现了 html 的封装和重用,在构建单页面应用方面有着独特的优势;
  • 双向数据绑定:保留了 angular 的特点,在数据操作方面更为简单;
  • 虚拟DOM:dom 操作是非常耗费性能的, 不再使用原生的 dom 操作节点,极大解放 dom 操作,但具体操作的还是 dom 不过是换了另一种方式;
  • 运行速度更快:相比较于 react 而言,同样是操作虚拟 dom ,就性能而言, vue 存在很大的优势。

MVC和MVVM

MVC:

框架:Angular

Model:数据层(data),负责保存应用数据,与后端数据进行同步

View:视图层,负责视图展示,将Model的数据渲染出来

Controller:控制器,负责业务逻辑,根据用户行为对Model数据进行修改

MVC的思想:Controller里面把Model的数据赋值给View。

MVC的特点:实现关注点分离,即应用程序中的数据模型与业务和展示逻辑解耦。就是将模型和视图之间实现代码分离,松散耦合,使之成为一个更容易开发、维护和测试的客户端应用程序。

MVC的优点

  • 耦合度低,视图层和业务层分离
  • 重用度高
  • 生命周期成本低
  • 可维护性高
  • 部署快

MVC的缺点

  • 不适合小型项目的开发
  • 视图与控制器间的过于紧密的连接,视图与控制器是相互分离,但却是联系紧密的部件,妨碍了他们的独立重用
  • 降低了视图对模型数据的访问,依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。
  • MVC的应用:主要用于中大型项目的分层开发。

MVVM:

框架:vue

Model:数据层

View:视图层

ViewModel:数据模型,视图和数据之间的转换

MVVM的特点: 在MVVM的框架下,视图和模型是不能直接通信的,它们通过ViewModal来通信,ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。并且MVVM中的View 和 ViewModel可以互相通信。

MVVM的优点

  • 低耦合(结构分离)view和model可以相互独立
  • 前后端分离,开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xml代码。
  • 组件化开发
  • 双向数据绑定,它实现了View和Model的自动同步,当Model的属性改变时,不需要手动操作Dom元素,来改变View的显示,而是改变属性后该属性对应View层显示会自动改变
  • 可测试,界面向来是比较难于测试的,而现在测试可以针对ViewModel来写
  • MVVM适用场景: 适合数据驱动的场景,数据操作比较多的场景

虚拟DOM和真实DOM

  • 虚拟dom是object类型的对象
  • 虚拟dom属性比较少,真实dom属性比较多,因为虚拟dom是内部使用,不需要真实dom那么多属性
  • 虚拟dom最终转成真实dom渲染在页面

vue全家桶

vue-cli、vuex、vue-router、axios

做过哪些Vue的性能优化?

  • v-if和v-for不能连用
  • key保证唯一
  • 防抖、节流
  • 第三方模块按需导入
  • 长列表动态加载
  • 图片懒加载

vue的自定义指令

概念:自定义指令就是一种有效的补充和扩展,不仅可用于定义任何的DOM操作,并且是可复用

添加自定义指令的两种方式:

  • 全局指令: 通过 Vue.directive() 函数注册一个全局的指令。
  • 局部指令:通过组件的 directives 属性,对该组件添加一个局部的指令。

什么是 vue 生命周期?有什么作用?

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做 生命周期钩子 的函数,这给了用户在不同阶段添加自己的代码的机会。

生命周期

创建前后---挂载前后---更新前后---销毁前后

beforeCreate:在实例部分(事件/⽣命周期)初始化完成之后调⽤。
created:在完成外部的注⼊/双向的绑定等的初始化之后调⽤。
beforeMount:在页⾯渲染之前执⾏。
mounted:dom 元素在挂载到页⾯之后执⾏。
beforeUpdate:数据改变,还没重新渲染之前执⾏。
updated:渲染数据完成之后执⾏。
执⾏销毁需要调⽤:vm.$destroy()
beforeDestroy:实例销毁之前执⾏。
destroyed:实例销毁之后执⾏。

组件生命周期:

actived:创建

deactived:销毁

vue获取数据在一般在哪个周期函数

  • created
  • beforeMount
  • mounted

vue中父子组件的生命周期

渲染的过程

  • 父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted

子组件更新过程

  • 父beforeUpdate->子beforeUpdate->子updated->父updated

父组件更新过程

  • 父beforeUpdate->父updated

销毁过程

  • 父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

Vue 生命周期中 created 和 mounted 有什么区别?

created(创建后):HTML没有渲染出来,不能直接操作dom节点;

mounted(挂载后):HTML已渲染,可以直接操作dom节点。

如何让CSS只在当前组件中起作用?

scoped

如何获取dom?

给dom元素加ref=‘refname’,然后通过this.$refs.refname进行获取dom元素

v-on可以监听多个方法吗?

可以,比如 v-on=“onclick,onbure”

v-if和v-for为什么不能同时使用?

Vue2:v-for的优先级是高于v-if的,如果作用在同一元素上,输出的渲染函数中可以看除会先执行循环再判断条件,哪怕只渲染列表中一小部分元素,也得在每次重渲染的时候遍历整个列表,这会造成性能的浪费

Vue3:v-if的优先级时高于v-for的,因此v-if执行时要调用的变量可能还不存在,会导致报错。

Vue兄弟组件通信

方法1:

通过父组件媒介,从组件1传给父组件,再从父组件传给组件2

方法2:

组件1

//发送方
methods: {
    submit() {
      this.$bus.$emit("name", this.value);
    },
  },

组件2

//接收方
mounted() {
    this.$bus.$on("name", (value) => {
      this.value = value;
    });
 },

Vue 中 keep-alive 的作用是什么?

组件缓存,用于那些频繁切换的页面,减少因页面频繁切换;组件不断的创建和销毁导致损耗性能的情况;

vue2.0和vue3.0区别?

更小:vue2对象编程,vue3是函数式编程,更利于代码的压缩

底层功能:渲染方式,数据监听,双向绑定,生命周期

数据双向绑定:vue2 用es5的发布订阅模式实现(defineProperty),vue3用了es6 的 Proxy对数据代理;

vue3.0可以在安装脚手架同时提前安装好一些项目开发必备的插件,并且3.0提供了可视化创建脚手架,可以更加方便的对插件和依赖进行管理和配置

vue3还新增了一些内置组件和方法,比如vue3可以默认进行懒观察,使用Function-based API,setup函数,对与插件或对象的一个按需引入,Computed Value ,新加入了 TypeScript 以及 PWA 的支持等等…
这里着重说一下vue3的一个按需引入

Vue2.x中new出的实例对象,所有的东西都在这个vue对象上,这样其实无论你用到还是没用到,都会跑一变,这样不仅提高了性能消耗,也无疑增加了用户加载时间。
而vue3.0中可以用ES module imports按需引入,如:keep-alive内置组件、v-model指令,等等,不仅我们开发起来更加的便捷,减少了内存消耗,也同时减少了用户加载时间,优化用户体验。

Vue 中 V-bind 和 V-model 有什么区别?

v-model:双向绑定,基本上用在表单元素上;

v-bind:单向绑定,绑定数据和属性以及表达式,数据只能从data流向页面

Vue中v-show和v-if有什么区别?

同:都是用于元素的显示和隐藏

不同:

v-show:CSS属性(display)实现显示还是隐藏

v-if:操作dom元素,消耗更高

Vue路由有哪些模式 

1.原理不同。
hash模式的实现原理是通过监听Change事件来实现的。history模式是通过调用 history.pushState方法(或者replaceState) 并且 监听popstate事件来实现的。history.pushState会追加历史记录,并更换地址栏地址信息,但是页面不会刷新,需要手动调用地址变化之后的处理函数,并在处理函数内部决定跳转逻辑;监听popstate事件是为了响应浏览器的前进后退功能。

2.表现不同。
hash模式会在地址栏中有#号,而history模式没有;同时由于history模式的实现原理用到H5的新特性,所以它对浏览器的兼容性有要求(IE >= 10)。

3.history模式特点
history模式开发的SPA项目,需要服务器端做额外的配置,否则会出现刷新白屏(链接分享失效)。原因是页面刷新时,浏览器会向服务器真的发出对这个地址的请求,而这个文件资源又不存在,所以就报404。处理方式就由后端做一个保底映射:所有的请求全部拦截到index.html上。

插槽

插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码

插槽分别有三种:具名插槽、匿名插槽、作用域插槽

具名插槽:子组件在slot插槽name属性自定义名称,父组件通过slot属性填充插槽的位置

//子组件


//父组件

我是header部分

作用域插槽:子组件的属性通过slot插槽传给父组件使用

子组件:把user对象通过slot插槽传给父组件



父组件:模板字符串template中v-slot指定接收

vue双向绑定 

vue中采用mvvm的模式,view层与model层两者进行关联,任何一方的变化都会让另外一方受到影响

vue双向绑定的原理

vue中内部采用了发布-订阅模式。内部结合了Object.defineProperty这个ES5的新特性,对vue传入的数据进行了相应的数据拦截,为其动态添加get与set方法。当数据变化的时候,就会触发对应的set方法,当set方法触发完成的时候,内部会进一步触发watcher,当数据改变了,接着进行虚拟dom对比,执行render,后续视图更新操作完毕

Vue中key的作用是什么

key是v-for渲染列表时的节点标识,当列表发生变化,Vue就会基于key的值重新排列元素顺序,并移除key不存在的元素,提升运行效率

常用的事件修饰符

.stop 阻止事件冒泡

.self 仅绑定元素自身可触发

.prevent 阻止默认行为

.once 只触发一次

Vue常用的指令有哪些

v-once:只会执行一次

v-show:元素隐藏,通过display属性

v-if:元素隐藏

v-for:遍历数组

v-text:渲染字符串

v-html:渲染html

v-model:数据双向绑定

Vue中computed和watch有什么区别

computed:

  1. 支持缓存,只有依赖数据发生变化时,就会执行计算函数;
  2. 不支持异步操作;
  3. 计算属性的函数中都有一个 get(默认具有,获取计算属性)和 set(手动添加,设置计算属性)方法;
  4. 计算属性是自动监听依赖值的变化,从而动态返回内容。
  5. 多条数据影响一条数据时使用计算属性,使用场景购物车。

watch:

  1. 不支持缓存,只要数据发生变化,就会执行侦听函数;
  2. 支持异步操作;
  3. 侦听属性的值可以是一个对象,接收 handler 回调,deep,immediate 三个属性;
  4. 监听的值变化时,可以触发一个回调,做一些其他事情。
  5. 一条数据更改,影响多条数据时,使用watch,使用场景搜索框。

Vue中的data为什么是函数?

data可以是函数,也可以是对象;

对象,属性存储的地址是同个位置,组件之间的data属性会相互影响;

函数,属性都在函数的作用域内,相互独立,不会影响

vuex 是什么?怎么使用?哪些功能场景使用它?

vue框架中状态管理。在 main.js 引入 store,注入。
新建了一个目录store.js,…export。
场景有:单页应用中,组件之间的状态。音乐播放、登陆状态、加入购物车


vuex有哪几种属性?

state

  • 存储数据的
  • 获取数据最好推荐使用getters
  • 硬要使用的话可以用MapState, 先引用,放在compute中...mapState(['方法名','方法名'])

getters

  • 获取数据的
  • this.$store.getters.xxx
  • 也可使用mapGetters 先引用,放在compute中,...mapGetters(['方法名','方法名'])

mutations

  • 同步操作数据的
  • this.$store.commit(“方法名”,数据)
  • 也可使用mapMutations ,使用方法和以上一样

actions

  • 异步操作数据的
  • this.$store.dispatch(“方法名”,数据)
  • 也可使用mapActions ,使用方法和以上一样

modules

  • 板块,里面可以放多个vuex

页面刷新后vuex的state数据丢失怎么解决?

就是放在localStorage 或者就是sessionStorage ,或者借用辅助插vuex-persistedstate

$router和$route的区别

  • $router 是“路由实例”对象包括了路由的跳转方法,钩子函数等。
  • $route 是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。

vue路由的方法

#有两种,分别是声明式和编程式

用router-link进行跳转叫声明式

用js方式进行跳转叫编程式,this.$router.push()

vue路由传参

路由传参有两种query和params

区别:

query:   1.参数在url可以看见

             2.页面刷新参数还在

             3.可以使用path或name属性跳转传参

params:1.参数不可见

             2.页面刷新参数不见

             3.必须使用name属性跳转

vue导航卫士

router.beforeEach((to, from, next) => {}) //路由跳转之前触发

router.afterEach((to, from, next) => {}) //路由跳转之后触发

to:要导航到的目标Route对象,简单点说就是到哪里去。

form:当前离开的对象,简单点说就是从哪儿来。

next:必须调用此函数才能解决钩子

uniapp部分

跨端适配—条件编译

//template


我是微信小程序




我是 app 


//js
// #ifndef H5
// 表示只有 h5 不使用这个 api
uni.createAnimation(OBJECT)
// #endif

//css
/* #ifdef  MP-WEIXIN */
/*  只在小程序中生效  */
.header {
	color:red
}
/*  #endif  */

 uniapp的配置文件、入口文件、主组件、页面管理部分

	pages.json	配置文件
	main.js		入口文件
	App.vue		主组件
	pages		页面管理部分
    manifest.json 应用的配置文件
    package.json  配置扩展

uni-app的生命周期

  • onLoad                      监听页面加载
  • onShow                     监听页面显示
  • onHide                       监听页面隐藏
  • onUnload                   监听页面卸载
  • onPullDownRefresh   监听下拉刷新
  • onReachBottom         监听滚动到底部
  • onPageScroll              监听页面滚动
  • onShareAppMessage 监听用户点击右上角分享
  • onAddToFavorites       监听用户点击右上角收藏
  • onShareTimeline         监听用户点击右上角转发到朋友圈
  • onTabItemTap             点击 tab 时触发

 路由和页面跳转

uni.navigateTo  保留当前页面,跳转到应用内的某个页面

uni.redirectTo  关闭当前页面,跳转到应用内的某个页面

uni.reLaunch    关闭所有页面,打开到应用内的某个页面

uni.switchTab   跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面

uni.navigateBack  关闭当前页面,返回上一页面或多级页面

axios 

get和post的区别

get:  1、参数可见;

        2、传输数据不超过2-4k;

        3、后退没有影响;

        4、可缓存;

        5、有历史记录

post:  1、参数不可见

          2、后退重新提交

          3、不可缓存;

          4、没有历史记录;

          5、传输数据可以无限大;

服务器返回的code意义

  • 2开头的表示成功
    • 一般见到的就是200
  • 3开头的表示重定向
    • 301永久重定向
    • 302临时重定向
    • 304表示可以在缓存中取数据(协商缓存)
  • 4开头表示客户端错误
    • 401身份未验证
    • 403跨域
    • 404未找到
  • 5开头表示服务端错误
    • 500

 http和https的区别

http是HTTP协议运行在TCP之上。所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。

https是HTTP运行在SSL/TLS之上,SSL/TLS运行在TCP之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。此外客户端可以验证服务器端的身份,如果配置了客户端验证,服务器方也可以验证客户端的身份

同源策略

  • 同源指的是域名、协议、端口号相同

跨域的解决方案

  • JSONP跨域
  • 后端在头部信息里面设置安全域名
  • Node 中间件代理

git的常用命令

git clone '链接'  下载目录

git init 初始化

git pull 更新

git status 查看状态

git add . 提交

git push 把本地仓库推到线上

git commit -m ‘描述’提交到本地仓库

你可能感兴趣的:(前端,css3,javascript)