1. 原型和原型链,constructor属性
答:原型:原型分为隐式原型和显式原型,每个对象都有一个隐式原型,它指向自己的构造函数的显式原型
原型链:当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下去,也就是我们平时所说的原型链的概念
原型就是一个普通对象,它是为构造函数的实例共享属性和方法;所有实例中引用的原型都是同一个对象
当一个对象调用自身不存在的属性和方法时就会去自己的proto的前辈prototype对象上去找,如果没找到就会去prototype的前辈上去找 直到找到或者返回undefiend 这个查找的过程就是原型链(原型链的根就是Object.prototype)
原型链使用场景:
vue的axios也是放在vue的原型链上,使用 $ axios在文件的任何位置都可以访问这个方法
将对象公共属性放在vue原型上,Vue.prototype.imgBaseUrl = config.imgBaseUrl;
jquery的 $ 就放在jquery的原型链上
数组方法Array.prototype
当需要创建多个具有相似行为和属性的对象时,可以使用原型来定义这些共同的属性和方法。
如何理解constructor属性:所有函数的原型对象都有一个constructor属性指向函数本身
2. 面向对象编程
答:1)面向编程分为面向对象和面向过程
2) 面向过程:照步骤编程 (函数和变量)
3) 面向对象:将需求分析出一个一个的对象,再分析出对象中的属性和方法,最后按照步骤编程(方法和属性)
4) 面向对象四大特征:1、抽象 2、封装 3、继承 4、多态
Namespace命名空间,在对象当中,设置一些具体的属性进行存值
class类:对象的属性和方法的抽象和模板
Object对象:类的一个实例,有类之后可以创建多个对象
Property属性:对象的特征,比如姓名,年龄等名词
Method方法:对象的能力,比如吃,跑等动词,就是对象的方法
Constructor构造函数:可以构造当前类的一些属性
Inheritance继承:一个类可以继承另一个类的特征
Encapsulation封装:一种把数据和相关的方法绑定在一起使用的形式。将对象的属性和方法封装给对象
Abstraction抽象:结合复杂的继承,方法,属性的对象能够模拟现实的模型。父级为抽象类,定义了很多方法和属性,子类可以使用
Polymorphism多态:多意为‘许多’,态意为‘形态’。不同类可以定义相同的方法或属性
3. 构造函数是什么?new操作符做了什么?
答:构造函数得本质是一个普通函数,它得特点是需要通过new关键字来调用,用来创建对象得实例。所有得引用类型,如:[](Array),{}(Object),Function等都是由构造函数实例化而来的,一般首字母大写
new操作符:
1)先创建一个空对象
2)把空对象和构造函数通过原型链进行链接
3)把构造函数的this绑定到新的空对象身上
4)根据构建函数返回的类型判断,如果是值类型则返回对象,如果是引用类型就要返回这个引用类型
4. JS的数据类型?
答:JavaScript 有 5 种简单数据类型:Undefined、Null、Boolean、Number、String和 1 种复杂数据类型Object,以及es6语法新增的Symbol、BigInt数据类型
基础类型(值类型):Undefined,Null,Boolean,Number,String
复杂类型(引用类型):Object,Array,Date,RegExp,Function
1)基本包装类型:Boolean,Number,String
2)单体内置对象:Global,Math
注:普通变量不能调用属性或者方法, 对象可以直接调用属性和方法
基本包装类型:本身是基本类型,但是在执行代码的过程中,如果这种变量调用了属性或者方法,那么这种类型就不再是基本类型了,而是基本包装类型,这种变量页不再是普通变量了,而是基本包装类型对象
为了方便操作基本数据类型,JS还提供了三个特殊的引用类型:String/Number/Boolean
栈:由系统自动分配释放,存放基本类型和复杂类型的地址
堆:存储复杂类型(对象),一般由程序员分配释放, 若程序员不释放,由垃圾回收机制回收,分配方式倒是类似于链表
注:JS中没有堆和栈的概念,此处我们用堆和栈来讲解
5. 作用域和作用域链?
答:作用域:规定变量和函数的可使用范围简称作作用域
作用域链:每个函数都有一个作用域链,查找变量或者函数时,需要从局部作用域到全局作用域依次查找,这些作用域的集合称作作用域链
6.闭包
答:闭包是什么:JS中内层函数可以访问外层函数的变量,是内部私有变量不受外界干扰,起到保护和保存作用
优点:隔离作用域,保护私有变量;有了闭包才有局部变量,否则都是全局变量;让我们可以使用回调,操作其他函数内部;变量长期驻扎在内从中,不会被内存回收机制回收,即延长变量的生命周期
缺点:内层函数引用外层函数变量,内层函数占用内存;如果不是放内存,过多时易引起内存泄漏
引用场景:for循环中的保留索引(i)的操作/防抖节流
7. 内存泄漏、垃圾回收机制
答:内存泄漏:是指不再使用的内存没有及时释放出来,导致该段内存无法被使用就是内存泄漏
垃圾回收机制:就是垃圾收集器按照固定的时间间隔,周期性地寻找哪些不在使用的变量,然受将其清除或者释放内存
8. 防抖和节流
答:节流:n秒内只运行一次,若在能秒内重复出发,只有一次生效
防抖:n秒后在执行该事件,若在n秒内被重复触发,则重新倒计时
都可以通过使用 setTimeout 实现,函数防抖关注一定时间连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次
9. 深拷贝和浅拷贝
答:浅拷贝是指对基本类型(String,Number,Boolean,Null,Undefined)的值拷贝,以及对象类型的地址拷贝
深拷贝是指触雷拷贝基本类型的值,还完全复刻了对象类型;深拷贝常用的方法:递归调用,JSON.stringify + JSON.parse, Object.assgin
浅拷贝和深拷贝的区别:浅拷贝最多拷贝对象的一层,深拷贝可能拷贝对象的多层
10. 跨域的解决方案,前后端分离
答: JSONP跨域,CORS,nginx代理跨域,nodejs中间件代理跨域,WebSocket协议跨域
前端:整个页面显示以及页面的交互逻辑。用ajax和node作为交互。其中node作为中间层
后端:提供api接口,利用redis保存session,与数据库交互
流程:客户端(浏览器)向node请求页面交互;node向后端(这里用java)转发请求。java在发送请求到数据库;java返回结果给node。node返回页面,提供数据
11. 浏览器存储及区别?
答:localStorage:永久保存,以键值对保存,存储空间5M
sessionStorage:关闭页签/浏览器时清空
cookie:随着http请求头发送,通过设置过期时间删除,关闭浏览器失效,存储空间5k
session:保存在服务端
12. 数组常用的方法,判断变量是数组类型,数组扁平化的方法,数组去重
答:改变原数组:push,pop,shift,unshift,sort,splice,reverse
不改变原数组:concat,join,map,forEach,filter,slice
判断是否为数组:使用instanceof关键字或者constructor属性
扁平化:递归concat;split和toString处理
数组去重:ES6语法,new Set() 去重,不支持对象;自定义去重方法;利用数组原型对象splice方法加上双重循环
13. ES6新特性
答:模板字符串,箭头函数,拓展运算符,map和set,promise和proxy,数组方法Array.form(),Array.map(),Array.filter(),Array.forEach(),Array.some(),Array.every()
14.性能优化
答: 1)使用缓存(最重要的一点),cookie与WebStorage
2)减少http请求
3)文件压缩合并:html,js,css压缩。删除一些无用代码:注释
4)图片无损压缩,安卓下可以使用webp格式图片
5)使用字体图标,矢量图svg,雪碧图,base64
6)js文件一般放在页面底部,若放在head里一般要在script标签上加 async 或者 defer 进行异步加载
7)懒加载,预加载
8)服务端渲染(SSR),增强页面的呈现速度,同时能增强SEO,但页面切换不如单页应用(SPA)流畅
9)减少dom操作,规避重绘与回流;更改css属性较多时,以类名的形式操作dom;有复杂动画的DOM,可以考虑使其脱离文档流,从而减少重绘与回流的范围
10)事件的节流与防抖
11)事件委托。利用事件冒泡,通过指定一个事件处理程序,来管理某一类型的所有事件。这样能减少页面消耗的内存
12)启用DNS预解析。遇到网页中的超链接,DNS prefetching从中提取域名并将其解析为IP地址,这些工作在用户浏览网页时,使用最少的CPU和网络在后台进行解析
13) 减少不必要的 DOM 节点,DOM 树的深度越浅,浏览器解析越快
15. Webpack是什么,Webpack打包优化
答:1)路由组件第三方插件按需加载引入require
2)优化loader配置:
优化正则匹配:通过 cacheDirectory 选项开启缓存;通过 include、exclude 来减少被处理的文件
module: {
rules: [
{
test: /\.js$/,
loader:'babel-loader?cacheDirectory',
include: [resolve('src')]
}
]
}
3) 关闭sourceMap文件生成
4)代码压缩,安装插件 npm i -D uglifyjs-webpack-plugin
5)图片吗压缩,安装插件 npm installimage-webpack-loader --save-dev
6)使用CDN优化,vue库等实用链接引入
7)使用gzip压缩,安装compression-webpack-plugin插件
8)懒加载,公共代码抽离,组件化
16.从浏览器输入url后都经历了什么?
答:先进行DNS域名解析,先查看本地hosts文件,查看有没有当前域名对应的ip地址,若有直接发起请求,没有的话会在本地域名服务器去查找,没找到的话就去根服务器查找最后查找到对应的ip地址后把对应规则保存到本地的hosts文件中。
进行http请求,三次握手四次挥手建立断开连接
服务器处理,可能返回304也可能返回200
客户端自上而下执行代码渲染页面
17.TCP协议和HTTP协议
答:TCP协议在建立过程中会进行三次握手四次挥手,三次握手确保双方同步并避免无效连接,四次挥手则正常终止连接或异常终止连接。
HTTP协议是超文本传输协议(Hyper Text Transfer Protocol),是用于从万维网服务器传输超文本到本地浏览器的传送协议。HTTP是一个基于TCP/IP通信协议来传递数据的。
18. HTML5新特性
答:1)拖拽释放(Drag and drop) API
2)语义化更好的内容标签(header,nav,footer,aside,article,section)
3)音频、视频API(audio,video)
4)画布(Canvas) API
5)地理(Geolocation) API
6)本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
7)sessionStorage 的数据在浏览器关闭后自动删除
8)表单控件,calendar、date、time、email、url、search
9)新的技术webworker, websocket, Geolocation
19. 单点登录(SSO single sign on)
答:单点登录:是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分
优缺点:数据用户表统一维护,表被删就有危险
1)登陆验证:用户在登录页面输入用户名和密码,前端将这些凭据通过HTTPS发送到后端认证服务
2)设置Token或Cookie:后端验证成功后,会返回一个Token(JWT常见)或者设置一个认证Cookie(包含用户信息或Token),前端需要保存这个Token或确保浏览器接收了这个Cookie。Set-Cookie: jwt=lll.zzz.xxx; HttpOnly; max-age=980000; domain=.taobao.com
3)自动登录检查:在其他需要登录状态的页面,前端首先检查是否有有效的Token(通常存储在LocalStorage或Cookie中)或通过API请求检查Session状态
4)跨域资源共享(CORS):如果前端和后端部署在不同的域名下,需要处理CORS问题,确保Cookie能够正确传递
5)后端要做统一认证服务:需要有一个中心认证服务器,负责验证用户凭据并发放Token或设置Session
将 Cookie 的 domain 属性设置为父域的域名(主域名),同时将 Cookie 的 path 属性设置为根路径,这样所有的子域应用就都可以访问到这个 Cookie 了
Set-Cookie: jwt=lll.zzz.xxx; HttpOnly; max-age=980000;domain=.taobao.com
Oauth2:是一种系统授权协议,它包含多种授权类型
localstorage跨域:通过 iframe+postMessage() 方式,将同一份 Token 写入到了多个域下的 LocalStorage 中
// 获取 token
var token = result.data.token;
// 动态创建一个不可见的iframe,在iframe中加载一个跨域HTML
var iframe = document.createElement("iframe");
iframe.src = "http://app1.com/localstorage.html";
document.body.append(iframe);
// 使用postMessage()方法将token传递给iframe
setTimeout(function () {
iframe.contentWindow.postMessage(token, "http://app1.com");
}, 4000);
setTimeout(function () {
iframe.remove();
}, 6000);
// 在这个iframe所加载的HTML中绑定一个事件监听器,当事件被触发时,把接收到的 token数据写入localStorage
window.addEventListener('message', function (event) {
localStorage.setItem('token', event.data)
}, false);
20.Token无感刷新
答:简单说就是短token失效时利用长token去获取短token实现无感刷新的效果
1)相应拦截器中监听401时用长token去换短token并存储,refresh token请求失败重新登录
2)重新调用接口,并发刷新 token的情况,解决方法是实例化一个全局变量的promise,如果其他的请求进来就返回这个promise,最后利用promise上的finally将promise赋值null
21. JS执行机制,循环机制,宏观微观任务
答:JS执行机制:
1)首先判断程序中存在任务类型即同步任务、异步任务
2)同步任务会在执行栈中先执行
3)异步任务则会经浏览器处理后,放入任务队列中
4)当同步任务完全执行完后,执行栈会查询任务队列,取出任务队列中罗列好的异步任务来执行
5)重复第4步直到异步也完全执行完毕(事件循环)
事件循环(EventLoop):JS有一个基于事件循环的并发模型,事件循环负责执行代码、收集和处理事件以及执行任务队列中的子任务;即:执行代码和收集异步任务的模型,在执行栈空闲时,不断从任务队列中获取任务、执行任务、再获取任务、再执行的过程,称为事件循环(eventLoop)
为什么设计事件循环:JS是一门单线程语言(某一刻只能执行一行代码),为了让耗时代码不阻塞其他代码运行,设计了事件循环模型
宏任务:setTimeout,setInterval,Ajax,DOM事件
微任务:Promise,async/await(微任务比宏任务执行更早)
22. map和forEach的区别?
答:都是循环遍历数组支持3个参数,map方法返回一个新的数组,数组中的元素为原始数组调用函数处理后的值
23. em和rem的区别?移动端怎么适配?
答:移动端适配使用lib-flexible会和px2rem-loader插件一起使用,目的是将css中的px转换为rem
px,绝对长度单位,像素的计算是针对屏幕的,一个像素(1px)就是屏幕的一个点
em,相对长度单位 ,相对于父元素,一般浏览器默认(1em=16px);
rem,相对长度单位,相对于根元素,即HTML元素,常用于响应式布局
html {
font-size: 100% // 相当于16px
}
div {
width: 3rem // 相当于3*16px = 48px
}
24. 大文件上传,断点续传
答:断点续传主要依赖于HTTP协议中的两个头部字段
Range:用于请求指定资源的某个范围。格式如 Range: bytes=start-end,其中start和end表示字节范围
Content-Range:服务器响应时使用,告诉客户端这个响应包含的资源范围,格式如 Content-Range: bytes start-end/fileSize
HTML5 File API FileList对象,最后用promise.all():
1)初始化检查:首先检查文件是否已部分上传,如果存在之前上传的记录,则获取已上传的字节范围
2)分片处理:将大文件切分为多个小块(将file分片slice),每个分片独立上传
3)发送请求:对每个未上传或未完成的分片,发送带有Range头部的HTTP请求(如PUT或POST),指定要上传的字节范围
4)记录状态:在上传过程中,记录每个分片的上传状态,以便于失败后重试或中断后续传
5)发送合并文件请求:服务端需要支持接收并合并这些分片,确保最终组合成完整的文件
25. Websocket断线心跳
答:心跳检测:通过定期发送小数据包(心跳包)来检查WebSocket连接状态,确认客户端和服务器之间的连接是否仍然活跃
短线重连:在WebSocket连接因网络问题或其他原因意外断开时,自动尝试重新建立连接的过程(断线原因:网络,服务器,防火墙,超时,代码问题)
websocket协议和http协议:WebSocket适用于实时交互的场景,提供持久的连接,支持二进制数据传输,数据传输双向,使用 ws:// 或 wss:// 前缀标识
HTTP 是无状态的,每次请求都需要重新建立连接,每次请求时都是独立的,数据传输单向,使用 http:// 或 https://
26. 循环引用及处理
答:循环引用也称循环依赖,是指两个或多个对象相互引用,形成一个闭环;潜在风险指内存泄漏,性能下降,调试困难;
解决方案:重构代码结构,弱引用,手动解除引用,使用工具库
27. HTTP状态码?304和强缓存,协商缓存
答: 1)304:请求的内容没有修改过,所以服务器返回此响应时,不会返回网页内容,而是使用缓存
2) 401:请求需要身份验证
3) 403:请求的对应资源禁止被访问
4) 404:服务器无法找到对应资源
5) 500:服务器内部错误
6) 503: 服务不可用
强缓存和协商缓存是HTTP缓存机制的两种类型,它们用于减少服务器的负担和提高网页加载速度
强缓存:客户端在没有向服务器发送请求的情况下,直接从本地缓存中获取资源
协商缓存:当强缓存失效时,浏览器会发送请求到服务器,通过ETag或Last-Modified等HTTP响应头与服务器进行验证,以确定资源是否被修改
28. 纯函数
答: 纯函数是这样一种函数,即相同的输入,永远会得到相同的输出的函数,而且没有任何可观察的副作用。 是指那些不依赖于外部状态,也不改变外部状态的函数
JavaScript中一些常见的自带纯函数包括:
1)Math.abs:返回参数的绝对值。
2) Math.min 和 Math.max:分别返回一组数中的最小值和最大值。
3)Math.round:四舍五入。
4)Math.floor 和 Math.ceil:分别向下和向上取整。
5)Array.prototype.slice:不改变原数组,返回一个新数组。
6)String.prototype.toUpperCase 和 String.prototype.toLowerCase:转换字符串的大小写
29.let,var,const
答:let和const具有块级作用域,var不存在块级作用域,可以跨块访问, 不能跨函数访问;const声明对象能修改,不能赋值
if(true){
var a = 0
let b = 0
const c = 0
}
console.log(a);
console.log(b);
console.log(c);
30. 封装判断数据类型的方法
答:typeof操作符返回一个字符串(全小写字母),表示未经计算的操作数的类型;用法可以是typeof operand或typeof(operand);operand一个表示对象或原始值的表达式,其类型将被返回
constructor:对象的constructor属性用于返回创建该对象的函数,也就是我们常说的构造函数
Object.prototype.toString():toString()是Object原型对象上的方法,返回的是代表该对象的字符串
Object.prototype.toString()与Object.toString()的区别:
1)Object.toString()的toString()是Object构造函数上的方法,返回的是对应的函数
2) Object.prototype.toString()的toString()是Object原型对象上的方法,返回的是代表该对象的字符串
31. 虚拟列表的实现和原理
答:虚拟列表大大减少了 DOM 元素的数量,提高了页面性能,让长列表的浏览更加流畅;1)只渲染可见区域; 2)监听滚动; 3)占位填充