前端部分知识总结

乱序 不间断更新

绝大多数写的比较浅显 看个乐子


display:none 和visibility:hidden的区别

display:none
完全消失
将会隐藏它以及全部的后代元素
占据的空间消失,浏览器不会解析该元素
页面产生回流+重绘javascript

visibility:hidden
视觉消失能够理解为透明度为0
占据的空间仍存在,浏览器仍然会解析该元素
页面产生重绘
visibility具备继承性,父元素设置visibility:hidden,子元素也会继承该属性,当子元素从新设置visibility:visible,元素又会从新显示,而display:none不会css


页面的呈现流程&回流&重绘

页面的呈现流程html

  1. 浏览器将读取的全部html代码解析,生成一个Dom树 ->dom tree
  2. 浏览器将全部样式解析成样式结构体 ->style rules
  3. Dom数和样式结构体结合生成构建呈现树 render tree ->attachment
  4. 浏览器根据render tree 绘制页面

some tips前端

  • 在解析样式结构体的过程当中浏览器会去除不能识别的样式(IE去掉-moz开头的样式,firefox去除_开头的样式)
  • render tree与dom tree区别很大,render tree可以识别样式,且不会包含隐藏的节点(display:none),visibility:hidden仍会包含在render tree内。在render tree中,每个节点被称为box

回流&重绘java

回流:render tree中部分(所有)元素的规模尺寸布局等改变而须要从新构建页面。
重绘:render tree中一些元素须要更新属性,但这些属性只影响元素的外观、风格而不引发布局的改变react

在解析样式结构体的过程当中浏览器会去除不能识别的样式
回流必将引发重绘,重绘不必定引发回流
参考文档:关于呈现、回流、重绘web


get请求和post请求

get:经过查询字符串的方式来进行传递ajax

用于获取少许信息(单次运输量不大于64k),使用url传递参数->很不安全

post:经过表单的方式传递算法

用于修改服务器的资源,无信息量限制,采用请求体承载的方式,不易暴露

本质上同根同源
get&post 都是http协议中用于发送请求的方法,而http是基于tcp/ip的关于数据如何在万维网通讯的协议
如何理解?
TCP->汽车 HTTP->交通规则 浏览器->运输公司
get->将货物放在车顶上(url) ,只产生一个数据包
post->将货物放在车箱里 , 产生header+body两个数据包chrome

post产生两个数据包,先发送header确认后再发送body,然而并非全部浏览器都在post中发两次包,如firefox就只发一次

域名的组成

http://    www.baidu.com    :8080    /dir/other.html
协议        主机名            端口     文件路径 参数 文件片断

transition和transform

transform
对元素进行移动、缩放、转动、拉长或拉伸
方法:
translate():元素从当前位置移动根据给定的top left 坐标移动

transform:tanslate(50px,30px)

rotate():元素顺时针旋转给定的角度,负值->逆时针旋转

transform:rotata(20deg)

scale():根据给定的XY轴参数、元素的尺寸会增长或减小(拉伸、收缩)

transform:scale(1.2,0.8)

skew():翻转

transform:skew(20deg, 20deg);
//围绕 X 轴把元素翻转20度,围绕 Y 轴翻转20度

transition过渡
元素从一种样式逐渐变为另外一种样式,属于一种简单的动画属性
四个属性:
transition-property: 过渡属性的样式(默认值为all)
transition-duration: 过渡持续时间(默认值为0s)必须值
transiton-timing-function: 过渡函数(默认值为ease函数)
transition-delay: 过渡延迟时间(默认值为0s)

div{
width:100px;
transition: width 1s;
//时长为一秒的宽度变化效果
}
div:hover{
width:500px;
}

参考:深刻理解trasition
参考:transition和transform


虚拟DOM

为何用虚拟dom?
生成页面时,浏览器从构建DOM树开始从到到尾执行一遍流程。好比在一次操做时,须要更新10个DOM节点,理想状态是一次性构建完DOM树,再执行后续操做。可是浏览器并不会这么作,收到第一个更新DOM请求后会立刻执行流程,所以须要执行10次。频繁的操做会引发页面卡顿。真实的DOM节点,哪怕最简单的一个div也会包含不少属性

虚拟DOM干什么?
如一次操做有10个更新DOM的动做,虚拟DOM不会马上操做DOM,而是将10次更新的diff内容保存到一个本地的js对象中,最终将js对象一次行attach到DOM树上,避免了大量的无谓计算量

虚拟的DOM的核心思想:对复杂的文档DOM结构,提供一种方便的工具,进行最小化地DOM操做


React的生命周期

clipboard.png

三个状态:装配 更新 卸载

初始化渲染:
constructor()构造函数

componentWillMount组件将要加载(17版本弃用,在这里请求异步数据,render可能不会渲染到,由于componentWillMount执行后,render立马执行)
整个生命周期只调用一次(组件更新再也不调用)

render()渲染方法

componentDidMount 组件已经加载
整个生命周期只调用一次(组件更新再也不调用)
↑在这里能够异步请求数据,在这里设置状态会触发从新渲染,可是不推荐使用setstate函数,会触发额外一次渲染,且在浏览器刷新屏幕以前执行,会致使性能问题

更新:
共有五个环节(不一样的状况有不一样的执行步骤)

1.componentWillReceiveProps(nextprops获取更新状态以及相应的组件状态,组件将要接收参数

2.shouldComponentUpdate(nextprops,nextstate)根据下一个props和state决定组件是否应该更新
↑immutable data在此使用immutable是一旦建立,就不能再被更改的数据

3.componentWillUpdate()组件将要更新 作准备工做(定时、网络请求等)
在这里能够更改state 可是不能使用setState函数 会引发函数调用componentshouldupdate从而进入死循环
4.render()渲染

getSnapshotBeforeUpdate(nextprops,nextstate)在更新前截图//不会用

5.componentDidUpdate() 组件已经更新完毕
能够在这里获取DOM

卸载
只有一个步骤,由于卸载后将失去控制能力
componentWillUnmount()组件将要卸载
在这里清除一些不须要的监听和计时器

三种模式下的执行步骤:

  1. 父组件带动子组件更新 -> 12345
  2. setState() 跳过componentWillReceiveProps() ->2345
  3. forceUpdate()强制更新 跳过shouldComponentUpdate()无需判读->345

defaultProps()
设定默认props 在组件没有被传入时生效,避免报错
propTypes 类型检查

import PropTypes from 'prop-types'.//结合第三方prop-types库
static propTypes = {
    title:PropTypes.string
}

原型&原型链

原型是JavaScript中继承的基础,JavaScript的继承就是基于原型的继承

什么是原型?
咱们建立的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象能够包含由特定类型的全部实例共享的属性和方法。而prototype就是经过调用构造函数建立的对象实例的原型对象

原型所指的就是一个对象,实例继承对象的属性。在原型上定义的属性,经过继承,实例也拥有了这个属性
实例经过_proto_这个属性直接访问到原型

function Person(){
Person.prototype.type   = 'object named Person';
person = new Person();
person._proto_ === Person.prototype;//二者等价

}

构造函数->prototype->访问原型
原型->constructor->访问构造函数

使用原型的好处:
可让对象的实例共享它所包含的属性和方法,没必要在构造函数中添加定义对象信息,而是能够将这些信息添加到原型中(若是使用构造函数就要让每一个方法都在实例中建立一遍)

clipboard.png

constructor是原型的一个属性,Constructor是真正的构造函数

什么是原型链?
_proto_是实例指向原型对象的一个指针,是任何对象都有的属性,js万物皆对象,因此就造成了一条由_proto_连起来的链条,递归访问到头,终值为null

在读取一个实例的属性时,若是该属性在当前实例没有找到,那么就会循着_proto_指定的原型继续向上找,若是还找不到,则寻找原型的原型,若是一直没有找到,则直到搜索到null为止

原型继承

Son.prototype = new Father();//Son继承了Father,经过原型,造成链条

参考文章:原型
参考文章:原型链


函数提高与变量提高的优先级

变量提高
ES6以前没有块级做用域,只有全局做用域和局部做用域,变量提高就是将变量声明提高到它所在做用域的最开始的部分

函数提高
建立函数有两种形式:函数声明和函数字面量,只有函数声明有变量提高

console.log(a)  // f a() { console.log(a) }
console.log(b) //undefined,不存在函数提高
    
function a() {
        console.log(a) 
}

var b = function(){
        console.log(b)
}

函数提高与变量提高的优先级
函数提高要比变量提高的优先级要高一些,且不会被变量声明覆盖,可是会被变量赋值以后覆盖。

console.log(a);    // f a() {console.log(10)}
console.log(a());    //  undefined
var a = 3;

function a() {
        console.log(10) //10
}
console.log(a)   //3
a = 6;
console.log(a());  //a is not a function;

正常的执行顺序

var a = funtion () {
        console.log(10)
    }
    var a;
    console.log(a);    // f a() {console.log(10)}
    console.log(a());  //  undefined

    a = 3;
    console.log(a)   //3
    a = 6;
    console.log(a());   //a() is not a function;

参考文章


JS处理异步的几种方式

  1. 事件监听
    onclick方法、addEventlistener、attachEvent(不支持ie,执行顺序3-2-1)
  1. setTimeout超时调用
    setInterval间歇调用,按照指定的时间间隔反复执行任务代码
  2. generator 可以屡次返回的“函数”
    每执行一次后就暂停,返回的值就是yield的返回值,每次返回一个值,直到done为true,这个generate对象已经所有执行完毕
  3. promise
    三种状态:等待(pengding) 成功(resolved) 失败(rejected)
  4. async/await
    一种特殊的语法,能够更温馨地与promise协同工做
    async放置在一个函数前面,使函数老是返回一个promise,即便其中包含非promise(会自动将返回值包装成promise的resolved值)
    await只能使用在async内,可以使JavaScript等待,直到promise处理结束
    1.若是它是一个错误,异常就产生了,就像在那个地方调用了throw error同样。
    2.不然,它会返回一个结果,咱们能够将它分配给一个值

    参考

  5. 观察者模式
    publish()/subscribe
    又称为发布、订阅模式
    某个任务执行完毕,则向信号中心发布一个信号,其余任务能够向信号中心订阅该信号,从而知道什么时候执行本身的任务
//f2()
 jQuery.subscribe("done", f2);
//f1()
function f1(){

    setTimeout(function () {

      // f1的任务代码

      jQuery.publish("done");

    }, 1000);

  }

//f2执行完毕后能够取消订阅
  jQuery.unsubscribe("done", f2);

该方法优于事件监听,能够经过查看消息中心了解如今有多少信号、订阅者,从而监控程序的执行状态
参考文档


回调函数的优劣

优势:容易理解和部署
缺点:不利于代码阅读、维护,各个部分耦合性很高,流程混乱,且每一个任务只能指定一个回调函数


跨域及跨域的方式

什么是跨域:
浏览器不能执行其余网站的脚本,由浏览器的同源策略形成,是浏览器对JavaScript施加的安全限制
判读是同域:
相同域名,端口相同,协议相同

Jsonp:
Json with Padding,为了解决跨域请求资源而产生的解决方案,是一种依靠开发人员创造出的一种非官方跨域数据交互协议。

Jsonp的产生:
ajax直接请求普通文件存在跨域无权限访问的问题,而web页面调用js时不受跨域影响,凡是带有src属性标签的都拥有跨域能力->在远程服务器上把数据装进js格式的文件里,能够实现跨域访问
JSON的纯字符数据格式能够简洁的描述复杂的程序,JSON还被原生js支持
因此,web客户端调用跨域服务器生成的js文件(JSON),便得到了本身想要的数据

Jsonp原理
利用script标签没有跨域限制的“漏洞”达到和第三方通信的目的
首先在客户端注册一个回调函数,而后把回调函数的名字传给服务器,这时服务器生成json数据,以JavaScript的方式生成function,将jasonp以入参的方式放到function里,生成JavaScript文档,返回给客户端,浏览器解析这个script,执行JavaScript文档,此时数据做为参数传入了客户端以前定义的回调函数里。

jsonp是请求以后后台包装好一段json,而且把数据放在一个callback函数,返回一个js文件,动态引入这个文件,下载完成js以后,会去调用这个callback,经过这样访问数据
json 是一种数据格式,jsonp 是一种数据调用的方式,带callback的json就是jsonp

跨域的几种方法

  1. Jsonp
    优势:不受同源策略限制,兼容性好,低版本的浏览器也能够运行,在请求完毕后能够经过调用callback的方式回传结果。
    缺点:只支持get请求不支持post请求,只支持跨域HTTP请求这种状况,不能解决不一样域的两个页面之间如何进行JavaScript调用的问题。
  2. document.domain跨域
    前提条件:
    这两个域名必须属于同一个基础域名!并且所用的协议,端口都要一致,不然没法利用document.domain进行跨域.
    方法:
    须要在a.html里与b.html里都加入:document.domain = "xxx.com";
  3. HTML5的postMessage方法跨域
    高级浏览器Internet Explorer 8+, chrome,Firefox , Opera 和 Safari 都将支持这个功能。这个功能主要包括接受信息的"message"事件和发送消息的"postMessage"方法。
    好比damonare.cn域的A页面经过iframe嵌入了一个google.com域的B页面,能够经过如下方法实现A和B的通讯
  4. CORS跨域
    基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功仍是失败。
    整个CORS通讯过程,都是浏览器自动完成,不须要用户参与。
    对于开发者来讲,CORS通讯与同源的AJAX通讯没有差异,代码彻底同样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感受。
    更适用于现代浏览器

参考文档


函数柯里化

把可以接受多个参数的函数变换成接受一个单一参数的函数,而且返回接受余下参数并且返回结果的函数技术

柯里化是指这样一个函数(假设叫作createCurry),他接收函数A做为参数,运行后可以返回一个新的函数。而且这个新的函数可以处理函数A的剩余参数。

函数柯里化(function currying)又称部分求值。一个currying的函数首先会接受一些参数,接受了这些参数后,该函数并不会当即求值,而是继续返回另一个函数,刚才传入的参数在函数造成的闭包里被保存起来。待到函数真正须要求值的时候,以前传入的参数都会被一次性用于求值。

Q:函数通过createCurry转化为一个柯里化函数,最后执行的结果,不是正好至关于执行函数自身吗?柯里化是否是把简单的问题复杂化了?

好处:
1.参数复用
2.提早返回
3.延时执行

参考文档
参考文档,高阶


模块化、CommonJs

对模块化的理解
功能封装,针对Javascript代码,隔离、组织复制的javascript代码,将它封装成一个个具备特定功能的的模块。
模块能够经过传递参数的不一样修改这个功能的的相关配置,每一个模块都是一个单独的做用域,根据须要调用。
模块化就是为了减小系统耦合度,提升内聚性,减小资源循环依赖,加强系统框架设计。
CommonJs
它的终极目标是提供一个相似Python,Ruby和Java标准库。这样的话,开发者可使用CommonJS API编写应用程序,而后这些应用能够运行在不一样的JavaScript解释器和不一样的主机环境中。
CommonJs的特色:

  1. 全部代码都运行在模块做用域,不会污染全局做用域。
  2. 模块能够屡次加载,可是只会在第一次加载时运行一次,而后运行结果就被缓存了,之后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
  3. 模块加载的顺序,按照其在代码中出现的顺序。

AMD规范和commonJS规范
1.相同点:都是为了模块化。
2.不一样点:AMD规范则是非同步加载模块,容许指定回调函数。CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操做。
参考文档


情景题,加载图片

  • 懒加载

    利用jQuery实现图片懒加载的原理。它的基本思想是:在输出HTML的时候,不要直接输出<img src="xxx",而是输出以下的img标签:

<img src="/static/loading.gif" data-src="http://真正的图片地址/xxx.jpg">
监听scroll事件,调用目标元素(绿色方块)的getBoundingClientRect()方法,获得它对应于视口左上角的坐标,再判断是否在视口以内。这种方法的缺点是,因为scroll事件密集发生,计算量很大,容易形成性能问题。

参考:JQuery实现

使用IntersectionObserve(callback,option) api监听图片素到视口的距离判断是否加载图片,实现懒加载
callback通常会触发两次。一次是目标元素刚刚进入视口(开始可见),另外一次是彻底离开视口(开始不可见)。
参考

有些事件(resize Mousemove scroll)几乎是不间断触发的,若是存在复杂的函数方法,很是影响性能,因此须要函数节流

  • 函数节流

    函数节流的基本思想是设置一个定时器,在指定时间间隔内运行代码时清除上一次的定时器,并设置另外一个定时器,直到函数请求中止并超过期间间隔才会执行。
    一个函数执行一次后,只有大于设定的执行周期后才会执行第二次

  • 防抖
    函数调用n秒后才会执行,若是函数在n秒内被调用的话则函数不执行,从新计算执行时间

函数的节流和函数的去抖都是经过减小实际逻辑处理过程的执行来提升事件处理函数运行性能的手段,并无实质上减小事件的触发次数。

节流和防抖的区别
函数节流是指必定时间内js方法只跑一次。
好比人的眨眼睛,就是必定时间内眨一次。这是函数节流最形象的解释。
函数防抖是指频繁触发的状况下,只有足够的空闲时间,才执行代码一次。
好比生活中的坐公交,就是必定时间内,若是有人陆续刷卡上车,司机就不会开车。只有别人没刷卡了,司机才开车。

代码实现
节流
声明一个变量为标志位,当这个变量为true的时候,表明如今的滚动处理事件是空闲的,可使用。直接return并将变量设为false这样,其余请求执行滚动事件的方法,就被挡回去了。而后用settimeout规定时间间隔,再执行定时函数内的代码,执行完毕将变量从新设为true
防抖
也须要一个settimeout辅助,延迟执行须要跑的代码
若是方法屡次触发,则把上次记录的延迟执行代码用clearTimeout清掉,从新开始。
若是计时完毕,没有方法进来访问触发,则执行代码。
 函数防抖的实现重点,就是巧用setTimeout作缓存池,并且能够轻易地清除待执行的代码。clearTimeout(timer)
参考


react父组件更新,子组件更新问题

只要父组件的render了,那么默认状况下就会触发子组件的render过程,子组件的render过程又会触发它的子组件的render过程,一直到React元素(即jsx中的<div>这样的元素)。当render过程到了叶子节点,即React元素的时候,diff过程便开始了,这时候diff算法会决定是否切实更新DOM元素。
React不能检测到你是否给子组件传了属性,因此它必须进行这个重渲染过程(术语叫作reconciliation)
连接描述


let&const

let、const、var的区别
var:能够跨块级做用域访问,不能跨函数做用域访问
let:只能在块级做用域访问,不能跨函数使用
const:定义常量,必须初始化且不能修改,只能在块级做用域内使用
关于变量提高:var不论声明在何处都会莫默认提高到函数/全局最顶部,可是let和const不会进行变量提高


promise.all()和promise.race() 的区别

clipboard.png


async await实现sleep

function sleep(ms){
  return new Promise((resolve)=>setTimeout(resolve,ms));
}
async function test(){
  var temple=await sleep(1000);
  console.log(1111)
  return temple
}
test();
//延迟1000ms输出了1111

async/await相对于promise的优点

  1. 代码更加简洁,可以更好的处理then链
    没必要编写.then,没必要建立一个匿名函数来处理响应,没必要将命名数据传递给咱们不须要使用的变量。咱们也避免了嵌套代码。
  2. 更好的处理中间值
    好比说time1 time2 time3 ,promise传递参数很麻烦,而用async/await就不须要多余的中间值
  3. 更易于调试

promise由于没有代码块,因此不能在一个返回的箭头函数中设置断点。若是你在一个 .then 代码块中使用调试器的步进(step-over)功能,调试器并不会进入后续的 .then 代码块,由于调试器只能跟踪同步代码的每一步。
使用 async/await,你就没必要再使用箭头函数。你能够对 await 语句执行步进操做

参考


diff算法

传统算法就是对每一个节点一一对比,循环遍历全部的子节点,而后判断子节点的更新状态,分别为remove、add、change。若是before的子节点仍有子节点依旧顺次执行。

clipboard.png

clipboard.png

参考
参考


flex弹性布局

主要思想是给予容器控制内部元素高度和宽度的能力

clipboard.png

主轴main axis 纵轴 cross axis
1点:

display: flex;
        justify-content: center;
        align-items:center;

2点:竖列布局且在主轴方向采用justify-content的两端对齐布局,这样两个圆点会在左边呈现,而后采用align-items让其居中

display: flex;
        flex-direction: column;//垂直显示
        justify-content: space-between;
        align-items:center;

3点:用到align-self属性让第二个和第三个圆点有本身的属性设置,分别在纵轴方向上居中和低端对齐

.item:nth-child(2){
        align-self:center;
    }
    .item:nth-child(3){
        align-self:flex-end;
    }

五点布局
思路:先竖着放两行圆点,每行圆点里横着放两个圆点,因此最外层父元素设置align,里面的父元素设置justify-content造成4点
让圆点(即子元素)在横轴上居中在竖轴上居中,分别用justify-content和align-items造成1点

display: flex;
        flex-wrap:wrap;//必要时拆行显示
        align-content:space-between;//各行在弹性盒容器中平均分布
    .column{
        flex-basis:100%;
        display:flex;
        justify-content: space-between;
    }

6点:
跟四点的同样,先竖放三行在每行横放两个圆点

实现骰子布局


雪碧图

一个网页可能有许多的小图标,访问时会发送不少次的请求,形成资源浪费、访问速度变慢。可使用一张图片来代替小图标,按必定的距离排开
前提条件
须要一个宽和高设置好的容器
须要设置background-position的值(默认为(0,0),也就是图片的左上角),即移动图片到本身想要的图标位置。

用css Gaga 自动生成雪碧图

css代码为:background-position:-xpx -ypx;


前端攻防

1.XSS攻击:
跨站脚本攻击指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入的恶意html代码会被执行,对受害用户可能采起Cookie资料窃取、会话劫持、钓鱼欺骗等各类攻击。
预防方法:

  • 设计xss Filter,分析用户提交的输入,并消除潜在的跨站脚本攻击、恶意的HTML等。在须要html输入的地方对html标签及一些特殊字符( ”
    < > & 等等 )作过滤,将其转化为不被浏览器解释执行的字符。
  • 前端防护组件:js-xss

2.CSRF跨站点伪造请求
攻击者经过各类方法伪造一个请求,模仿用户提交表单的行为,从而达到修改用户的数据,或者执行特定任务的目的。
解决方法:

  • 采用POST请求,增长攻击的难度.用户点击一个连接就能够发起GET类型的请求。而POST请求相对比较难,攻击者每每须要借助javascript才能实现。
  • 对请求进行认证,确保该请求确实是用户本人填写表单并提交的,而不是第三者伪造的.具体能够在会话中增长token,确保看到信息和提交信息的是同一我的。(验证码)

3.Http Heads攻击
HTTP协议在Response header和content之间,有一个空行,即两组CRLF(0x0D 0A)字符。这个空行标志着headers的结束和content的开始。“聪明”的攻击者能够利用这一点。只要攻击者有办法将任意字符“注入”到headers中,这种攻击就能够发生。

解决办法:
服务器通常会限制request headers的大小。例如Apache server默认限制request header为8K。若是超过8K,Aapche Server将会返回400 Bad Request响应。
对于大多数状况,8K是足够大的。假设应用程序把用户输入的某内容保存在cookie中,就有可能超过8K.攻击者把超过8k的header连接发给受害者,就会被服务器拒绝访问.解决办法就是检查cookie的大小,限制新cookie的总大写,减小因header过大而产生的拒绝访问攻击
参考


闭包
垂直居中实现

redux原理


Javascript全局函数

clipboard.png


JS的内置对象

clipboard.png

相关文章
相关标签/搜索