自我介绍 & 项目介绍
从用户输入URL到看到页面,这个过程中都发生了什么?
defer & async 的区别
defer与async的区别是:前者要等到整个页面正常渲染结束,才会执行;后者一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。 一句话,defer是“渲染完再执行”,async是“下载完就执行”。 另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。
为什么加载同步script标签中的内容会阻塞文档渲染?
JavaScript是单线程的语言。
单线程意味着什麽呢?意味着一次只能干一件事。这条线程,被JavaScript的执行和浏览器的渲染所共享(也就是说两者用的均是这一条线程,浏览器在某个时间点只能执行JS或渲染UI一个动作)。
CSS盒模型
对BFC语法规范的理解?
BFC(Block Formatting Context)
:块级格式化上下文。可以把它理解成一个独立的区域
另外还有个概念叫IFC
(IFC的line box(线框高度由其包含行内元素中最高的实际高度计算而来(不受到竖直方向的padding/margin影响)。不过,BFC
问得更多。
如何生成BFC
1、overflow: 不为
visible
2、浮动中:不为none
3、定位中:不为static
4、display:flex,inline-block
对“闭包”的理解?
在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
优点:
1、可以从内部函数访问外部函数的作用域中的变量,且访问到的变量长期驻扎在内存中,可供之后使用。
2、避免变量污染全局。
3、把变量存到独立的作用域,作为私有成员存在。
缺点:
1、对内存消耗有负面影响,因内部函数保存了对外部变量的引用,导致无法被垃圾回收,增大内存使用量,所以使用不当会导致内存泄漏。
2、对处理速度具有负面影响。闭包的层级决定了引用的外部变量在查找时经过的作用域长度。
防抖 & 节流 的原理及应用场景?
1、基本概念
防抖:最后一次点击事件后time过后才会执行
节流:持续触发事件时,保证一定time内执行一次
2、分别适合用在什么场景:
防抖:input
节流:resize scroll
滚动条滚动时触发的scroll事件对应的event对象的组成以及各属性的使用场景
①scrollTop/scrollLeft:滚动的距离,一开始默认都是0,往下滚动scrollTop增加,往右scrollLeft增加。
②scrollHeight/scrollWidth:整个页面内容的大小,包括被隐藏的部分。
③clientHeight/clientWidth:视图显示部分的大小
①判断滚动方向,记录之前的scrollTop,scrollLeft,然后触发后进行比较判断
②判断是否到达顶部底部,scrollTop+clientHeight == scrollHeight到达底部
JS的异步处理函数有哪些?(具体阐述,ES5 –> ES6)
setTimeout、setInterval、promise、async await
关于async和await的应用场景题
一个请求接着一个请求:后一个请求依赖前一个请求返回值
请求后的错误处理:使用 try/catch 直接捕获
1 | async function imageCrawler(url) { |
浏览器的异步处理队列?(宏任务和微任务,具体有哪些?)
宏任务:整体代码,setTimeout,setInterval,I/O操作
微任务:new Promise().then ,MutaionObserver(前端的回溯)
Node V10以后和浏览器的行为统一了:先执行完一轮宏任务,再去清空微任务队列.
Vue的双向数据绑定原理
利用Object.defineProperty()数据劫持,结合发布者-订阅者模式实现的。
数据劫持:Object.defineProperty():简单的说 就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值的时候,又用到了它里面的set方法
发布者-订阅者:
前面所讲的数据劫持,其实就是为属性创建了一个观察者对象,监听数据的变化。接下来就是创建发布类和订阅类,如下:
observer,创建数据监听,并为每个属性建立一个发布类。
Dep是发布类,维护与该属性相关的订阅实例,当数据发生更新时,会通知所有的订阅实例。
Watcher是订阅类,注册到所有相关属性的Dep发布类中,接受发布类的数据变更通知,通过回调,实现视图的更新。
Vue的diff算法
diff
算法只对同级节点进行对比
都用key做为唯一标识,进行查找,只有key和标签类型相同时才会复用老节点(遍历前都会根据老的节点构建一个map,方便根据key快速查找)
ps:与react不同的是,react 采用从左向右进行遍历
使用v-for渲染列表是key值的作用?
key的作用让列表中每个item都有一个唯一的识别身份,可以下标值index或者id, 主要是为了vue精准的追踪到每一个元素,高效的更新虚拟DOM。
项目中的商品列表使用懒加载之后,还存在哪些不足?怎么优化?(虚拟列表)
原理:首先将页面上的图片的 src 属性设为空字符串,而图片的真实路径则设置在data-original属性中, 当页面滚动的时候需要去监听scroll事件,在scroll事件的回调中,判断我们的懒加载的图片是否进入可视区域,如果图片在可视区内将图片的 src 属性设置为data-original 的值,这样就可以实现延迟加载。
优点:页面加载速度快、可以减轻服务器的压力、节约了流量,用户体验好
不足:数据量大的时候,加载速度依旧很慢
优化:缩略图格式(压缩资源大小)
项目中遇到的问题?
使用echarts针对相同类型的数据无法渲染,echarts渲染区域未定义
this.$nextTick()将回调延迟到下次 DOM 更新之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。
由于dom元素还没有更新, 因此打印出来的还是未改变之前的值,而通过this.$nextTick()获取到的值为dom更新之后的值
小程序的样式适配怎么做的
小程序的适配原理,提出了一种新单位rpx,可以根据屏幕宽度进行自适应,规定屏幕宽为750rpx
微信官方提供的换算方式:rpx = px * (目标设备宽 px 值 / 750)
在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
一般情况设计稿是按照iphone6尺寸设计的,设计稿上尺寸大小可以直接等于rpx
CSS弹性布局,如果想给容器里面某一个项目设置在交叉轴上的排列与其他不同怎么设置
flex布局下的一个属性:align-self
CSS选择器(常见的,伪类选择器用过哪些,::before ::after应用场景)
常见伪类——:hover,:link,:active,
1 | /*让超链接点击之前是红色*/ |
常见伪元素——::before,::after,
::before和::after下特有的content,用于在css渲染中向元素逻辑上的头部或尾部添加内容。
这些添加不会出现在DOM中,不会改变文档内容,不可复制,仅仅是在css渲染层加入。
所以不要用:before或:after展示有实际意义的内容,尽量使用它们显示修饰性内容,例如图标。
举例:网站有些联系电话,希望在它们前加一个icon☎,就可以使用:before伪元素,如下:
1 |
|
最常用的就是清除浮动
选择器优先级排列
内联样式 => id(id选择器) => class(类选择器) => div(标签选择器) => ul>li子选择器() => li a(后代选择器) => a:hover(伪类选择器)
选择器的权值加到一起,大的优先;如果权值相同,后定义的优先
CSS函数用过嘛?常见的calc()函数 计算长度值, var()
calc()
这个函数使我们能够计算CSS值,而不是指定确切的值。通常用于计算元素的大小或位置。它支持加法、减法、乘法和除法。
需要特别注意重要一点是+
和-
运算符必须用空格隔开,不然无法正常工作。*
和/
运算符不有这限制,但出于一致性的考虑,建议添加空格。
实践例子:水平居中
1 | <p class="calc">Centered with calc</p> |
1 | p.calc { |
var()
通过这个函数,我们可以使用一个自定义属性的值作为另一个CSS属性的值。简单地说,可以定义一个颜色,放在自定义属性(CSS变量)中,然后通过调用var函数重用该属性值。
此函数接受两个参数,即自定义属性和一个默认值,如果出现问题,将使用默认值。
实践例子:一个网站的主题色
1 | :root { |
js如何判断数组 Array.isArray() instanceof 原理
1 | Array.isArray = function(value) { |
简单理解就是运用对象原型的toString方法将Array转换为字符串,之后进行比对,下面我们来详细分析下各个部分的组成。
Object.prototype.toString代表这个toString方法本来是对象原型上面的,之后call方法将toString方法中的this转换为参数value,这样传进的参数value(实际上对于此方法应该是个数组[])就可以通过原型的方法来转换为字符串。
value instanceof Type == true/false
instanceof实现原理:看左边实例的–proto–指向的原型链上,有没有跟右侧类型的prototype指向同一个对象
JS对象深拷贝
使用JSON.parse()和 JSON.stringify()对对象进行深拷贝
1 | clone(obj){ |
(会忽略function和undefined的字段,只能克隆原始对象自身的值,不能克隆它继承的值)
字符串翻转
1 | return str.split("").reverse().join(""); |
事件循环(Event Loop)机制
js是单线程的
宏任务:整体代码,setTimeout,setInterval,I/O操作
微任务:new Promise().then ,MutaionObserver(前端的回溯)
二分法查找时间复杂度O(logn)、 快排时间复杂度O(nlogn)
二分查找:假设一个数组长度为n,每次查找后数据长度减半,第一次查找后数据长度为n/2,第二次查找后数据长度为n/(2的2次方),第k次查找后数据长度为n/(2的k次方),最坏情况下数数据长度为1时找到该数,即n/(2的k次方)=1, 解得k=log2n
快排基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
冒泡排序:O(n^2)
栈和队列的区别
栈:先进后出
队列:先进先出
打印二叉树用什么数据结构
队列
遍历对象和数组的方法
遍历对象:for…in、Object.keys().forEach()
遍历数组:forEach、map、for循环遍历、for…in、for…of(只能遍历出value,无下标)