前言
陆续整理本人在平时面试当中经常会遇到的一些面试题,以及自己的一些个人理解,希望能对大家有帮助
1.值类型和引入类型的区别
- 值类型(简单数据类型)的数据储存在栈区,修改拷贝后的数据对原数据没有影响
- 引入类型(复杂数据类型)的地址储存在栈区,数据存在堆区,修改拷贝后的数据对原数据有影响
2.事件委托
给父元素注册事件,委托给子元素处理,原理是冒泡排序
3.cookie、sessionStorage、localStorage的区别
- sessionStorage:内存存储
- localStorage:硬盘存储
- cookie:每次http请求都会携带cookie,所有cookie只适合保存很小的数据,数据不能超过4k
4.new关键字的四个流程
- 创建一个新对象
- this指向这个新对象
- 对象赋值
- 返回这个对象
5.原型
任何构造函数在被创建的时候,系统都会自动帮我们创建一个与之对应的对象,称之为原型对象
- 访问原型对象:构造函数名.prototype
- proto属性介绍:属于对象,指向实例化这个对象的构造函数对应的原型
- constructor属性介绍:属于原型对象,指向这个原型对应的构造函数 作用:可以得知某个实例对象,到底是由哪一个构造函数生成的
6.构造函数,原型对象和实例对象的三者关系
- 构造函数有一个属性prototype,指向自己的原型对象
- 原型对象有一个属性constructor,指向自己的构造函数
- 实例对象有一个属性__proto__,指向自己的原型对象
7.原型链
每一个对象都有原型,原型本身又是对象,所以原型又有原型,以此类推形成一个链式结构,称为原型链 对象访问原型链中的成员规则:就近原则
当访问一个对象的成员变量时,会首先访问它自身的成员变量,如果有则访问。没有则在原型中寻找,能找到就访问,不能找到则继续往原型的原型中寻找,以此类推,如果找到原型链的顶端还是找不到,则程序报错:xxx is not a function
8.面向对象的三大特性
- 封装:将某个具体功能封装在对象中,只对外部暴露指定的接口,外界在使用的时候,只考虑接口怎么用,不用考虑内部怎么实现
- 继承:一个对象拥有其他对象的属性和方法
- 多态:一个对象在不同情况下的多种状态(java语言使用较多,js语言基本不涉及)
9.instanceof运算符作用
用于检测 构造函数的prototype在不在实例对象的原型链中,通常用于判断数据类型
10.for-of和for-in 区别
- 功能不同
- for-in是遍历数组的下标
- for-of是遍历数组的元素
- 原型不同
- for-in会遍历原型中的属性
- for-of不会遍历原型中的属性
- 数据类型不同
- for-in可以遍历数组和对象
- for-of只能遍历数组
11.this的三种指向
this:谁调用,就指向谁
- 全局函数:this指向window
- 构造函数:this指向new创建出来的对象
- 对象方法:this指向对象(点语法左边的对象就是this,例如obj.eat(),此时this指向obj)
12.call,apply,bind区别
共同点:都可以修改function函数的this
不同点:
1.传参方式不同:call是单个传参,apply是数组/伪数组传参
2.执行机制不同:call和apply会立即执行函数,bind不会立即执行而是返回一个修改this的新函数
13.闭包
什么是闭包:(以下两种回答都可以)
-
闭包是一个访问其他函数内部变量的函数(条件1函数,条件2访问其他函数的内部变量)
-
闭包是 函数 + 上下文引用组合
闭包作用:解决变量污染
14.深拷贝和浅拷贝
-
浅拷贝: 拷贝的是地址 特点:修改拷贝后的数据,原数据也会随之修改
-
深拷贝:拷贝的是数据 特点:修改拷贝后的数据,对原数据没有影响
15.递归
什么是递归:函数内部调用自己 递归场景:深拷贝,遍历DOM树
16.get请求与post请求区别
1.传参方式不同
-
get在url后面拼接(请求行)
-
post在请求体传参
- 大小限制不同
- get有大小限制,不同浏览器大小限制不同。 一般2-5 MB
- post没有大小限制
3.安全性不同
- get参数直接暴露在url,不安全(一般查询类数据都是get)
- post参数在请求体中,更加安全(一般登录注册必须是post)
4.传输速度不同
- get传输速度快
- post传输速度慢
17.HTTP协议组成
HTTP协议组成 : 请求报文 与 响应报文
-
请求报文: 前端发送数据格式
-
响应报文 : 后端响应数据格式
请求报文 : 三个部分组成
-
请求行 : 请求地址 + 请求方法
-
请求头 : 浏览器告诉服务器,我发你的数据是什么格式
-
请求体 : 请求参数
响应报文 : 三个部分组成
1.响应行 : 响应状态码 + 服务器ip地址
2.响应头 : 服务器告诉浏览器,我响应给你的数据是什么格式
3.响应体 : 响应的数据
18.常见状态码
-
2xx : 请求成功
200 : 成功
204 : 用于post请求, 预检请求
-
3xx : 重定向
302 : 重定向(服务器修改浏览器网址)
-
4xx : 前端的问题
400 : 参数错误
404 : 路径错误
401 : 未认证(需要登录的接口,没有登录)
403 : 没有权限(未登录、或账号权限不够)
413 : 文件超出大小限制
-
5xx : 后台问题
500 : 后台崩溃
19.网页输入url到呈现过程
1.DNS解析 : 把域名 解析成 ip 地址
2.TCP连接 : 保证HTTP传输的安全可靠
(1)前端->后端 : 能听到我说话吗 (验证前端 发)
(2)后端->前端 : 我听到了,你能听到我说话吗 (验证后端 收+发)
(3)前端->后端 : 我也能听到你说话 (验证前端 收)
3.HTTP连接 : 请求、处理、响应
(1)浏览器发送请求
(2)服务器处理请求
(3)服务器响应请求
4.服务器响应html,浏览器渲染
(1)解析HTML结构, 生成DOM树
(2)解析CSS样式, 生成样式树
(3)将 DOM树 + 样式树 合并成 渲染树
(4)渲染引擎 绘制 渲染树
(5)呈现页面
20.防抖和节流
1. 函数防抖 : 单位时间内,频繁触发事件,只会触发'最后一次'
- 防抖经典场景 :
输入框输入事件 oninput
减少事件触发频率,提高网页性能
- 函数防抖流程 :
(1)声明全局变量存储定时器id
(2)每一次触发事件之前,清除上一次定时器
(3)开启本次防抖定时器
2. 函数节流 : 单位时间内,频繁触发事件,只会‘触发一次’
-
节流场景: 解决高频事件(滚动条、鼠标移动)
-
节流实现方式
(1) 声明全局开关
(2 )触发事件的时候判断开关
如果判断为 开: 执行事件,并且关闭开关
(3) 开启节流定时器,打开开关.
21.Token工作流程
token是什么 : 认证令牌
token是一串经过加密之后的字符串,相当于是用户一种身份认证令牌。类似于古代的腰牌,现代的工牌。 见到这个牌子,服务器才知道你是自己人,才会把数据响应给你
token应用 : 免登录
有了token之后,用户就不需要每一次访问网站都要先输入账号密码,才能拿到数据了。 而是只需要登录一次,以后拿着token,服务器就知道你是哪一个用户了。
token工作流程分为三个步骤
第一步: 用户发送登录请求
第二步:服务器响应token,客户端将token存储在本地
第三步: 登录之后的所有请求,用户都需要在请求头中发送token
22.为什么post请求会发送两次请求
1.第一次请求为options预检请求,状态码为:204
作用:主要有两个,回答任意一个。或两个都回答。 都可以
作用1: 询问服务器是否支持修改的请求头,如果服务器支持,则在第二次中发送真正的请求
作用2: 检测服务器是否为同源请求,是否支持跨域
相关资料:www.ruanyifeng.com/blog/2016/0…
2.第二次为真正的post请求
23.说说几个前端web优化方案
1.减少HTTP请求数
-
这是必须要放在第一个回答的,因为这是优化web最优方案
-
具体示例 : 精灵图、多个文件合并成一个
-
精灵图适用场景 : (1)图片不经常更换的,比如按钮图标 (2)图片不能太大
2.资源压缩
-
就是一般我们第三方包有一个min版本,就是通过压缩文件体积来优化web
-
具体示例 :响应min文件
3.合理利用浏览器缓存
-
某些接口的数据是固定的,服务器就没有必要每一次都响应数据。可以让浏览器进行缓存。
-
具体示例:例如省市县数据, 这种数据一般不会变化
24.nodejs模块加载原理
-
require会先去判断是否是路径,如果是路径的话,会认定为自定义模块直接引入这个js文件
-
如果判断是文件名,会先在node_module文件夹当中去查找同名文件夹,然后导入文件夹下面的index文件, 如果当前文件夹没有找到,会根据就近原则依次向上级文件夹查找
-
如果找到根目录仍然没找到,最后会去node的核心模块去查找,如果仍然还是没找到,程序会直接报错
25.promise
- promise是什么?
Promise是ES6新出的一个构造函数 ,用来解决回调地狱
- promise原理
-
promise对象有三种状态
- 进行中(pending)
- 已成功(fulfilled)
- 已失败(rejected)
-
promise状态只会有两种变化
- 从pending变为fulfilled
- 从pending变为rejected
-
注意点: promise对象只要声明, 里面的异步会立即执行。
- 一般不会在promise内部去处理异步结果,而是调用resolve()或reject()
- promise解决回调地狱原理:
-
promise并不能改变异步的顺序(异步是无序的,编译器决定无法改变)。 promise本质是控制异步结果的顺序
-
在上一个promise的then方法中, 返回下一个promise实例,依次形成链式调用
-
- async函数 : 相当于promise高级写法
1.使用async修饰函数: async function 函数名(){ }
- 作用:让函数内部可以使用await关键字
2.函数内部使用异步函数: const res = await promise实例
- 作用 : 会执行promise的then方法, await方法返回值就是then里面的res
- 只有上面的await执行完毕了,才会执行下一个await
26.事件循环Event Loop
-
事件循环又叫事件队列,是浏览器解析执行js代码的一种运行机制(执行规则)
js代码主要分为两大类: 同步代码、异步代码
异步代码又分为:微任务与宏任务
-
事件循环执行机制
-
解析第一个script标签,进入第一次事件循环
-
从上往下依次 '解析' 代码, 判断代码是同步还是异步
-
如果是同步,立即 '执行'
-
如果是异步,不立即执行。 微任务就会放入微任务队列, 宏任务就会放入宏任务队列中。
-
当前队列所有的同步都执行完毕,开始执行异步队列。
-
先执行微任务,然后执行宏任务。
-
当前宏任务队列清除后,按照以上规则解析下一个宏任务。以此类推,形成一次事件循环。
27.webpack
-
什么是webpack?
静态模块打包工具
-
webpack作用
分析、压缩、打包代码
-
webpack好处
-
减少文件体积、减少文件数量
-
提高网页加载速度
-
-
webpack使用基本流程
1.初始化npm : npm init -y
2.使用开发依赖下载webpack : npm i webpack webpack-cli -D
3.在项目src文件夹中新建index.js文件
4.项目根目录下执行打包命令: npx webpack
-
默认入口文件和出口文件 output: 出口文件(对象类型)
-
path : 设置出口文件夹(必须是绝对路径)
- 默认值:
${__dirname}/dist
- 默认值:
-
filename: 设置出口js文件名 (相对于path路径)
- 默认值:
main.js
- 默认值:
entry : 入口文件
默认值(相当于项目根目录): ./src/index.js
- npm run build 原理
1.在package.json里面检查是否有自定义build命令
2.检查到build命令后会真正执行webpack命令
3.读取配置文件,有配置文件的情况下,会根据配置文件得到配置参数
4.没有配置文件的情况下会执行默认的配置文件
5.根据配置文件里面的entry找到入口文件
6.分析计算依赖关系图,编译各个模块的文件
7.输出在配置文件中的出口文件
- 什么是loader,什么是Plugin loader直译为"加载器"。webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。 所以loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。
说人话: loader就是用于解析文件的
例如:css-loader 、style-loader、image-loader
Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 webpack 提供的 API 改变输出结果。
说人话:插件就是拓展功能的
例如:html-webpack-plugin,
个人见解: 广义来说,loader属于插件的一种。
插件范围很广 : 只要不是webapck原生的功能,都可以理解为插件 loader : 一种特殊的插件,主要是用在webpack编译环节,帮我们编译各种文件的