几种缓存的总结
几种缓存的总结
1 DNS缓存
- 为了增加访问效率,计算机有域名缓存机制,当访问过某个网站并得到其IP后,会将其域名和IP缓存下来,下一次访问的时候,就不需要再请求域名服务器获取IP,直接使用缓存中的IP,提高了响应的速度。当然缓存是有有效时间的,当过了有效时间后,再次请求网站,还是需要先请求域名解析。
- 但是域名缓存机制也可能会带来麻烦。例如IP已变化了,仍然使用缓存中的IP来访问,将会访问失败。再如 同一个域名在内网和外网访问时所对应的IP是不同的,如在外网访问时通过外网IP映射到内网的IP。同一台电脑在外网环境下访问了此域名,再换到内网来访问此域名,在DNS缓存的作用下,也会去访问外网的IP,导致访问失败。根据情况,可以手动清除DNS缓存或者禁止DNS缓存机制。
2 CDN缓存
- 用户在浏览网站的时候,浏览器能够在本地保存网站中的图片或者其他文件的副本,这样用户再次访问该网站的时候,浏览器就不用再下载全部的文件,减少了下载量意味着提高了页面加载的速度。
- 如果中间加上一层CDN,客户端浏览器先检查是否有本地缓存是否过期,如果过期,则向CDN边缘节点发起请求,CDN边缘节点会检测用户请求数据的缓存是否过期,如果没有过期,则直接响应用户请求,此时一个完成http请求结束;如果数据已经过期,那么CDN还需要向源站发出回源请求(back to the source request),来拉取最新的数据
3 浏览器端缓存
http缓存 localStorage缓存 sessionStorage缓存 cookies缓存 application cache缓存
4 服务器缓存
如何解决移动端两栏自适应的问题
如何解决移动端两栏自适应的问题?overflow:hidden
要求:第一水平方向不要有滚动条;第二,水平第一个侧栏宽度固定,第二个侧栏宽度自适应
1 明确元素的宽度:块级元素 默认占据整行,如果不设置宽度,则默认和父元素等宽;行内块元素的宽度由内容决定,可以自行设置;行内元素的宽度由内容决定,不可设置宽高;
2 设置了浮动或者定位的层的宽宽由内容决定,发生元素转换,display:inline-block;
3 目的是实现 :右边栏的宽度 = 屏幕宽度 - 左边栏宽度 ,以此来实现右边栏里面的内容进行百分比设置宽度以自适应屏幕的时候,是以 右边栏的宽度 = 屏幕宽度 - 左边栏宽度 为基准的。
4 注意理解块级元素的流体特性:在默认情况下(非浮动、定位),块级元素会默认在水平方向自动填满外部的容器(自动填满父元素)。
5 浮动元素left和触发了BFC特性的元素right,right栏自适应,right设置overflow:hdden,触发BFC特性,即可实现right自动填充剩余的空间,而不是那种文字环绕图片的效果。
|
|
6 注意:高潮来了,如何设置left和right之间的间隙呢?
- 给right设置margin-right 或者 padding-left
|
|
|
|
- 给left设置margin-right 或者 padding-right 来撑开两栏之间的间隙
|
|
7 BFC自适应布局的组件化代码
|
|
8 如果是右边栏宽度固定,左边栏宽度自适应呢?
解析顺序不同会导致占位不同,所以只需要将右边写在左边前面即可
|
|
Angular Js angularModule
1 模块的定义
module是angular中重要的模块组织方式,它提供了将一组内聚的业务组件(controller、service、filter、directive…)封装在一起的能力。这样做可以将代码按照业务领域问题分module的封装,然后利用module的依赖注入其关联的模块内容,使得我们能够更好的”分离关注点“,达到更好的”高内聚低耦合“。”高内聚低耦合“是来自面向对象设计原则。内聚是指模块或者对象内部的完整性,一组紧密联系的逻辑应该被封装在同一模块、对象等代码单元中,而不是分散在各处;耦合则指模块、对象等代码单元之间的依赖程度,如果一个模块的修改,会影响到另一个模块,则说明这两模块之间是相互依赖紧耦合的。
同时module也是我们angular代码的入口,首先需要声明module,然后才能定义angular中的其他组件元素,如controller、service、filter、directive、config代码块、run代码块等。
关于module的定义为:angular.module(‘com.ngbook.demo’, [])。关于module函数可以传递3个参数,它们分别为:
- name:模块定义的名称,它应该是一个唯一的必选参数,它会在后边被其他模块注入或者是在ngAPP指令中声明应用程序主模块;
- requires:字符串的参数列表;模块的依赖,它是声明本模块需要依赖的其他模块的参数。特别注意:如果在这里没有声明模块的依赖,则我们是无法在模块中使用依赖模块的任何组件的;它是个可选参数。
- configFn: 模块的启动配置函数,在angular config阶段会调用该函数,对模块中的组件进行实例化对象实例之前的特定配置,如我们常见的对$routeProvider配置应用程序的路由信息。它等同于”module.config“函数,建议用”module.config“函数替换它。这也是个可选参数。
我们可以打印出来angular全局对象和angular.module()这个方法返回的对象来更深入的了解它们之间的关系
|
|
2 声明module之后,其他组件元素,如controller、service、filter、directive、config代码块、run代码块也就可以在对应的模块上使用了。
Object对象assign方法
JS中深拷贝和浅拷贝
一 : 先来区分下一个小的细节 点操作符 和 [ ] 操作 对象属性的时候的区别
|
|
|
|
|
|
二 下面来实现一个浅拷贝的源码: 浅拷贝是指在复制一个对象的时候,仅仅对第一层的键值对进行复制,第二层的对象复制的是一个地址
|
|
三 深拷贝原理如下:用到了递归
|
|
注意数组的slice和concat方法其实是一种浅复制
|
|
Object assign
1 先来看下字符串,数字和布尔类型转化为对象包装类
|
|
2 Object.assign(target,source1,source2,······);该方法会将source1,2对象的 可枚举的属性复制到target对象上,然后返回target对象
2.1 如果只传了一个参数,那么直接返回该参数,(如果传的是基本数据类型null和undefined会报错),基本数据类型转化为包装对象,复杂数据类型直接返回
|
|
2.2 如果传递了多个参数,那么进行赋值拷贝,注意assign方法执行的是浅拷贝,也就是说如果键值的值是复杂数据类型,那么复制的是地址,如果source有包装类型字符串可以进行赋值,null undefined 数字以及布尔类型会跳过
|
|
2.3 如果对象target的属性和source的属性名有重复的,那么会进行合并覆盖
|
|
2.4 原型上的属性以及不可枚举的属性不会被复制
|
|
3 assign经常的用法,以下代码都是有联系的
|
|
3.1 为对象添加属性
|
|
3.2 为对象添加方法
|
|
3.3 克隆对象
|
|
3.4 合并多个对象
|
|
3.5 为属性指定默认值
|
|
Arrayfrom API ES6
Array.from(arrayLike[, mapFn[, thisArg]]) 该方法从一个类似数组或可迭代对象创建一个新的数组实例
- 第一个参数是一个类数组对象,
- 第二个参数作为map函数的callback执行,
- 第三个参数是执行mapFn时候的this指向
- 返回值是一个新的数组实例
关于类数组对象只要该对象中有length属性, 即可认为是类数组对象
1 将类数组转化为数组
先抛出一个问题,这个也是在网上看到的
如何不使用loop循环,创建一个长度为100的数组,并且每个元素的值等于它的下标?
以下测试均在chorm浏览器,火狐有的版本会直接初始化为undefined
|
|
如果使用Array.from就很简单了
|
|
然后通过Object.keys(obj) 该方法返回obj对象的所有可枚举的属性的键值组成的 数组;
|
|
当然了上面这些是ES6的新特性,如何在ES5中达到类似的效果呢?方法其实也很多
方法1 :
|
|
方法2 :
|
|
然后同样调用Object.keys(obj)方法即可;
2 将类数组转化的数组实例通过mapFn函数加工,返回一个加工后的数组
|
|
Array API ES6
ES5 数组新增API
1 数组的length属性,该属性是可读可写的
|
|
2 Array.isArray(value) 该方法用来判断传递进来的参数是不是数组,如果是则返回true,否则返回false;
Array.from(arrayLike[, mapFn[, thisArg]])
参数
arrayLike
想要转换成真实数组的类数组对象 (只要该对象有length属性即可)或可遍历对象
mapFn
可选参数,如果指定了该参数,则最后生成的数组会经过该函数的加工处理后再返回。
thisArg
可选参数,执行 mapFn 函数时 this 的值。
返回值
一个新的Array实例
|
|
3 Array.prototype.map (callback,thisArg ) 数组的map方法将向callback函数中传递三个参数,依次是每个数组元素,当前数组元素的索引,当前数组,callback执行的返回值 会作为数组元素添加到一个新的数组中去;
|
|
|
|
|
|
|
|
在网上又看到了一个更好地办法
|
|
|
|
3.1 callback 函数只会在有值的索引上被调用;那些数组中未初始化的元素或者使用 delete删除的索引则不会被调用
|
|
4 Array.prototype.forEach( callback , thisArg ) 数组的forEach 方法向callback回调函数中传递3 个参数,依次是每个数组元素,当前数组元素的索引,当前数组,forEach API 不像map API ,forEach每次执行callback并没有接受返回值,也不会返回一个数组,而map会将callback的返回值(如果没有显式的返回,则默认undefined),形成一个新的数组,然后返回这个新的数组;
|
|
|
|
4.1 forEach 没有办法中止或者跳出 forEach 循环,除了抛出一个异常
|
|
|
|
4.2 如果在遍历的过程中,某个元素被删除了,那么会直接跳过该元素
|
|
4.3 forEach函数的返回值是undefined,所以它不能像map或者reduce函数那样,可以链式调用数组的方法,因为map函数会将callback每次的返回值存在一个数组中整体返回
|
|
4.4 forEach 方法按升序为数组中含有效值的每一项执行一次callback 函数,那些已删除(使用delete方法等情况)或者未初始化的项将被跳过(但不包括那些值为 undefined 的项)
|
|
5 Array.prototype.every( callback , thisArg ) 数组的every方法向callback回调函数中传递3 个参数,依次是每个数组元素,当前数组元素的索引,当前数组,返回值是布尔类型;当执行某个元素返回值是false的时候,终止every函数的执行,返回false;只有当每个元素执行结果为true,最终才能返回true;
而 Array.prototype.some(callback ,thisArg) 和every基本上一样,只要有一个数组元素执行callback结果是true,那么就返回true,停止当前循环,不再进行后面的循环遍历操作;
|
|
|
|
6 Array.prototype.reduce(callback ,[initialValue]) (reduceRight函数和reduce函数类似,只不是从数组的最后反向开始迭代);数组的reduce方法向callback函数传递四个参数,分别是
|
|
reduce如何工作?
|
|
callback |
accumulator |
currentValue |
currentIndex |
array |
return value |
---|---|---|---|---|---|
first call | 0 |
1 |
1 |
[0, 1, 2, 3, 4] |
1 |
second call | 1 |
2 |
2 |
[0, 1, 2, 3, 4] |
3 |
third call | 3 |
3 |
3 |
[0, 1, 2, 3, 4] |
6 |
fourth call | 6 |
4 |
4 |
[0, 1, 2, 3, 4] |
10 |
|
|
callback |
accumulator |
currentValue |
currentIndex |
array |
return value |
---|---|---|---|---|---|
first call | 10 |
0 |
0 |
[0, 1, 2, 3, 4] |
10 |
second call | 10 |
1 |
1 |
[0, 1, 2, 3, 4] |
11 |
third call | 11 |
2 |
2 |
[0, 1, 2, 3, 4] |
13 |
fourth call | 13 |
3 |
3 |
[0, 1, 2, 3, 4] |
16 |
fifth call | 16 |
4 |
4 |
[0, 1, 2, 3, 4] |
20 |
reduce将callback函数的返回值作为accumulator传递给callback重复执行;
ruduce函数经常用来扁平化数组
|
|
7 Array.prototype.filter( callback ,thisArg ) filter向callback传递参数 依次是每个数组元素,当前数组元素的索引,当前数组。该方法返回一个新的数组,不改变原数组; filter函数对每个数组元素进行判断,满足条件的会保存下来,返回到新的数组当中,不满足条件的话进行下一个数组元素的判断(其实本质是如果callback函数返回true,那么保留当前数组元素,如果callback函数返回false,不保留该数组元素,那么进行对下一个数组元素的判断)
|
|
8 Array.prototype.keys( ) 返回的结果是一个Array迭代器
|
|
9 Array.prototype.indexOf()
indexOf
使用strict equality (无论是 ===, 还是 triple-equals操作符都基于同样的方法)进行判断 searchElement与
数组中包含的元素之间的关系。
注意比较下面的情况,对于复杂数据类型,比较的是引用地址是否指向同一个地址,如果是则能找到,返回其对应的索引值,如果不是,则找不到,返回-1
|
|
|
|
Array Sort
数组的sort方法—-改变原数组
简单粗暴直接上代码咯(sort方法的定义请查阅W3C或者搜索)
注意:sort(fn) 方法可以接受一个 方法为参数 ,这个方法有两个参数。分别代表每次排序比较时的两个数组项。sort()排序时每次比较两个数组项都回执行这个参数,并把两个比较的数组项作为参数传递 给这个函数。
当函数返回值为 1 的时候就交换两个数组项的顺序,否则就不交换。
sort方法排序的关键是在于传入函数的返回值;改变原数组,并不产生新的数组;如果fn这个参数被省略,那么元素将按照 ASCII 字符顺序进行升序排列。
一 数字类型数组排序
|
|
|
|
|
|
|
|
二 字符串数组排序
那么如何才能排序字符串呢?这个之前需要先了解,字符串的比较 < <= > >= 返回一个布尔类型的值
对于字符串,第一个字符串中每个字符的代码都与会第二个字符串中对应位置的字符的代码进行数值比较。完成这种比较操作后,返回一个 Boolean 值。
所以对于字符串的排序,需要进行比较运算的运用,判断字符代码的大小,然后选择返回 1 -1 还是 0
|
|
|
|
此方法通用数字数组
三 如果数组里面存放一组对象呢?如何按照对象的某一个数据进行排序?
|
|
四 如何打乱一个随机数组
|
|
或者更简洁
|
|
Git command detail Reset
1 撤销修改
git checkout – index.html
一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次 git commit 或 git add 时的状态。
git reset HEAD index.html
git reset 命令既可以回退版本,也可以把暂存区的修改回退到工作区;也就是说将添加到暂存区的修改退回到工作区;当我们用HEAD时,表示最新的版本。
再用git status查看一下,现在暂存区是干净的,工作区有修改: