一、背景
这套题目是广东靓仔认识的一位前端妹子经过“一番努力”Get到的,感谢~
这套题目,比较实用的,接下来广东靓仔跟小伙伴一起来看看这套百度某部门的技术一面原题。
二、原题
设置元素的backgroud 哪些区域颜色会改变
background填充区域默认为content、padding和border区域。
然而该行为由background-clip属性决定,默认为border-box该属性对应的
background填充对应区域如下:
FOUC 无样式闪烁(文档样式短暂失效)@import
如果使用import方法对CSS进行导入,会导致某些页面在Windows 下的Internet Explorer出现一些奇怪的现象:以无样式显示页面内容的瞬间闪烁,这种现象称之为文档样式短暂失效(Flash of Unstyled Content),简称为FOUC。
原因大致为:
1:使用import方法导入样式表;
2:将样式表放在页面底部;
3:有几个样式表,放在html结构的不同位置;
其实原理很清楚:
当样式表晚于结构性html加载,当加载到此样式表时,页面将停止之前的渲染。此样式表被下载和解析后,将重新渲染页面,也就出现了短暂的花屏现象。
解决方法:
使用LINK标签将样式表放在文档HEAD中。
重绘重排区别
重绘不一定需要重排(比如颜色的改变)
重排必然导致重绘(比如改变网页位置)
重排(Reflow):
当渲染树的一部分必须更新并且节点的尺寸发生了变化,浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。
重绘(Repaint):
是在一个元素的外观被改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。比如改变某个元素的背景色、文字颜色、边框颜色等等
减少重排次数和缩小重排影响范围解决方式:
1. 将多次改变样式属性的操作,合成一次操作。
2. 将需要多次重排的元素,嗯,position属性。设为absolute。或fixed。使其脱离文档流,这样,他的变化就不会影响到其他的元素。
3. 在内存中多次操作节点。完成后再添加到文档中去。
4. 如果对一个元素进行复杂的操作,可以将display属性设为none嗯使其隐藏。操作完后再显示。
5. 在需要经常获取那些引起浏览器重排的属性值时,要缓存到变量。
你们项目中Token是怎么拿到的
- 用户登陆,发送手机号码和验证码
- 后台接收参数,查找用户,用户存在就生成token,返回给前端
- 前端登陆成功,把token存到vuex(做持久化)
- 使用axios拦截器,读取vuex中的token,并放入请求头
- 请求其他接口,就会带上token
- 后台在需要登陆的接口上,获取token,解密token获得userId,返回前端需要的数据
- 用户在下次使用app,如果token还在有效期内,不需要重新登陆
有不同的或者更好的方案也可以回答,发散题,自由发挥
cookie是什么?
cookie 是存储在浏览器中的纯文本,浏览器的安装目录下会专门有一个 cookie 文件夹来存放各个域下设置的cookie。
存储量很小4kb
拓展说明,加分项:
当网页要发http请求时,浏览器会先检查是否有相应的cookie,有则自动添加在request header中的cookie字段中。 这些是浏览器自动帮我们做的,而且每一次http请求浏览器都会自动帮我们做。
所以对于那设置“每次请求都要携带的信息(最典型的就是身份认证信息)”就特别适合放在cookie中,其他类型的数据就不适合了。
时效性
expires 是 http/1.0协议中的选项,在新的http/1.1协议中expires已经由 max-age选项代替,两者的作用都是限制cookie 的有效时间。
expires的值是一个时间点(cookie失效时刻= expires ),而max-age 的值是一个以秒为单位时间段(cookie 失效时刻= 创建时刻+ max-age )。
httpOnly
设置cookie是否能通过 js 去访问。默认情况下,cookie不会带httpOnly选项(即为空),所以默认情况下,客户端是可以通过js代码去访问(包括读取、修改、删除等)这个cookie的。当cookie带httpOnly选项时,客户端则无法通过js代码去访问(包括读取、修改、删除等)这个cookie。
Js数据类型有哪些
值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
引用数据类型:对象(Object)、数组(Array)、函数(Function)。
基本类型引用类型区别
基本类型
基本类型的访问是按值访问的,就是说我们可以操作保存在变量中的实际的值。
基本类型有以下几个特点:
- 1.基本类型的值是不可变得:
2.基本类型的比较是值的比较:
3.基本类型的变量是存放在栈区的(栈区指内存里的栈内存)
引用类型
引用类型可以拥有属性和方法,属性又可以包含基本类型和引用类型。
引用类型的有以下一些特性:
1.引用类型的值是可变的
2.引用类型的值是同时保存在栈内存和堆内存中的对象
3.引用类型的比较是引用的比较
判断一个对象是不是数组
方法1:
根据对象的class属性来判断
let obj = [] console.log(Object.prototype.toString.call(obj) === '[object Array]')
方法2:
Array.isArray直接判断
let obj = [] console.log(Array.isArray(obj))
js数组遍历都有哪些方法
这里列举12种,具体如下所示:
1.for循环
for(i = 0,len=arr.length; i < len; i++) { }
2.foreach循环
// 没有返回值,对原数组无影响 arr.forEach((item,index,array)=>{ //执行代码 }) // 参数:value数组中的当前项, index当前项的索引, array原始数组;
3.map循环
var ary = [12,23,24,42,1]; var res = ary.map(function (item,index,ary ) { return item*10; }) console.log(res);//-->[120,230,240,420,10]; 原数组拷贝了一份,并进行了修改 console.log(ary);//-->[12,23,24,42,1]; 原数组并未发生变化
4.forof遍历
for (var value of myArray) { console.log(value); }
5.filter遍历
不会改变原始数组,返回新数组
var arr = [73,84,56, 22,100] var newArr = arr.filter(item => item>80) //得到新数组 [84, 100] console.log(newArr,arr)
6.every遍历
every()是对数组中的每一项运行给定函数,如果该函数对每一项返回true,则返回true。
var arr = [ 1, 2, 3, 4, 5, 6 ]; console.log( arr.every( function( item, index, array ){ return item > 3; })); // false
7.some遍历
some()是对数组中每一项运行指定函数,如果该函数对任一项返回true,则返回true。
var arr = [ 1, 2, 3, 4, 5, 6 ]; console.log( arr.some( function( item, index, array ){ return item > 3; })); // true
8.reduce
reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。
var total = [0,1,2,3,4].reduce((a, b)=>a + b); //10
reduce接受一个函数,函数有四个参数,分别是:上一次的值,当前值,当前值的索引,数组
[0, 1, 2, 3, 4].reduce(function(previousValue, currentValue, index, array){ return previousValue + currentValue; });
9.reduceRight
reduceRight()方法的功能和reduce()功能是一样的,不同的是reduceRight()从数组的末尾向前将数组中的数组项做累加。
reduceRight()首次调用回调函数callbackfn时,prevValue 和 curValue 可以是两个值之一。如果调用 reduceRight() 时提供了 initialValue 参数,则 prevValue 等于 initialValue,curValue 等于数组中的最后一个值。如果没有提供 initialValue 参数,则 prevValue 等于数组最后一个值, curValue 等于数组中倒数第二个值。
var arr = [0,1,2,3,4]; arr.reduceRight(function (preValue,curValue,index,array) { return preValue + curValue; }); // 10
10.find
find()方法返回数组中符合测试函数条件的第一个元素。否则返回undefined。
var stu = [ { name: '张三', gender: '男', age: 20 }, { name: '王小毛', gender: '男', age: 20 }, { name: '李四', gender: '男', age: 20 } ] stu.find((element) => (element.name == '李四')) //返回结果为 //{name: "李四", gender: "男", age: 20}
11.findIndex
对于数组中的每个元素,findIndex 方法都会调用一次回调函数(采用升序索引顺序),直到有元素返回 true。只要有一个元素返回 true,findIndex 立即返回该返回 true 的元素的索引值。如果数组中没有任何元素返回 true,则 findIndex 返回 -1。
findIndex 不会改变数组对象。
[1,2,3].findIndex(x => x == 4); // Returns an index value of -1.
12.keys,values,entries
ES6 提供三个新的方法 —— entries(),keys()和values() —— 用于遍历数组。它们都返回一个遍历器对象,可以用for...of循环进行遍历,唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历
for (let index of ['a', 'b'].keys()) { console.log(index); } // 0 // 1 for (let elem of ['a', 'b'].values()) { console.log(elem); } // 'a' // 'b' for (let [index, elem] of ['a', 'b'].entries()) { console.log(index, elem); } // 0 "a" // 1 "b"
Js事件循环机制
Event Loop 包含两类:
1. 一类是基于 Browsing Context ,
2. 一种是基于 Worker
二者是独立运行的。
JavaScript 是一门单线程语言,异步操作都是放到事件循环队列里面,等待主执行栈来执行的,并没有专门的异步执行线程。
任务队列
任务可以分为同步任务和异步任务,同步任务,顾名思义,就是立即执行的任务,同步任务一般会直接进入到主线程中执行;
而异步任务,就是异步执行的任务,比如ajax网络请求,setTimeout 定时函数等都属于异步任务,异步任务会通过任务队列( Event Queue )的机制来进行协调。
在事件循环中,每进行一次循环操作称为tick,通过阅读规范可知,每一次 tick 的任务处理模型是比较复杂的,其关键的步骤可以总结如下:
- 在此次 tick 中选择最先进入队列的任务( oldest task ),如果有则执行(一次)
- 检查是否存在 Microtasks ,如果存在则不停地执行,直至清空Microtask Queue
- 更新 render
- 主线程重复执行上述步骤
深浅拷⻉贝区别
浅拷贝(Shallow Copy):
仅拷贝对象的非对象属性(基本类型属性)、不可变对象属性,但是不拷贝对象的对象属性(不含不可变对象) ,即为浅拷贝。
以下这些函数得到的都是浅拷贝:
Object.assign、Array.prototype.slice()、Array.prototype.concat()
深拷贝(Deep Copy):
对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。
简单理解:深拷贝会拷贝所有的属性。深拷贝前后两个对象互不影响。
JSON.parse(JSON.stringify())、手写递归函数、函数库lodash
箭头函数特点
1. 省略function换成=> 一个参数的时候()可以省略 一个return的时候{}可以省略
2. 不绑定this,其中的this指向函数定义位置的上下文this
3. 内部不存在arguments和new.target,使用的都是外部的
4. 没有原型,占用内存空间小
Js垃圾回收方法
Javascript具有自动垃圾回收机制(GC:Garbage Collecation)。
原理:垃圾收集器会定期(周期性)找出那些不在继续使用的变量,然后释放其内存。
(1)标记清除法
在函数声明一个变量的时候,就将这个变量标记为“进入环境”。
(2)引用计数法
引用计数的含义是跟踪记录每个值被引用的次数。当这个值的引用次数变成0时,就可以将其占用的内存空间回收回来。
Vuex更新流程
vuex的工作流程就是:
(1)通过dispatch去提交一个actions,
(2)actions接收到这个事件之后,在actions中可以执行一些异步|同步操作,根据不同的情况去分发给不同的mutations,
(3)actions通过commit去触发mutations,
(4)mutations去更新state数据,state更新之后,就会通知vue进行渲染
拓展:
不能在mutations执行异步操作
Vuex中所有的状态更新的唯一途径都是mutation,异步操作通过 Action 来提交 mutation实现,这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现 time-travel 了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难。