display:flex; 在父元素设置,子元素受弹性盒影响,默认排成一行,若是超出一行,按比例压缩 flex:1; 子元素设置,设置子元素如何分配父元素的空间,flex:1,子元素宽度占满整个父元素align-items:center 定义子元素在父容器中的对齐方式,center 垂直居中justify-content:center 设置子元素在父元素中居中,前提是子元素没有把父元素占满,让子元素水平居中。javascript
transtion transition-property 规定设置过渡效果的 CSS 属性的名称。css
transition-duration 规定完成过渡效果须要多少秒或毫秒。html
transition-timing-function 规定速度效果的速度曲线。前端
transition-delay 定义过渡效果什么时候开始。vue
animation属性能够像Flash制做动画同样,经过控制关键帧来控制动画的每一步,实现更为复杂的动画效果。java
ainimation实现动画效果主要由两部分组成:node
经过相似Flash动画中的帧来声明一个动画;react
在animation属性中调用关键帧声明的动画。webpack
translate 3D建模效果ios
图片中的 alt属性是在图片不能正常显示时出现的文本提示。alt有利于SEO优化
图片中的 title属性是在鼠标在移动到元素上的文本提示。
<style>
div {
width: 0;
height: 0;
border-top: 40px solid transparent;
border-left: 40px solid transparent;
border-right: 40px solid transparent;
border-bottom: 40px solid #ff0000; } </style> </head> <body> <div></div> </body> 复制代码
标准盒子模型:宽度=内容的宽度(content)+ border + padding
低版本IE盒子模型:宽度=内容宽度(content+border+padding)
已知宽度,block元素 ,添加添加margin:0 auto属性。
已知宽度,绝对定位的居中 ,上下左右都为0,margin:auto
div {
position: relative / fixed; /* 相对定位或绝对定位都可 */
width:500px;
height:300px;
top: 50%;
left: 50%;
margin-top:-150px;
margin-left:-250px;
外边距为自身宽高的一半 */
background-color: pink; /* 方便看效果 */
}
.container {
display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
}
.container div {
width: 100px; /* 可省 */
height: 100px; /* 可省 */
background-color: pink; /* 方便看效果 */
}
复制代码
clear清除浮动(添加空div法)在浮动元素下方添加空div,并给该元素写css样式 {clear:both;height:0;overflow:hidden;}
给浮动元素父级设置高度
父级同时浮动(须要给父级同级元素添加浮动)
父级设置成inline-block,其margin: 0 auto居中方式失效
给父级添加overflow:hidden 清除浮动方法
万能清除法 after伪类 清浮动(如今主流方法,推荐使用)
float_div:after{
content:"."; clear:both; display:block; height:0; overflow:hidden; visibility:hidden; } .float_div{ zoom:1 } 复制代码
圣杯布局/双飞翼布局
<style>
* {
margin: 0;
padding: 0;
}
.middle,
.left,
.right {
position: relative;
float: left; min-height: 130px; } .container { padding: 0 220px 0 200px; overflow: hidden; } .left { margin-left: -100%; left: -200px; width: 200px; background: red; } .right { margin-left: -220px; right: -220px; width: 220px; background: green; } .middle { width: 100%; background: blue; word-break: break-all; } </style> </head> <body> <div class='container'> <div class='middle'></div> <div class='left'></div> <div class='right'></div> </div> </body> 复制代码
display:none 隐藏对应的元素,在文档布局中再也不给它分配空间,它各边的元素会合拢,就当他历来不存在。
visibility:hidden 隐藏对应的元素,可是在文档布局中仍保留原来的空间。
link属于HTML标签,而@import是CSS提供的页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载
import只在IE5以上才能识别,而link是HTML标签,无兼容问题
link方式的样式的权重 高于@import的权重.
共同点: 改变行内元素的呈现方式,display被置为block 让元素脱离普通流,不占据空间 默认会覆盖到非定位元素上
不一样点: absolute的”根元素“是能够设置的 fixed的”根元素“固定为浏览器窗口。当你滚动网页,fixed元素与浏览器窗口之间的距离是不变的。
Animation和transition大部分属性是相同的,他们都是随时间改变元素的属性值,他们的主要区别是transition须要触发一个事件才能改变属性, 而animation不须要触发任何事件的状况下才会随时间改变属性值,而且transition为2帧,从from .... to,而animation能够一帧一帧的。
transition 规定动画的名字 规定完成过渡效果须要多少秒或毫秒 规定速度效果 定义过渡效果什么时候开始 animation 指定要绑定到选择器的关键帧的名称
不一样级别:总结排序:!important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
1.属性后面加!import 会覆盖页面内任何位置定义的元素样式
2.做为style属性写在元素内的样式
3.id选择器
4.类选择器
5.标签选择器
6.通配符选择器(*)
7.浏览器自定义或继承
**同一级别:后写的会覆盖先写的**
复制代码
css选择器的解析原则:选择器定位DOM元素是从右往左的方向,这样能够尽早的过滤掉一些没必要要的样式规则和元素
多个图片集成在一个图片中的图
使用雪碧图能够减小网络请求的次数,加快容许的速度
经过background-position,去定位图片在屏幕的哪一个位置
复制代码
相同点: 都经常使用来判断一个变量是否为空,或者是什么类型的。
不一样点: typeof 返回值是一个字符串,用来讲明变量的数据类型 instanceof 用于判断一个变量是否属于某个对象的实例.
visibility:hidden、display:none、z-index=-一、opacity:0
1.opacity:0,该元素隐藏起来了,但不会改变页面布局,而且,若是该元素已经绑定了一些事件,如click事件也能触发
2.visibility:hidden,该元素隐藏起来了,但不会改变页面布局,可是不会触发该元素已经绑定的事件
3.display:node, 把元素隐藏起来,而且会改变页面布局,能够理解成在页面中把该元素删掉
复制代码
浅克隆: 只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,咱们把这种拷贝叫作“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,若是原地址中对象被改变了,那么浅复制出来的对象也会相应改变。
深克隆: 建立一个新对象,属性中引用的其余对象也会被克隆,再也不指向原有对象地址。 JSON.parse、JSON.stringify()
let定义块级做用域变量 没有变量的提高,必须先声明后使用 let声明的变量,不能与前面的let,var,conset声明的变量重名
const 定义只读变量 const声明变量的同时必须赋值,const声明的变量必须初始化,一旦初始化完毕就不容许修改 const声明变量也是一个块级做用域变量 const声明的变量没有“变量的提高”,必须先声明后使用 const声明的变量不能与前面的let, var , const声明的变量重 const定义的对象\数组中的属性值能够修改,基础数据类型不能够
ES6能够给形参函数设置默认值
在数组以前加上三个点(...)展开运算符
数组的解构赋值、对象的解构赋值
箭头函数的特色 箭头函数至关于匿名函数,是不能做为构造函数的,不能被new 箭头函数没有arguments实参集合,取而代之用...剩余运算符解决 箭头函数没有本身的this。他的this是继承当前上下文中的this 箭头函数没有函数原型 箭头函数不能当作Generator函数,不能使用yield关键字 不能使用call、apply、bind改变箭头函数中this指向 Set数据结构,数组去重
=赋值
==返回一个布尔值;相等返回true,不相等返回false; 容许不一样数据类型之间的比较; 若是是不一样类型的数据进行,会默认进行数据类型之间的转换; 若是是对象数据类型的比较,比较的是空间地址
=== 只要数据类型不同,就返回false;
一、js工厂模式
二、js构造函数模式
三、js原型模式
四、构造函数+原型的js混合模式
五、构造函数+原型的动态原型模式
六、观察者模式
七、发布订阅模式
复制代码
call() 和apply()的第一个参数相同,就是指定的对象。这个对象就是该函数的执行上下文。
call()和apply()的区别就在于,二者之间的参数。
call()在第一个参数以后的 后续全部参数就是传入该函数的值。
apply() 只有两个参数,第一个是对象,第二个是数组,这个数组就是该函数的参数。 bind() 方法和前二者不一样在于: bind() 方法会返回执行上下文被改变的函数而不会当即执行,而前二者是 直接执行该函数。他的参数和call()相同。
原型链继承 核心: 将父类的实例做为子类的原型
构造继承 核心:使用父类的构造函数来加强子类实例,等因而复制父类的实例属性给子类
实例继承 核心:为父类实例添加新特性,做为子类实例返回
拷贝继承
组合继承 核心:经过调用父类构造,继承父类的属性并保留传参的优势,而后经过将父类实例做为子类原型,实现 函数复用
寄生组合继承 核心:经过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实 例方法/属性,避免的组合继承的缺点
我的感受,简单来讲闭包就是在函数里面声明函数,本质上说就是在函数内部和函数外部搭建起一座桥梁,使得子函数能够访问父函数中全部的局部变量,可是反之不能够,这只是闭包的做用之一,另外一个做用,则是保护变量不受外界污染,使其一直存在内存中,在工做中咱们仍是少使用闭包的好,由于闭包太消耗内存,不到万不得已的时候尽可能不使用。
把全部的对象共用的属性所有放在堆内存的一个对象(共用属性组成的对象),而后让每个对象的 __proto__存储这个「共用属性组成的对象」的地址。而这个共用属性就是原型,原型出现的目的就是为了减小没必要要的内存消耗。而原型链就是对象经过__proto__向当前实例所属类的原型上查找属性或方法的机制,若是找到Object的原型上仍是没有找到想要的属性或者是方法则查找结束,最终会返回undefined
将html代码按照深度优先遍从来生成DOM树。 css文件下载完后也会进行渲染,生成相应的CSSOM。 当全部的css文件下载完且全部的CSSOM构建结束后,就会和DOM一块儿生成Render Tree。 接下来,浏览器就会进入Layout环节,将全部的节点位置计算出来。 最后,经过Painting环节将全部的节点内容呈现到屏幕上。
一、浏览器的地址栏输入URL并按下回车。
二、浏览器查找当前URL是否存在缓存,并比较缓存是否过时。三、DNS解析URL对应的IP。
四、根据IP创建TCP链接(三次握手)。
五、HTTP发起请求。
六、服务器处理请求,浏览器接收HTTP响应。
七、渲染页面,构建DOM树。
八、关闭TCP链接(四次挥手)
复制代码
相同点 都是保存在浏览器端,且同源的。
不一样点
同源策略(协议+端口号+域名要相同)
一、jsonp跨域(只能解决get) 原理:动态建立一个script标签。利用script标签的src属性不受同源策略限制,由于全部的src属性和href属性都不受同源策略的限制,能够请求第三方服务器资源内容
步骤: 1).去建立一个script标签 2).script的src属性设置接口地址 3).接口参数,必需要带一个自定义函数名,要否则后台没法返回数据 4).经过定义函数名去接受返回的数据
二、document.domain 基础域名相同 子域名不一样
三、window.name 利用在一个浏览器窗口内,载入全部的域名都是共享一个window.name
四、服务器设置对CORS的支持 原理:服务器设置Access-Control-Allow-Origin HTTP响应头以后,浏览器将会容许跨域请求
五、利用h5新特性window.postMessage()
1.建立ajax实例
2.执行open 肯定要访问的连接 以及同步异步
3.监听请求状态
4.发送请求
ES6的set对象 先将原数组排序,在与相邻的进行比较,若是不一样则存入新数组
function unique(arr){ var arr2 = arr.sort(); var res = [arr2[0]]; for(var i=1;i<arr2.length;i++){ if(arr2[i] !== res[res.length-1]){ res.push(arr2[i]); } } return res; } 利用下标查询 function unique(arr){ var newArr = [arr[0]]; for(var i=1;i<arr.length;i++){ if(newArr.indexOf(arr[i]) == -1){ newArr.push(arr[i]); } } return newArr; } 复制代码
2开头
3开头
以4开头的都是客户端的问题;
以5开头都是服务端的问题
同步:在同一时间内作一件事情
异步:在同一时间内作多个事情 JS是单线程的,每次只能作一件事情,JS运行在浏览器中,浏览器是多线程的,能够在同一时间执行多个任务。
定时器、ajax、事件绑定、回调函数、async await、promise
三次握手
四次挥手
创建链接的时候, 服务器在LISTEN状态下,收到创建链接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。 而关闭链接时,服务器收到对方的FIN报文时,仅仅表示对方再也不发送数据了可是还能接收数据,而本身也未必所有数据都发送给对方了,因此己方能够当即关闭,也能够发送一些数据给对方后,再发送FIN报文给对方来表示赞成如今关闭链接,所以,己方ACK和FIN通常都会分开发送,从而致使多了一次。
- 若是元素类型发生变化,直接替换
- 若是是文本,则比较文本里面的内容,是否有差别,若是是元素就须要比较当前元素的属性是否相等,会先比较key, 在比较类型 为何 react中循环 建议不要使用索引 ,若是纯为了展现 那能够使用索引
全局做用域
私有做用域
块级做用域
上级做用域
他是ES6中新增长的一个类(new Promise),目的是为了管理JS中的异步编程的,因此把他称为“Promise设计模式” new Promise 经历三个状态:padding(准备状态:初始化成功、开始执行异步的任务)、fullfilled(成功状态)、rejected(失败状态)== Promise自己是同步编程的,他能够管理异步操做的(重点),new Promise的时候,会把传递的函数当即执行 Promise函数天生有两个参数,resolve(当异步操做执行成功,执行resolve方法),rejected(当异步操做失败,执行reject方法) then()方法中有两个函数,第一个传递的函数是resolve,第二个传递的函数是reject ajax中false表明同步,true表明异步,若是使用异步,不等ajax完全完成
相同点
不一样点
注意:forEach对于空数组是不会调用回调函数的。
async/await函数是异步代码的新方式
async/await是基于promise实现的
async/await使异步代码更像同步代码
await 只能在async函数中使用,不能再普通函数中使用,要成对出现
默认返回一个promise实例,不能被改变
await下面的代码是异步,后面的代码是同步的
- 全局做用域下的this指向window
- 若是给元素的事件行为绑定函数,那么函数中的this指向当前被绑定的那个元素
- 函数中的this,要看函数执行前有没有 . , 有 . 的话,点前面是谁,this就指向谁,若是没有点,指向window
- 自执行函数中的this永远指向window
- 定时器中函数的this指向window
- 构造函数中的this指向当前的实例
- call、apply、bind能够改变函数的this指向
- 箭头函数中没有this,若是输出this,就会输出箭头函数定义时所在的做用域中的this
全部的函数数据类型都天生自带一个prototype属性,该属性的属性值是一个对象 prototype的属性值中天生自带一个constructor属性,其constructor属性值指向当前原型所属的类 全部的对象数据类型,都天生自带一个_proto_属性,该属性的属性值指向当前实例所属类的原型
promise、generator、async/await
promise: 1.是一个对象,用来传递异步操做的信息。表明着某个将来才会知道结果的时间,并未这个事件提供统一的api,供进异步处理
2.有了这个对象,就可让异步操做以同步的操做的流程来表达出来,避免层层嵌套的回调地狱
3.promise表明一个异步状态,有三个状态pending(进行中),Resolve(以完成),Reject(失败)
4.一旦状态改变,就不会在变。任什么时候候均可以获得结果。从进行中变为以完成或者失败
promise.all() 里面状态都改变,那就会输出,获得一个数组
promise.race() 里面只有一个状态变为rejected或者fulfilled即输出
promis.finally()无论指定无论Promise对象最后状态如何,都会执行的操做(本质上仍是then方法的特例)
复制代码
事件流描述的是从页面中接受事件的顺序,事件 捕获阶段 处于目标阶段 事件冒泡阶段 addeventListener 最后这个布尔值参数若是是true,表示在捕获阶段调用事件处理程序;若是是false,表示在冒泡阶段调用事件处理程序。
一、事件捕获阶段:实际目标div在捕获阶段不会接受事件,也就是在捕获阶段,事件从document到<html>再到<body>就中止了。
二、处于目标阶段:事件在div发生并处理,可是事件处理会被当作是冒泡阶段的一部分。
三、冒泡阶段:事件又传播回文档
阻止冒泡事件event.stopPropagation()
function stopBubble(e) {
if (e && e.stopPropagation) { // 若是提供了事件对象event 这说明不是IE浏览器
e.stopPropagation()
} else {
window.event.cancelBubble = true //IE方式阻止冒泡
}
}
阻止默认行为event.preventDefault()
function stopDefault(e) {
if (e && e.preventDefault) {
e.preventDefault()
} else {
// IE浏览器阻止函数器默认动做的行为
window.event.returnValue = false
}
}
复制代码
在DOM标准事件模型中,是先捕获后冒泡。可是若是要实现先冒泡后捕获的效果, 对于同一个事件,监听捕获和冒泡,分别对应相应的处理函数,监听到捕获事件,先暂缓执行,直到冒泡事件被捕获后再执行捕获事件。
千万不要使用typeof来判断对象和数组,由于这种类型都会返回object。
复制代码
typeOf()是判断基本类型的Boolean,Number,symbol, undefined, String。 对于引用类型:除function,都返回object null返回object。
installOf() 用来判断A是不是B的实例,installof检查的是原型。
toString() 是Object的原型方法,对于 Object 对象,直接调用 toString() 就能返回 [Object Object] 。而对于其余对象,则须要经过 call / apply 来调用才能返回正确的类型信息。
hasOwnProperty()方法返回一个布尔值,指示对象自身属性中是否具备指定的属性,该方法会忽略掉那些从原型链上继承到的属性。
isProperty()方法测试一个对象是否存在另外一个对象的原型链上。
由于js是单线程的。浏览器遇到etTimeout 和 setInterval会先执行完当前的代码块,在此以前会把定时器推入浏览器的
待执行时间队列里面,等到浏览器执行完当前代码以后会看下事件队列里有没有任务,有的话才执行定时器里的代码
复制代码
1.slice(start,end):方法能够从已有数组中返回选定的元素,返回一个新数组,
包含从start到end(不包含该元素)的数组方法
注意:该方法不会更新原数组,而是返回一个子数组
2.splice():该方法想或者从数组中添加或删除项目,返回被删除的项目。(该方法会改变原数组)
splice(index, howmany,item1,...itemx)
·index参数:必须,整数规定添加或删除的位置,使用负数,从数组尾部规定位置
·howmany参数:必须,要删除的数量,
·item1..itemx:可选,向数组添加新项目
3.map():会返回一个全新的数组。使用于改变数据值的时候。会分配内存存储空间数组并返回,forEach()不会返回数据
4.forEach(): 不会返回任何有价值的东西,而且不打算改变数据,单纯的只是想用数据作一些事情,他容许callback更改原始数组的元素
5.reduce(): 方法接收一个函数做为累加器,数组中的每个值(从左到右)开始缩减,最终计算一个值,不会改变原数组的值
6.filter(): 方法建立一个新数组,新数组中的元素是经过检查指定数组中符合条件的全部元素。它里面经过function去作处理
复制代码
vue是一个渐进式的JS框架。他易用,灵活,高效; 能够把一个页面分隔成多个组件;当其余页面有相似功能时,直接让封装的组件进行复用; 他是构建用户界面的声明式框架,只关心图层;不关心具体是如何实现的
Vue的双向数据绑定是由数据劫持结合发布者订阅者实现的。 数据劫持是经过Object.defineProperty()来劫持对象数据的setter和getter操做。 在数据变更时做你想作的事
- 原理 经过Observer来监听本身的model数据变化,经过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通讯桥梁,达到数据变化->视图更新 在初始化vue实例时,遍历data这个对象,给每个键值对利用Object.definedProperty对data的键值对新增get和set方法,利用了事件监听DOM的机制,让视图去改变数据
react总体是函数式的思想,把组件设计成纯组件,状态和逻辑经过参数传入,因此在react中,是单向数据流;
vue的思想是响应式的,也就是基因而数据可变的,经过对每个属性创建Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom。
页面经过mapAction异步提交事件到action。action经过commit把对应参数同步提交到mutation。
mutation会修改state中对于的值。 最后经过getter把对应值跑出去,在页面的计算属性中
经过mapGetter来动态获取state中的值
复制代码
- state中保存着共有数据,数据是响应式的
- getter能够对state进行计算操做,主要用来过滤一些数据,能够在多组件之间复用
- mutations定义的方法动态修改state中的数据,经过commit提交方法,方法必须是同步的
- actions将mutations里面处理数据的方法变成异步的,就是异步操做数据,通store.dispatch来分发actions,把异步的方法写在actions中,经过commit提交mutations,进行修改数据。
- modules:模块化vuex
- hash ——即地址栏URL中的#符号(此hsah 不是密码学里的散列运算) hash 虽然出现URL中,但不会被包含在HTTP请求中,对后端彻底没有影响,所以改变hash不会从新加载页面。
- history ——利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法
这两个方法应用于浏览器的历史记录站,在当前已有的back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改是,虽然改变了当前的URL,但你浏览器不会当即向后端发送请求。
当 Vue.js 用v-for正在更新已渲染过的元素列表时,它默认用“就地复用”策略。 若是数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是简单复用此处每一个元素,而且确保它在特定索引下显示已被渲染过的每一个元素。
key的做用主要是为了高效的更新虚拟DOM。
$route
和$router
的区别
- $route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
- $router是“路由实例”对象包括了路由的跳转方法,钩子函数等。
- 导航守卫 router.beforeEach 全局前置守卫
// main.js 入口文件
import router from './router'; // 引入路由 router.beforeEach((to, from, next) => { next(); }); router.beforeResolve((to, from, next) => { next(); }); router.afterEach((to, from) => { console.log('afterEach 全局后置钩子'); }); 复制代码
路由独享的守卫 你能够在路由配置上直接定义 beforeEnter 守卫
const router = new VueRouter({
routes: [
{
path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ] }) 复制代码
组件内的守卫 你能够在路由组件内直接定义如下路由导航守卫
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 由于当守卫执行前,组件实例还没被建立
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,可是该组件被复用时调用
// 举例来讲,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 因为会渲染一样的 Foo 组件,所以组件实例会被复用。而这个钩子就会在这个状况下被调用。
// 能够访问组件实例 `this`
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用,咱们用它来禁止用户离开
// 能够访问组件实例 `this`
// 好比还未保存草稿,或者在用户离开前,
将setInterval销毁,防止离开以后,定时器还在调用。 } } 复制代码
请求后台资源的模块。
$ npm install axios -S装好
复制代码
而后发送的是跨域,需在配置文件中config/index.js进行设置。后台若是是Tp5则定义一个资源路由。 js中使用import进来,而后.get或.post。返回在.then函数中若是成功,失败则是在.catch函数中
1.不要在模板里面写过多表达式
2.循环调用子组件时添加key
3.频繁切换的使用v-show,不频繁切换的使用v-if
4.尽可能少用float,能够用flex
5.按需加载,能够用require或者import()按需加载须要的组件
6.路由懒加载
- extend 是构造一个组件的语法器。 而后这个组件你能够做用到Vue.component这个全局注册方法里 还能够在任意vue模板里使用组件。 也能够做用到vue实例或者某个组件中的components属性中并在内部使用apple组件。
- Vue.component 你能够建立 ,也能够取组件。
png24位的图片在iE6浏览器上出现背景 解决方案是作成PNG8.也能够引用一段脚本处理.
浏览器默认的margin和padding不一样。 解决方案是加一个全局的*{margin:0;padding:0;}来统一。
IE6双边距bug:块属性标签float后,又有横行的margin状况下,在ie6显示margin比设置的大。
浮动ie产生的双倍距离(IE6双边距问题:在IE6下,若是对元素设置了浮动,同时又设置了margin-left或margin-right,margin值会加倍。) #box{ float:left; width:10px; margin:0 0 0 100px;}
=> 相同点:
1.数据驱动页面,提供响应式的试图组件
2.都有virtual DOM,组件化的开发,经过props参数进行父子之间组件传递数据,都实现了webComponents规范
3.数据流动单向,都支持服务器的渲染SSR
4.都有支持native的方法,react有React native, vue有wexx
=> 不一样点:
1.数据绑定:Vue实现了双向的数据绑定,react数据流动是单向的
2.数据渲染:大规模的数据渲染,react更快
3.使用场景:React配合Redux架构适合大规模多人协做复杂项目,Vue适合小快的项目
4.开发风格:react推荐作法jsx + inline style把html和css都写在js了
vue是采用webpack + vue-loader单文件组件格式,html, js, css同一个文件
复制代码
Redux数据流里,reduces实际上是根据以前的状态(previous state)和现有的action(current action)
更新state(这个state能够理解为上下累加器的结果)
每次redux reducer被执行时,state和action被传入,这个state根据action进行累加或者是'自身消减'(reduce),
进而返回最新的state,这也就是典型reduce函数的用法:state -> action -> state
复制代码
refs就想一个逃生窗,容许咱们之间访问dom元素或者组件实例,能够向组件添加一个ref属性的值是一个回调函数,
它将接受地城dom元素或组件的已挂在实例,做为第一个参数
复制代码
帮组咱们跟踪哪些项目已更改、添加、从列表中删除,key是独一无二的,可让咱们高效的去定位元素,而且操做它
复制代码
三个状态:Mounting(已插入真实的DOM)
Updating(正在被从新渲染)
Unmounting(已移除真实的DOM)
componentDIdMount 在第一次渲染后调用,只在客服端。以后组件已经生成对应的DOM结构,
componentDidUpdate 在组件完成更新后当即调用,在出初始化是不会调用
复制代码
父组件经过props 给子组件传递数据,子组件则是经过调用父组件传给它的函数给父组件传递数据。
复制代码
虚拟DOM至关于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的doom操做,从而提升性能
具体实现步骤:
·用JavaScript对象结构表示DOM树的结构;而后用这个树构建一个真正的DOM树,插到文档中
·当状态变动的时候,从新构造一棵树的对象树,而后用新的树和旧的树进行对比,记录两棵树差别
·把2所记录的差别应用到步骤1所构建的真正的DOM树上,试图就更新了。
复制代码
1.把树形结构按照层级分解,只比较同级元素
2.给列表结构的每一个单元添加key属性,方便比较。在实际代码中,会对新旧两棵树进行一个深度优先的遍历,这样每一个节点都会有一个标记
3.在深度优先遍历的时候,每遍历到一个节点就把该节点和新的树进行对比。若是有差别的话就记录到一个对象里面
Vritual DOM 算法主要实现上面步骤的三个函数:element, diff, patch。而后就能够实际的进行使用
react只会匹配相同的class的component(这里的class指的是组件的名字)
合并操做,条用component的setState方法的时候,React将其标记为dirty.到每个时间循环借宿,React检查全部标记dirty的component从新绘制
4.选择性子树渲染。能够重写shouldComponentUpdate提升diff的性能
复制代码
flux的最大特色,就是数据的‘单向流动’
1.用户访问View
2.View发出用户的Action
3.Dispatcher收到Action,要求state进行相应的更新
4.store更新后,发出一个‘change’事件后,更新页面
复制代码
shouldComponentUpdate 这个方法用来判断是否须要调用render方法从新描绘dom.由于dom的描绘很是消耗性能,
若是咱们在shouldComponentUpdate方法中可以写出更优化的dom diff算法,能够极大的提升性能
复制代码
根据组件的职责一般把组件分为UI组件和容器组件
UI组件负责UI的呈现,容器组件负责管理数据和逻辑
二者经过React-redux提供connect方法联系起来
复制代码
setState经过一个队列机制实现state更新,当执行setState时,会将须要更新的state很后放入状态队列
而不会当即更新this.state,队列机制能够高效地批量更新state。若是不经过setState而直接修改this.state的值
那么该state将不会被放入状态队列中。当下次调用setState并对状态队列进行合并时,就会忽略以前修改的state,形成不可预知的错误
同时,也利用了队列机制实现了setState的异步更新,避免了频繁的重复更新state
同步更新state:
setState 函数并不会阻塞等待状态更新完毕,所以 setNetworkActivityIndicatorVisible 有可能先于数据渲染完毕就执行。
第二个参数是一个回调函数,在setState的异步操做结束而且组件已经从新渲染的时候执行
也就是说,咱们能够经过这个回调来拿到更新的state的值,实现代码的同步
例子:componentDidMount() {
fetch('https://test.com')
.then((res) => res.json())
.then(
(data) => {
this.setState({ data:data });
StatusBar.setNetworkActivityIndicatorVisible(false);
}
复制代码
1.异步加载模块
2.提取第三库
3.代码压缩
4.去除没必要要的插件
复制代码
1、减小代码体积 1.使用CommonsChunksPlugin 提取多个chunk之间的通用模块,减小整体代码体积
2.把部分依赖转移到CDN上,避免每次编译过程都由Webpack处理
3.对一些组件库采用按需加载,避免无用的代码
2、减小目录检索范围
·在使用loader的时候,经过制定exclude和include选项,减小loader遍历的目录范围,从而加快webpack编译速度
3、减小检索路经:resolve.alias能够配置webpack模块解析的别名,对于比较深的解析路经,能够对其配置alias
复制代码
一、首屏加载和按需加载,懒加载
二、资源预加载
三、图片压缩处理,使用base64内嵌图片
四、合理缓存dom对象
五、使用touchstart代替click(click 300毫秒的延迟)
六、利用transform:translateZ(0),开启硬件GUP加速
七、不滥用web字体,不滥用float(布局计算消耗性能),减小font-size声明
八、使用viewport固定屏幕渲染,加速页面渲染内容
九、尽可能使用事件代理,避免直接事件绑定
复制代码
1.减小入口文件体积
2.静态资源本地缓存
3.开启Gzip压缩
4.使用SSR,nuxt.js
复制代码
由来:
300毫米延迟解决的是双击缩放。双击缩放,手指在屏幕快速点击两次。safari浏览器就会将网页缩放值原始比例。因为用户能够双击缩放或者是滚动的操做,
当用户点击屏幕一次以后,浏览器并不会判断用户确实要打开至这个连接,仍是想要进行双击操做
所以,safair浏览器就会等待300ms,用来判断用户是否在次点击了屏幕
解决方案:1.禁用缩放,设置meta标签 user-scalable=no
2.fastclick.js
原理:FastClick的实现原理是在检查到touchend事件的时候,会经过dom自定义事件当即
发出click事件,并把浏览器在300ms以后真正的click事件阻止掉
fastclick.js还能够解决穿透问题
复制代码
在不改变外部行为的前提下,简化结构、添加可读性
2XX(成功处理了请求状态)
200 服务器已经成功处理请求,并提供了请求的网页
201 用户新建或修改数据成功
202 一个请求已经进入后台
204 用户删除成功
3XX(每次请求使用的重定向不要超过5次)
304 网页上次请求没有更新,节省带宽和开销
4XX(表示请求可能出错,妨碍了服务器的处理)
400 服务器不理解请求的语法
401 用户没有权限(用户名,密码输入错误)
403 用户获得受权(401相反),可是访问被禁止
404 服务器找不到请求的网页,
5XX(表示服务器在处理请求的时候发生内部错误)
500 服务器遇到错误,没法完成请求
503 服务器目前没法使用(超载或停机维护)
复制代码
1.服务器首先产生Etag,服务器可在稍后使用它来判断页面是否被修改。本质上,客户端经过该记号传回服务器要求服务器验证(客户端)缓存)
2.304是 HTTP的状态码,服务器用来标识这个文件没有被修改,不返回内容,浏览器接受到这个状态码会去去找浏览器缓存的文件
3.流程:客户端请求一个页面A。服务器返回页面A,并在A上加一个Tage客服端渲染该页面,并把Tage也存储在缓存中。客户端再次请求页面A
并将上次请求的资源和ETage一块儿传递给服务器。服务器检查Tage.而且判断出该页面自上次客户端请求以后未被修改。直接返回304
last-modified: 客服端请求资源,同时有一个last-modified的属性标记此文件在服务器最后修改的时间
客服端第二次请求此url时,根据http协议。浏览器会向服务器发送一个If-Modified-Since报头,
询问该事件以后文件是否被修改,没修改返回304
有了Last-Modified,为何还要用ETag?
一、由于若是在一秒钟以内对一个文件进行两次更改,Last-Modified就会不正确(Last—Modified不能识别秒单位的修改)
二、某些服务器不能精确的获得文件的最后修改时间
三、一些文件也行会周期新的更改,可是他的内容并不改变(仅仅改变修改的事件),这个时候咱们并不但愿客户端认为文件被修改,而从新Get
ETag,为何还要用Last-Modified?
一、二者互补,ETag的判断的缺陷,好比一些图片等静态文件的修改
二、若是每次扫描内容都生成ETag比较,显然要比直接比较修改时间慢的多。
ETag是被请求变量的实体值(文件的索引节,大小和最后修改的时间的Hash值)
一、ETag的值服务器端对文件的索引节,大小和最后的修改的事件进行Hash后获得的。
复制代码
1.get数据是存放在url以后,以?分割url和传输数据,参数之间以&相连; post方法是把提交的数据放在http包的Body中
2.get提交的数据大小有限制,(由于浏览器对url的长度有限制),post的方法提交的数据没有限制
3.get须要request.queryString来获取变量的值,而post方式经过request.from来获取变量的值
4.get的方法提交数据,会带来安全问题,好比登陆一个页面,经过get的方式提交数据,用户名和密码就会出如今url上
复制代码
1.超文本的传输协议,是用于从万维网服务器超文本传输到本地资源的传输协议
2.基于TCP/IP通讯协议来传递数据(HTML,图片资源)
3.基于运用层的面向对象的协议,因为其简洁、快速的方法、适用于分布式超媒体信息系统
4.http请求信息request:
请求行(request line)、请求头部(header),空行和请求数据四部分构成
请求行,用来讲明请求类型,要访问的资源以及所使用的HTTP版本.
请求头部,用来讲明服务器要使用的附加信息
空行,请求头部后面的空行是必须的
请求数据也叫主体,能够添加任意的其余数据。
5.http相应信息Response
状态行、消息报头、空行和响应正文
状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成
消息报头,用来讲明客户端要使用的一些附加信息
空行,消息报头后面的空行是必须的
响应正文,服务器返回给客户端的文本信息。
复制代码
https:是以安全为目标的HTTP通道,简单讲是HTTP的安全版本,经过SSL加密
http:超文本传输协议。是一个客服端和服务器端请求和应答的标准(tcp),使浏览器更加高效,使网络传输减小
复制代码
长链接:HTTP1.0须要使用keep-alive参数来告知服务器创建一个长链接,而HTP1.1默认支持长链接
节约宽带:HTTP1.1支持只发送一个header信息(不带任何body信息)
host域(设置虚拟站点,也就是说,web server上的多个虚拟站点能够共享同一个ip端口):HTTP1.0没有host域
1.http2采用的二进制文本传输数据,而非http1文本格式,二进制在协议的解析和扩展更好
2.数据压缩:对信息头采用了HPACK进行压缩传输,节省了信息头带来的网络流量
3.多路复用:一个链接能够并发处理多个请求
4.服务器推送:咱们对支持HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端须要的资源一块儿推送到客户端,省得客户端再次建立链接发送请求到服务器端获取。这种方式很是合适加载静态资源
复制代码
1.web缓存就是存在于客户端与服务器之间的一个副本、当你第一个发出请求后,缓存根据请求保存输出内容的副本
2.缓存的好处
(1)减小没必要要的请求
(2)下降服务器的压力,减小服务器的消耗
(3)下降网络延迟,加快页面打开速度(直接读取浏览器的数据)
复制代码
1.sql注入原理:是将sql代码假装到输入参数中,传递到服务器解析并执行的一种攻击手法。也就是说,
在一些对server端发起的请求参数中植入一些sql代码,server端在执行sql操做时,会拼接对应参数,
同时也将一些sql注入攻击的“sql”拼接起来,致使会执行一些预期以外的操做。
防范:1.对用户输入进行校验
2.不适用动态拼接sql
2.XSS(跨站脚本攻击):往web页面插入恶意的html标签或者js代码。
举例子:在论坛放置一个看是安全的连接,窃取cookie中的用户信息
防范:1.尽可能采用post而不使用get提交表单
2.避免cookie中泄漏用户的隐式
3.CSRF(跨站请求假装):经过假装来自受信任用户的请求
举例子:黄轶老师的webapp音乐请求数据就是利用CSRF跨站请求假装来获取QQ音乐的数据
防范:在客服端页面增长伪随机数,经过验证码
XSS和CSRF的区别:
1.XSS是获取信息,不须要提早知道其余用户页面的代码和数据包
2.CSRF代替用户完成指定的动做,须要知道其余页面的代码和数据包
复制代码
1.尽量的避开互联网有可能影响数据传输速度和稳定性的瓶颈和环节。使内容传输的更快更稳定。
2.关键技术:内容存储和分发技术中
3.基本原理:普遍采用各类缓存服务器,将这些缓存服务器分布到用户访问相对的地区或者网络中。当用户访问网络时利用全局负载技术
将用户的访问指向距离最近的缓存服务器,由缓存服务器直接相应用户的请求(全局负载技术)
复制代码
客服端发c起请求链接服务器端s确认,服务器端也发起链接确认客服端确认。
第一次握手:客服端发送一个请求链接,服务器端只能确认本身能够接受客服端发送的报文段
第二次握手: 服务端向客服端发送一个连接,确认客服端收到本身发送的报文段
第三次握手: 服务器端确认客服端收到了本身发送的报文段
复制代码
1.查询NDS(域名解析),获取域名对应的IP地址 查询浏览器缓存
2.浏览器与服务器创建tcp连接(三次握手)
3.浏览器向服务器发送http请求(请求和传输数据)
4.服务器接受到这个请求后,根据路经参数,通过后端的一些处理生成html代码返回给浏览器
5.浏览器拿到完整的html页面代码开始解析和渲染,若是遇到外部的css或者js,图片同样的步骤
6.浏览器根据拿到的资源对页面进行渲染,把一个完整的页面呈现出来
复制代码
流程:解析html以及构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树
概念:1.构建DOM树: 渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node(包括js生成的标签)生成内容树
2.构建渲染树: 解析对应的css样式文件信息(包括js生成的样式和外部的css)
3.布局渲染树:从根节点递归调用,计算每个元素的大小,位置等。给出每一个节点所在的屏幕的精准位置
4.绘制渲染树:遍历渲染树,使用UI后端层来绘制每个节点
重绘:当盒子的位置、大小以及其余属性,例如颜色、字体大小等到肯定下来以后,浏览器便把这些颜色都按照各自的特性绘制一遍,将内容呈如今页面上
触发重绘的条件:改变元素外观属性。如:color,background-color等
重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性从新绘制,使元素呈现新的外观
注意:table及其内部元素须要屡次计算才能肯定好其在渲染树中节点的属性值,比同等元素要多发时间,要尽可能避免使用table布局
重排(重构/回流/reflow): 当渲染书中的一部分(或所有)由于元素的规模尺寸,布局,隐藏等改变而须要从新构建,这就是回流。
每一个页面都须要一次回流,就是页面第一次渲染的时候
重排必定会影响重绘,可是重绘不必定会影响重排
复制代码
1.浏览器预先加载css后,能够没必要等待HTML加载完毕就能够渲染页面了
2.其实HTML渲染并不会等到彻底加载完在渲染页面,而是一边解析DOM一边渲染。
3.js写在尾部,主要是由于js主要扮演事件处理的功能,一方面不少操做是在页面渲染后才执行的。另外一方面能够节省加载时间,使页面可以更加的加载,提升用户的良好体验
可是随着JS技术的发展,JS也开始承担页面渲染的工做。好比咱们的UI其实能够分被对待,把渲染页面的js放在前面,时间处理的js放在后面
复制代码
1.indexBD: 是h5的本地存储库,把一些数据存储到浏览器中,没网络,浏览器能够从这里读取数据,离线运用。5m
2.Cookie: 经过浏览器记录信息确认用户身份,最大4kb,这也就限制了传输的数据,请求的性能会受到影响
3.Session: 服务器端使用的一种记录客户状态的机制(session_id存在set_cookie发送到客服端,保存为cookie)
4.localStroage: h5的本地存储,数据永久保存在客服端
复制代码
一、cookie,sessionStorage,localStorage是存放在客户端,session对象数据是存放在服务器上 实际上浏览器和服务器之间仅需传递session id便可,服务器根据session-id找到对应的用户session对象 session存储数据更安全一些,通常存放用户信息,浏览器只适合存储通常的数据 二、cookie数据始终在同源的http请求中携带,在浏览器和服务器来回传递,里面存放着session-id sessionStorage,localStorage仅在本地保存 三、大小限制区别,cookie数据不超过4kb,localStorage在谷歌浏览中2.6MB 四、数据有效期不一样,cookie在设置的(服务器设置)有效期内有效,无论窗口和浏览器关闭 sessionStorage仅在当前浏览器窗口关闭前有效,关闭即销毁(临时存储) localStorage始终有效
SessionStorage和localStorage区别: 1.sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在用一个会话的页面中才能被访问(也就是说在第一次通讯过程当中) 而且在会话结束后数据也随之销毁,不是一个持久的本地存储,会话级别的储存 2.localStorage用于持久化的本地存储,除非主动删除数据,不然不会过时
一、token就是令牌,好比你受权(登陆)一个程序时,他就是个依据,判断你是否已经受权该软件(最好的身份认证,安全性好,且是惟一的)
用户身份的验证方式
二、cookie是写在客户端一个txt文件,里面包括登陆信息之类的,这样你下次在登陆某个网站,就会自动调用cookie自动登陆用户名
服务器生成,发送到浏览器、浏览器保存,下次请求再次发送给服务器(存放着登陆信息)
三、session是一类用来客户端和服务器之间保存状态的解决方案,会话完成被销毁(表明的就是服务器和客户端的一次会话过程)
cookie中存放着sessionID,请求会发送这个id。sesion由于request对象而产生。
复制代码
一、用户经过用户名和密码发送请求
二、服务器端验证
三、服务器端返回一个带签名的token,给客户端
四、客户端储存token,而且每次用于发送请求
五、服务器验证token而且返回数据
每一次请求都须要token
复制代码
一、cookie数据存放在客户的浏览器上,session数据放在服务器上。
二、cookie不是很安全,别人能够分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session。
三、session会在必定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能考虑到减轻服务器性能方面,应当使用COOKIE。
四、单个cookie保存的数据不能超过4K,不少浏览器都限制一个站点最多保存20个cookie。
复制代码
一、session认证只是把简单的User的信息存储Session里面,sessionID不可预测,一种认证手段。只存在服务端,不能共享到其余的网站和第三方App
二、token是oAuth Token,提供的是认证和受权,认证针对用户,受权是针对App,目的就是让某APP有权访问某用户的的信息。Token是惟一的,
token不能转移到其余的App,也不能转到其余用户上。(适用于App)
三、session的状态是存在服务器端的,客户端只存在session id, Token状态是存储在客户端的
复制代码
一、数量和长度的限制。每一个特定的域名下最多生成20个cookie(chorme和safari没有限制)
二、安全性问题。
复制代码
1、观察者模式:juejin.im/post/5a14e9… juejin.im/post/5af05d… 在软件开发设计中是一个对象(subject),维护一系列依赖他的对象(observer),当任何状态发生改变自动通知他们。强依赖关系 简单理解:数据发生改变时,对应的处理函数就会自动执行。一个Subjet,用来维护Observers,为某些event来通知(notify)观察者
2、发布-订阅者 有一个信息中介,过滤 耦合性低 它定义了一种一对多的关系,能够使多个观察者对象对一个主题对象进行监听,当这个主题对象发生改变时,依赖的全部对象都会被通知到。
1.冒泡排序:重复走访过要排序的数列,一次比较两个元素,若是他们的顺序错误就把它们交换过来。
实现过程:1.比较相邻的元素。若是第一个比第二个大,就交换他们两个
2.对每一对相邻元素做一样的工做,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数
3.针对全部的元素重复以上的步骤,除了最后一个
4.重复步骤1-3,直到排序完成。
2.选择排序:首先在未排序序列中找到最小值,放在排序序列的起始位置,而后,在从剩下未排序元素中继续寻找最小值,而后放在与排序序列的末尾
实现过程:
3.插入排序:构建有序序列,对于未排序数据,在已排序序列中冲后向前扫描,找到相应位置并插入
实现过程:1.从第一个元素开始,该元素能够认为已经被排序
2.取出下一个元素,在已排序的元素序列中冲后向前扫描
3.若是该元素(以排序)大于新元素,将元素向后移一位
4.在取出一个元素,比较以前的,直到找到本身合适的位置
4.桶排序:将数据分布到有限数量的桶里,每一个桶在分别排序
1.快速排序:快速排序使用分治法把一个串(list)分为两个子串(sub-lists).具体算法实现
实现过程:1.从数组中挑出一个元素,成为一个基准
2.从新排列数组,全部元素比基准小的摆在基准前面,全部元素比基准大的摆在基准后面(相同的能够摆在一边)
这个分区退出以后,该基准就处于数列的中间位置。成为分区操做。
3.递归的把小于基准值的子数列和大于基准值元素的子数列排序
算法实现: function quickSort (arr) {
if (arr.length <= 1) {return arr}
var destIndex = Math.floor(arr.length/2)
var left = [], right = [];
var dest = arr.splice(destIndex,1)[0];
for (var i =0;i<arr.length;i++){
if (arr[i]<dest) {
left.push(arr[i])
} else {
right.push(arr[i]) }
return quickSort(left).concat([dest],quickSort(right)
2.堆排序:利用对这种数据结构所涉及的一种排序算法,堆积是一个近乎彻底二叉树的结构,并同时知足堆积的性质:即子节点的键值或索引老是小于(或大于)它的父节点。
实现过程:1.
复制代码
1.双重循环
2.indexOf
3.数组排序去重 最快你Olong
复制代码
判断回文字符串:(递归的思想)
1.字符串分隔,倒转,聚合[...obj].reverse().join('')
2.字符串头部和尾部,逐次向中间检测
实现:function isPalindrome(line) {
line += '';
for (var i=0,j=line.length-1;i<j;i++,j--) {
if (line.chartAt(i) !== line.chartAt(j) {
return false
}
3.递归
复制代码
二分查找能够解决已排序数组的查找问题,即只要数组中包含T(要查找的值),那么经过不断的缩小包含T的数据范围,就能够最终要找到的数
(1) 一开始,数据范围覆盖整个数组。
(2) 将数组的中间项与T进行比较,若是T比数组的中间项小,则到数组的前半部分继续查找,反之,则到数组的后半部分继续查找。
(3) 就这样,每次查找均可以排除一半元素,至关于范围缩小一半。这样反复比较,反复缩小范围,最终会在数组中找到T
代码实现:function binarySearch (data, dest, start, end){
var end = end || data.length-1;
var start = start || 0;
var m = Math.floor((start+end)/2);
if (dest<data[m]){
return binarySearch(data, dest, 0, m-1)
} else {
return binarySearch(data, dest, m+1, end)
}}
return false
复制代码
一句话归纳:1.bind()返回一个新函数,并不会当即执行。
2.bind的第一个参数将做为他运行时的this,以后的一系列参数将会在传递的实参前传入做为他的参数
3.bind返回函数做为构造函数,就是能够new的,bind时指定的this值就会消失,但传入的参数依然生效
复制代码
Function.prototype.bind = function (obj, arg) { var arg = Array.prototype.slice.call(arguments, 1); var context = this; var bound = function (newArg) { arg = arg.concat(Array.prototype.slice.call(newArg); return context.apply(obj, arg) } var F = function () {} // 在new一个bind会生成新函数,必须的条件就是要继承原函数的原型,所以用到寄生继承来完成咱们的过程 F.prototype = context.prototype; bound.prototype = new F(); return bound; } 复制代码
ajax的原理:至关于在用户和服务器之间加一个中间层(ajax引擎),使用户操做与服务器响应异步化。
优势:在不刷新整个页面的前提下与服务器通讯维护数据。不会致使页面的重载
能够把前端服务器的任务转嫁到客服端来处理,减轻服务器负担,节省宽带
劣势:不支持back。对搜索引擎的支持比较弱;不容易调试
怎么解决呢?经过location.hash值来解决Ajax过程当中致使的浏览器前进后退按键失效,
解决之前被人常遇到的重复加载的问题。主要比较先后的hash值,看其是否相等,在判断是否触发ajax
复制代码
function getData(url) { var xhr = new XMLHttpRequest(); // 建立一个对象,建立一个异步调用的对象 xhr.open('get', url, true) // 设置一个http请求,设置请求的方式,url以及验证身份 xhr.send() //发送一个http请求 xhr.onreadystatechange = function () { //设置一个http请求状态的函数 if (xhr.readyState == 4 && xhr.status ==200) { console.log(xhr.responseText) // 获取异步调用返回的数据 } } } Promise(getData(url)).resolve(data => data) AJAX状态码:0 - (未初始化)尚未调用send()方法 1 - (载入)已调用send方法,正在发送请求 2 - (载入完成呢)send()方法执行完成 3 - (交互)正在解析相应内容 4 - (完成)响应内容解析完成,能够在客户端调用了 ``` #### 3、函数节流(throttle) ``` function throttle (func, wait) { var timeout; var previous = 0; return function () { context = this; args = arguments; if (!timeout) { timeout = setTimeout(() => { timeout = null; func.apply(context,args) }, wait); } } } } ``` #### 4、函数防抖(dobounce) ``` function debounce (func, wait) { var timeout; return function() { var context = this; var args = arguments; clearTimeout(timeout); timeout = setTimeout(() => { func.apply(context,args) }, wait); } } ``` #### 5、实现一个函数clone,能够对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制 ``` Object.prototype.clone = function() { var newObject = this.constructor === Array ? [] : {} //对象的深拷贝 获取对应的构造函数 [] 或者 {} for (let e in this) { //遍历对象的属性 in this[e] newObject[e] = typeof this[e] === 'object' ? this[e].clone() : this[e] //对象中的属性若是仍是对象 那就继续递归 不然就返回基本的数据类型 } return newObject } ``` #### 6、实现一个简单的Promise https://juejin.im/post/5b2f02cd5188252b937548ab ``` class Promise { constructor (executor) { // executor里面有两个参数,一个叫resolve(成功),一个叫reject(失败)。 this.status = 'pending', this.value = undefined; this.reason = undefined; // 成功存放的数组 this.onResolvedCallbacks = []; // 失败存放法数组 this.onRejectedCallbacks = []; let resolve = (value) => { if (this.status == 'pending') { this.status = 'resolve'; this.value = value; this.onResolvedCallbacks.forEach(fn => fn()) } } let reject = (reason) => { if (this.status == 'pending') { this.status = 'reject'; this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn()) } } try{ executor(resolve, reject); } catch (err) { reject(err); } } then (onFullFilled,onRejected) { if (this.status == 'resolved') { onFullFilled(this.value) } if (this.status == 'rejectd') { onRejected(this.reason); } if (this.status == 'pending') { this.onResolvedCallbacks.push(()=>{ onFullFilled(this.value); }) this.onRejectedCallbacks.push(()=> { onRejected(this.reason); }) } } } const p = new Promise((resolve, reject) => { setTimeout(() => { resolve('hello world') }, 1000); }) p.then((data) =>{ console.log(data) },(err) =>{ console.log(err); }) ``` #### 7、发布订阅者模式(观察者模式) ``` var event = {}; // 发布者 event.clientList = [] //发布者的缓存列表 event.listen = function (fn) { // 增长订阅者函数 this.clientList.push(fn) } event.trigger = function () { // 发布信息 for (var i =0;i<this.clientList.length;i++) { var fn = this.clientList[i]; fn.apply(this, arguments); } } event.listen (function(time) { console.log('正式上班时间为:' +time) }) event.trigger ('2018/7') ``` #### 8、手动写一个node服务器 ``` const http = require('http'); const fs = require('fs'); const server = http.createServer((req,res) => { if (reu.url == '/') { const indexFile = fs.createReadStream('./index.html') req.writeHead(200,{'context-Type':'text/html;charset = utf8}) indexFile.pipe(res) } server.listen(8080)