web前端面试收集

373 阅读15分钟

腾讯面试流程(一面):

开始先半小时做笔试题,一般是一些常规js方法的使用,一道promise打印问题,一道实际问题解决的方法。 笔试完面试官会看看你做的怎么样,并会询问你这道题的结果怎么来的,我被问道的是promise的打印,回答分析后他会给你分析对错,以及这道题的考点,回答完成后开始正式面试。 先自我介绍,项目经历

  1. 你之前做的项目中有什么亮点,回答一个以后还会问你还有么)
  2. 说一下变量提升吧,我想要一个块级作用域怎么做
  3. 你知道闭包么?会产生什么问题?怎么解决?

一个函数返回另一个函数,我认为有两个作用第一个作用就是保护,另一个作用就是保存,保护呢就是函数之前会形成一个私有作用域,不受外部干扰,它很适合模块儿开发,我们在ES6model还是commonjs,都能看到闭包的影子,第二个呢就是保存,当一个函数返回另一个引流数据类型的时候呢,被外界所接受了就会形成不销毁的作用域他就会一直存在堆内存的浏览器里面,它很容易造成内存泄露,什么内存泄露呢?内存泄露其实就是浏览器无法回收代码的内存比如说一个对象或者一个数组这种。所有的闭包都会导致内存泄露吗?就看他有没有被外界所接受了,垃圾回收机制就那些算法?其实他会有一个新有一个旧现在的话都是标记清楚标记整理和引用计数了

  1. new做了什么,具体点说
  2. 怎么改变this的指向,以及他们几个的区别
  3. 你知道跨域么?产生的原因以及解决方式 (跨域是是因为浏览器的限制,是浏览器的一种安全机制,服务端之间是不存在跨域的。 所谓同源指的是两个页面具有相同的协议、主机和端口,三者有任一不相同即会产生跨域)
  4. 你知道的web安全有哪些
  5. 问点简单的吧:
  6. 怎么实现继承
  7. 知道Class么
  8. vue的响应式原理,它是怎么知道数据变化的呢
  9. 你遇到问题是怎么解决的
  10. 你最近有在学什么新东西么
  11. 我这边就没什么问题了,看你有什么想问的么? 在你回答的过程中,面试官会问,你确定么?我记得好像不是这样?来提示你有问题
  12. vue路由的hash模式和history模式区别
  1.hash的路由地址有#,history模式没有
  2.在做回车刷新的时候,hash模式会加载对应页面,history会报错404
  3.hash模式支持低版本浏览器,history不支持,因为是H5新增的API
  4.hash不会重新加载页面,单页面应用必备
  5.history有历史记录,H5新增了pushStatue和replaceState()去修改历史记录,宾辉立刻发送请求
  6.history需要后台配置

61f93c80e7dbc38b695508efde52649.png 16.路由拦截是怎么实现的

17.说一下vue的动态路由。

18.如何解决刷新后二次加载路由?

19.vuex刷新数据会丢失吗? 怎么解决?

20.了解diff算法和虚拟DOM吗?

21.vue的双向数据绑定原理是什么?

Vue数据双向绑定原理是通过数据劫持结合发布者-订阅者模式的方式来实现的,首先是对数据进行监听,然后当监听的属性发生变化时则告诉订阅者是否要更新,若更新就会执行对应的更新函数从而更新视图。 Object.defineProperty这个API来实现

24001fa4978b9f594e62f540765ddc8.png

1fd0de8719445bd7f5e35d42ce72867.png

new Set 集体去重:
let a = [{a: 1},{b:1}]
let b = [{a: 1},{b:1}]
let c = a.concat(b)
c = [...new Set(c.map(t=>JSON.stringify(t)))].map(v=>JSON.parse(v))

new map 固定单个去重比如id
let a = [{id:1,name:'张三'},{id: 1, name: '李四'},{ id: 2,name: '王五'}]
let res = new Map()
a=a.filter((key) => !res.has(key['id']) && res.set(key['id'], 1))
  1. 什么是伪类和伪元素
    伪类: 以冒号:开头 用于选择处于特定状态的元素
    伪元素: 以双冒号:: 开头,用于在文档中插入虚构的元素
    
    动态伪类:`:visited``:focus``:hover`等
    状态伪类:`:disabled``:empty``:required` 等
    结构伪类:`:first-child``:nth-of-type`等
    其他伪类:`:target``:lang``:not()`等

## 常用的伪类 :active :focus(获取焦点) :hover :link :net-child() first-child()

## 伪元素

**伪元素** **选中或创建出来的元素** **兼容性**

与伪类相比,[伪元素](https://link.juejin.cn?target=https%3A%2F%2Fdrafts.csswg.org%2Fcss-pseudo%2F "https://link.juejin.cn?target=https%3A%2F%2Fdrafts.csswg.org%2Fcss-pseudo%2F")就少很多了,常用的如下:

| **伪元素**                  | **选中或创建出来的元素**                | **兼容性**                                   |
| ------------------------ | ----------------------------- | ----------------------------------------- |
| `::first-letter`         | 选中块状元素中的首字母                   |                                           |
| `::first-line`           | 选中首行                          |                                           |
| `::before`               | 在之前创建一个不在文档树中的元素              |                                           |
| `::after`                | 在之后创建一个不在文档树中的元素              |                                           |
| `::placeholder`          | 选中表单元素的占位文本                   |                                           |
| `::file-selector-button` | 选中类型为 file 的 input 里面的 button |                                           |
| `::selection`            | 选中被用户高亮的部分                    | 部分浏览器支持(可能需要加前缀,例如 `:webkit-`或 `:-moz-`等) |
| `::backdrop`             | 选中视觉聚焦元素后面的背景元素               | 部分浏览器支持(可能需要加前缀,例如 `:webkit-`或 `:-moz-`等) |
| `::marker`               | 选中 list 的 marker              | 部分浏览器支持(可能需要加前缀,例如 `:webkit-`或 `:-moz-`等) |

注意:创建 `::before`和 `::after`的元素时,必须要设置 content 属性,否则就不存在了。另外宿主元素的 position 别忘记设置成 relative 或 absolute 了,否则布局可能会乱掉。

www.cnblogs.com/yaya-003/p/… 改变this的指向案例

  1. 什么是原型链

原型链本质上就是一个列表当你new函数的时候他会返回一个实例,然后这个实例会有一个proto属性指向他的原型同时这fucntion会指向这个原型,当你访问这个实例上的属性的时候如果他没有的话会顺着他这个proto指向原型,如果原型上没有的话他会顺着proto在找原型的原型一直找到大的object的实例如果找到的话他会把这个值付给你取的这个变量。原型链我认为这个是js特有的所有对象都可以共享原型上面的方法这个在java 和 python都没有他的优势就是能够节省内存非常方便,像我们引用场景比如jquery

我们创建的每个函数都有一个==prototype==(原型)属性,prototype属性指向原型对象。通过该函数创建的实例对象会共享原型对象上的所有属性和方法。

    function Person(){ 
    
    } 
    Person.prototype.name = 'test';
    Person.prototype.age = 25;
    Person.prototype.sayName = function(){ console.log(this.name); } 
    const person1 = new Person();
    person1.sayName(); 

image.png 但是我们可以发现Object.prototype也有自己的__proto__ 但是却指向的是null,null为原型链的终点

其他公司面试:

函数工厂和构造函数

函数工厂

  1. 它是一个函数。
  2. 它用来创建对象。
  3. 它像工厂一样,“生产”出来的函数都是“标准件”(拥有同样的属性)
function person(firstName, lastName, age){
  const person = {}
  person.firstName = firstName;
  person.lastName = lastName;
  person.age = age;
  return person;
}

const mike = person('mike', 'grand', 23);

使用构造函数

注意:在JavaScript中,这些构造函数也被称为 constructor,因为它们用于创建对象

function Person(firstName, lastName, age) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.age = age;
}
const mike = new Person('mike', 'grand', 23);

通过代码示例我们可以很容易知道它俩的区别如下:

  1. 工厂函数的使用不借助 new,而构造函数需要
  2. 工厂函数没有使用 this
  3. 工厂函数需要 明确 返回新对象,而构造函数不需要

究其根本,造成它俩的差异的根本原因是 newthis 这俩东西,因此我们需要搞清楚这俩的运行原理,才能真正明白两种模式的区别 \

什么是 BFC,有什么作用,如何形成 BFC**

BFC 是一个完全独立的空间(布局环境),让空间里的子元素不会影响到外面的布局

列举几个触发 BFC 的 CSS 属性:

  • overflow: hidden
  • display: inline-block
  • position: absolute
  • position: fixed
  • display: table-cell
  • display: flex

防抖节流

  • 防抖:触发事件,一段时间之后才会执行回调函数,如果在这段时间内重复触发,那么计时器会重新计时;
  • 节流:触发事件一段时间之内只会执行一次回调函数;

js 几种情况为false 1: false
2: null
3:undefined
4:"" 空字符串
5:0
6:NaN

new关键字的执行过程(4步)

1、 创建一个空对象object,let obj = new Object()---创建对象新对象,就是指在栈内新建了一个obj,这个obj实际上是指的堆中对应的一个地址。

2、 设置[原型链]这里所说原型链,就是设置新建对象obj的隐式原型即_proto_属性指向构造函数Person的显示原型prototype对象(让this指向该空对象)

3、 执行构造函数里面的代码 给这个新对象添加属性和方法

4、返回这个新对象

XMLHttpRequest.status;XMLHttpRequest.statusText-即对应的状态提示信息

  • 200:访问正常√
  • 301:永久移动
  • 302:暂时移动
  • 304:未修改--即协商缓存击中√
  • 307:暂时重定向
  • 401:未授权
  • 403:禁止访问
  • 404:未找到指定网址
  • 500:服务器端发生错误

前端跨域

反向代理

// vue 的开发服务器代理配置
// vue.config.js
module.exports = {
  devServer: { // 配置开发服务器
    proxy: { // 配置代理
      "/api": { // 若请求路径以 /api 开头
        target: "http://dev.taobao.com", // 将其转发到 http://dev.taobao.com
      },
    },
  },
};

JSONP

JSONP有着明显的缺点,即其只能支持GET请求

CORS

postMessage

https-proxy

nginx

websocket location.hash

call,apply,bind的区别

  • 它们都是用于改变this的指向的,主要区别在于传入的参数和返回值;
  • call(context,arg1,arg2...):第一个参数是传入的this对象,后面的参数为函数的形参;
  • apply(context,array):第一个参数是传入的this对象,第二个接收一个数组或者伪数组;
  • bind(context,arg1,arg2...):参数和call相同,但会返回一个改变了this指向的新函数;

let const var的区别

  • 块级作用域

  • 变量提升:var存在变量提升,let和const不存在变量提升,即在变量只能在声明之后使用,否在会报错

  • 重复声明:var声明变量时,可以重复声明变量,后声明的同名变量会覆盖之前声明的遍历。const和let不允许重复声明变量。

  • 暂时性死区:在使用let、const命令声明变量之前,该变量都是不可用的。这在语法上,称为暂时性死区。使用var声明的变量不存在暂时性死区。

扁平数据结构转Tree

js数据类型 栈 堆

  • 栈:原始数据类型(Undefined、Null、Boolean、Number、String)
  • 堆:引用数据类型(对象、数组和函数)

 数据类型检测

  • typeof:其中数组、对象、null都会被判断为object,其他判断都正确(返回字符串)

  • instanceof:可以正确判断对象的类型,其内部运行机制是判断在其原型链中能否找到该类型的原型(返回boolean)

  • Object.prototype.toString.call():使用 Object 对象的原型方法 toString 来判断

什么是虚拟 dom

Virtual DOMDOM 节点在 JavaScript 中的一种抽象数据结构,之所以需要虚拟 DOM,是因为浏览器中操作 DOM 的代价比较昂贵,频繁操作 DOM 会产生性能问题。

虚拟 DOM 的作用是在每一次响应式数据发生变化引起页面重渲染时,Vue 对比更新前后的虚拟 DOM,匹配找出尽可能少的需要更新的真实 DOM,从而达到提升性能的目的。

虚拟 DOM 的实现原理主要包括以下 3 部分:

  • JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;
  • diff 算法 — 比较两棵虚拟 DOM 树的差异;
  • pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM

vue 首屏渲染优化有哪些

  • 图片压缩/懒加载
  • 禁止生成 .map 文件
  • 路由懒加载
  • cdn 引入公共库
  • 开启 GZIP 压缩

MVVM

如今主流的web框架基本都采用的是MVVM模式,为什么放弃了MVC模式,转而投向了MVVM模式呢。在之前的MVC中我们提到一个控制器对应一个视图,控制器用状态机进行管理,这里就存在一个问题,如果项目足够大的时候,状态机的代码量就变得非常臃肿,难以维护。还有一个就是性能问题,在MVC中我们大量的操作了DOM,而大量操作DOM会让页面渲染性能降低,加载速度变慢,影响用户体验。最后就是当Model频繁变化的时候,开发者就主动更新View,那么数据的维护就变得困难。世界是懒人创造的,为了减小工作量,节约时间,一个更适合前端开发的架构模式就显得非常重要。这时候MVVM模式在前端中的应用就应运而生。 MVVM让用户界面和逻辑分离更加清晰。下面是MVVM的示意图,可以看到它由Model、ViewModel、View这三个部分组成。

image.png

前端面试重要笔记

js循环机制

js 是一门单线程上下级语言,分为同步和异步任务,异步任务分为宏任务和微任务, 举个荔枝比如我去银行办理业务,都需要领号排队,银行柜员就相当于一个 js 线程, 客户排队相当于同步任务队列,每个人相当于柜员的一个个任务,这个时候我电话 响了有急事需要打半个小时电话,柜员看见这种情况会叫下一个人来办理,这个时 候我就被分到了异步任务队列,等前面的人办理好业务之后柜员把我叫过去办理我 的业务,这是就是同步队列中的任务执行完了,主线程会处理异步队列的任务 比如

    setTimeout(function(){
    console.log(t1)
    },0)

    new Promise(function(resolve){
        console.log(p1)
        resolve()
    }).then(funciton(){
        console.log(p2)
    })
    console.log(2)

第一步建立执行上下,进入执行栈开始执行代码所以打印 1 第二步往下执行会遇到定时器,定时器属于宏任务将回调函数放入宏任务队列,等待执行 第三步有个 Promise 参数中的 P1 是同步执行的 其次是因为 Promise 是 microtasks,会在同步任务执行完后会去清空 microtasks queues, 最后清空完微任务再去宏任务队列取值。,resolve 后.then 会把其内部 的回调放入微任务队列等待执行 第四步打印最底层 2,这时,主执行栈清空了,开始寻找任务队列中有没有可执行的微任务发现.then 里面的微任务所以执行 p1,第一次 循环结束 第五步 在开始第二次循环,从宏任务开始,检查宏任务队列是否可有执行的代码,发现有一个定时器里面的 t1 所以打印顺序是 1 2 p1 p2 t1

什么是原型链

原型链有 prototype 和proto 一个是显示原型一个是隐式原型,每个函数或类都有显示原型 prototype, 原型的作用就是给这个构造函数所创建出的每一个实例添加一个统一的方法或者属性,在对象使用属性或 调用方法的时候,会优先在自身的属性中寻找,如果找不到就去隐式原型proto里面依次往上寻找,如果找 不到就返回 null,我们把proto与 prototype 的链条关系称为原型链,js 对象就是通过原型链实现属性的继承 函数够着函数的实例,对象 object 构造函数的实例 还有就是构造函数的 prototype 和其实例的proto是指向同一个地方比如

    function Test(x,y){
        this.x = x 
        this.y = y
    }
    Test.prototype.set = function (){
    console.log(this.x)
    }
    let test2 = new Test(1,2)

    Test.prototype === test2.__proto__
    结果返回true
    原型链的继承test2.set()
    instanceof 作用(A instanceof B)作用:判断B的prototype是否在A的原型链上
    console.log(test2 instanceof Test ) // true

双向绑定响应式原理实现

juejin.cn/post/698910… proxy

v-model.jpg proxy.jpg

渲染机制

渲染步骤

浏览器的渲染机制一般分为以下几个步骤:

  1. 处理 HTML 并构建 DOM 树。
  2. 处理 CSS 构建 CSSOM 树。
  3. 将 DOM 与 CSSOM 合并成一个渲染树
  4. 根据渲染树来布局,计算每个节点的位置。
  5. 调用 GPU 绘制,合成图层,显示在屏幕上

TCP三次握手

重绘和回流

浏览器工作原理

juejin.cn/post/714451…

juejin.cn/post/720480…

DNS查询

客服端向服务器发送请求,服务求接受到请求之后对域名进行DNS解析成IP地址,DNS具有缓存作用,也就是说之前查询过最新的一次就不需要进行DNS查询(记住,DNS 查询只发生在我们第一次访问一个网站时)所以下次访问同一个网址会更快

TCP三次握手

一旦浏览器知道了网站的 IP 地址,将通过TCP三次握手与持有资源的服务器建立连接,它的作用是在传输数据前协商好连接的参数,他们都步骤主要分为三步,电脑(1:你好服务器,能为我打开一个连接吗?(SYNC)2:服务器:好的收到,我也需要你为我打开一个连接(SYNC-ACK),3:好的没问题)最后服务器回复一个ACK信息,双向连接TCP成功之后就会进入TLS协商阶段

TLS协商

TLS协商加密通信,验证服务器

虚拟DOM