【转载】前端面试攻略

转载地址:https://blog.csdn.net/mus123/article/details/105323672

该博主看起来挺厉害的百度携程滴滴头条360的offer都有,

我马上也要人生第一次前端实习面试了是美团的所以刷题看看人家的面经~

链接:https://m.sohu.com/a/236608417_690895
这个各方面都有吧能找到答案的我一般都做了传送门

文章目录

一、算法部分

如果你算法不好就可以直接告诉面试官。不需要过多作假,面试官其实也很聪明的,如果你作弊很快就能发现的。

1、基本排序的方式

img

冒泡、快排、桶排、堆排序、归并排序、插入排序。

(1)冒泡:排序思路:遍历数组,每次遍历就将最大(或最小)值推至最前。越往后遍历查询次数越少, 跟插入排序刚好相反。

(2)快排:选择一个元素作为基数(通常是第一个元素),把比基数小的元素放到它左边,比基数大的元素放到它右边(相当于二分),再不断递归基数左右两边的序列。

(3)桶排:取 n 个桶,根据数组的最大值和最小值确认每个桶存放的数的区间,将数组元素插入到相应的桶里,最后再合并各个桶。(n个容量至少为1的桶,从大到小,每次的数字放到对应桶的排序好的位置)

(4)堆排序:因为js模拟二叉树比较麻烦,所以堆排序的优势用js语言无法体现, 相对而言C语言的链表在实现上更能表现堆排序,堆排序或许更适合指针类的计算机语言

形成大顶堆,然后顶和末尾叶节点交换,堆容量递减。并且每次构建完上边的堆要回去看一下其子堆有没有受到影响,(太麻烦了不写了,我解读一个别人的吧)

(5)归并排序:递归将数组分为两个序列,有序合并这两个序列(递归向下)

写的时候一直死递归,超出堆栈(但是我明明谢了结束条件了啊,发现有一个地方逗号写成了.然后块级作用域变量left、right忘了加let导致污染,真是难顶)

(6)插入排序:以第一个元素作为有序数组,其后的元素通过在这个已有序的数组中找到合适的位置并插入。

var arr=[1,3,6,9,2,7,5,4,8,3];//十位数
console.log(arr);
function swap(a,i,j){
      
      
    let t=a[i];
    a[i]=a[j];
    a[j]=t;
}
/** */

// //1.冒泡 稳定 n方
// function PopSort(arr){
// let len=arr.length;
// for(let i=0;i<len;i++)
// for(let j=0;j<len-i;j++)
// if(arr[j]>arr[j+1])swap(arr,j,j+1);//如果比右边的大就交换
// }
// PopSort(arr);

// //2.快排 不稳定 nlogn
// function QuickSort(arr){
// let len=arr.length;
// if(len<=1)return arr;//结束条件,如果arr长度为1或0
// let left=[];
// let right=[];
// let p=arr[0];
// for(let i=1;i<len;i++){//比基小放左边,反之放右边
// if(arr[i]<=p)left.push(arr[i]);
// else right.push(arr[i]);
// }
// //返回的是左边+基+右边
// return QuickSort(left).concat(p,QuickSort(right));
// }
// arr=QuickSort(arr);

// //3.桶排序 稳定 n+k
// function buckerSort(arr,n){
// let len=arr.length;
// let max=Math.max(…arr);
// let min=Math.min(…arr);
// let range=Math.ceil((max-min)/n)||1;//取到桶容量大小
// let ranges=[];
// let bucker=new Array(n).fill(0);//保证元素不为空才能用map
// bucker=bucker.map((b)=>{
// return [];
// })//写成二维数组
// for(let i=1;i<=n;i++){
// ranges.push(min+range*i);//得到各个桶的范围(最大值)
// }
// arr.map((a)=>{
// for(let i=0;i<n;i++){//便利n个桶
//
// if (a<=ranges[i])
// {
// let f=0;
// var l=bucker[i].length||0;
// for(let j=0;j<l;j++)
// if(bucker[i][j]>a){bucker[i].splice(j,0,a);f=1;break;}//插到特定位置,并跳出
//
// if(f==0){bucker[i].push(a);}//如果原来是空直接push
// break;//如果能插入桶就跳出
// }
// }
// })
// let s=[];
// bucker=bucker.map(b=>{
// s.push(…b);
// })
// return s;

// }
// arr=buckerSort(arr,3);

// //4.堆排序 不稳定 nlogn
// function heapSort(){
// function maxHeapify(array, index, heapSize) {//调整形成大顶堆
// var iMax, iLeft, iRight;
// while (true) {
// iMax = index;
// iLeft = 2 * index + 1;//左孩子
// iRight = 2 * (index + 1);//右孩子
// if (iLeft < heapSize && array[index] < array[iLeft]) {
// iMax = iLeft;
// }

// if (iRight < heapSize && array[iMax] < array[iRight]) {
// iMax = iRight;
// }
// //检查该三节点小堆是否符合大顶
// if (iMax != index) {//如果不符合,能交换,但是要向下审查
// swap(array, iMax, index);
// index = iMax;//把基准换成被交换到子节点的节点
// } else {//如果没发生交换,说明下面更没有可能变动
// break;
// }
// }
// }
// function buildMaxHeap(array) {//堆构建
// var i, iParent = Math.floor(array.length / 2) - 1;//得到最后一个非叶节点

// for (i = iParent; i >= 0; i–) {//从非叶节点开始往前做堆调整,以此节点i为基准(即小堆父)
// maxHeapify(array, i, array.length);
// }
// }

// function sort(array){//起点
// buildMaxHeap(array);//先构筑一个大顶堆
// for (var i = array.length - 1; i > 0; i–) {//从最后一个节点开始向前做大顶堆与叶节点的交换
// swap(array, 0, i);//交换堆顶与堆尾
// maxHeapify(array, 0, i);//重调大顶,不包括末尾节点
// }
// //循环进行完之后,从尾部向头部变成当前堆最大的值
// return array;
// }
// return sort(arr);
// }
// arr=heapSort(arr)
// //5.归并排序 稳定 nlogn
// function mergeSort(arr){

// function sort(array){
// let len=array.length;
// if(len<=1)return array;

// let mid=Math.floor(len/2);
// let left=array.slice(0,mid);
// let right=array.slice(mid,len);
// return merge(sort(left),sort(right));
// }
// function merge(left,right){
// let s=[];
// while(left.length>0&&right.length>0){
// if(left[0]<right[0]){
// s.push(left.shift());
// }
// else{
// s.push(right.shift());
// }

// }

// return s.concat(left,right);
// }

// return sort(arr);
// }
// arr=mergeSort(arr);
// //6.插入排序 稳定 n方
// function insertSort(arr){
// for(let i=0;i<arr.length;i++){
// for(let j=i;j<arr.length;j++)
// if(arr[i]>arr[j]){
// let t=arr[j];
// arr.splice(j,1);//取出这个数
// arr.splice(i,0,t);//插到比他大的那个数前面
// }
// }
// }
// insertSort(arr);

/** */
console.log(arr);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161

上边六种都通过了;冒泡和插入比较简单并且都稳定,但是复杂度较高。快排是在方便实现的里面稳定性和复杂度都比较好的了

2、二分查找。

//首先保证查找序列有序唯一,用快排排个序
let arr=[808,6,9,51,33,54,4];
function QuickSort(arr){
    
    
    let len=arr.length;
    if(len<=1)return arr;//结束条件,如果arr长度为1或0
        let left=[];
        let right=[];
        let p=arr[0];
        for(let i=1;i<len;i++){
    
    //比基小放左边,反之放右边
            if(arr[i]<=p)left.push(arr[i]);
            else right.push(arr[i]);
        }
        //返回的是左边+基+右边
        return QuickSort(left).concat(p,QuickSort(right));
}
arr=QuickSort(arr);
let k=4;//查个4,保证肯定在里面
let key=binarySearch(arr,k,0,arr.length);
console.log(`查${
      
      k}在第${
      
      key+1}个\n`,arr);
/** */
function binarySearch(arr,k,low,high){
    
    
    if(arr.length<1)return;
    let mid=Math.floor((low+high)/2);
    if(arr[mid]==k)return mid;
    else if(arr[mid]>k){
    
    
        return binarySearch(arr,k,low,mid-1);
    }
    else{
    
    
        return binarySearch(arr,k,mid+1,high);
    }
}

 
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

3.二叉树便利(前序中序后序)

https://blog.csdn.net/zsy_snake/article/details/80353336

4.尽量刷牛客和剑指offer

二、计算机网络部分

1.最重要的就是http协议。毕竟前端大多都和http协议搞事情。

http协议大多包含了以下几种问题吧

  • http请求报文解构都包含什么

    请求行(请求方法+url+http协议版本号)

    GET:获取资源
    客户端—-GET(访问某个资源)—–>服务器

    POST:发给服务器的参数全部放在请求体中
    客户端—-POST(上传某个信息)—–>服务器

    PUT:传输文件(PUT自身不带验证机制,任何人都可以传,不安全)
    客户端—-PUT(上传一个文件)—–>服务器

    HEAD:获得报文首部(不返回主体部分,只返回响应的首部)
    客户端—-HEAD(把那个相关信息告诉我)—–>服务器

    DELETE:删除文件(与PUT相反,不安全)
    客户端—-HEAD(把那个文件删除)—–>服务器

    OPTIONS:询问支持的方法(查询对请求URI指定资源支持的方法)
    客户端—-OPTIONS(这个资源支持哪些方法访问)—–>服务器

    请求头(存放请求信息,缓存)

    Host: 指定请求的服务器的域名和端口号 --域名端口号
    Accept: 指定客户端能够接受的内容类型 – 类型
    Accept-Charset: 浏览器可以接受的字符编码集 --编码集
    Accept-Encoding: 指定浏览器可以支持的web服务器返回内容压缩编码类型 – 内容压缩编码类型
    Accept-Language: 浏览器可接受的语言 – 语言
    Accept-Ranges:可以请求网页实体的一个或多个子范围字段 – 子范围字段
    AuthorizationHTTP:授权证书
    Cache-Control: 指定请求和响应遵循的缓存机制
    Connection:表示是否需要持久连接 --连接
    CookieHTTP: 请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器 – cookie
    Content-Length:请求的内容长度 – 长度

    正文(数据实体)

  • http协议常用的状态码

    参见:https://www.jianshu.com/p/b58025e61b2d

    分类 描述
    1** 信息。服务器收到请求,请继续执行请求
    2** 成功。请求被成功接收并处理
    3** 重定向。需要进一步操作来完成请求
    4** 客户端错误。无法完成请求,或请求包含语法错误
    5** 服务器错误。服务器在处理请求的过程中发成错误

    -100继续请求者应当继续提出请求。服务器已收到请求的一部分,正在等待其余部分。
    101切换协议请求者已要求服务器切换协议,服务器已确认并准备切换。
    -200成功服务器已成功处理了请求。
    -201已创建请求成功并且服务器创建了新的资源。
    -202已接受服务器已接受请求,但尚未处理。
    -203非授权信息服务器已成功处理了请求,但返回的信息可能来自另一来源。
    -204无内容服务器成功处理了请求,但没有返回任何内容。
    -205重置内容服务器成功处理了请求,内容被重置。
    206部分内容服务器成功处理了部分请求。
    -300多种选择针对请求,服务器可执行多种操作。
    -301永久移动请求的网页已永久移动到新位置,即永久重定向。
    -302临时移动请求的网页暂时跳转到其他页面,即暂时重定向。
    303查看其他位置如果原来的请求是 POST,重定向目标文档应该通过 GET 提取。
    -304未修改,此次请求返回的网页未修改,继续使用上次的资源。
    -305使用代理请求者应该使用代理访问该网页。
    307临时重定向请求的资源临时从其他位置响应。
    -400错误请求,服务器无法解析该请求。
    -401未授权请求,没有进行身份验证或验证未通过。
    -403禁止访问服务器拒绝此请求。
    -404未找到服务器找不到请求的网页。
    -405方法禁用服务器禁用了请求中指定的方法。
    -406不接受,无法使用请求的内容响应请求的网页。
    407需要代理授权请求者需要使用代理授权。
    -408请求超时服务器请求超时。
    -409冲突,服务器在完成请求时发生冲突。
    -410已删除请求的资源已永久删除。
    411需要有效长度服务器不接受不含有效内容长度标头字段的请求。
    412未满足前提条件服务器未满足请求者在请求中设置的其中一个前提条件。
    -413请求实体过大请求实体过大,超出服务器的处理能力。
    414请求 URI 过长请求网址过长,服务器无法处理。
    415不支持类型请求的格式不受请求页面的支持。
    416请求范围不符页面无法提供请求的范围。
    417未满足期望值服务器未满足期望请求标头字段的要求。
    -500服务器内部错误服务器遇到错误,无法完成请求。
    -501未实现服务器不具备完成请求的功能。
    -502错误网关服务器作为网关或代理,从上游服务器收到无效响应。

    -503服务不可用服务器目前无法使用。

    -504网关超时服务器作为网关或代理,但是没有及时从上游服务器收到请求。
    -505HTTP 版本不支持服务器不支持请求中所用的 HTTP 协议版本。

  • http头部关于缓存的字段(浏览器缓存控制机制有两种:HTML Meta标签 和 HTTP头信息)

    强缓存定义: 在缓存未失效时候,浏览器向服务端发起请求,直接从缓存中获取数据,
    Expires的值为web服务器返回的到期时间(GMT 格林威治时间),浏览器下次请求时间小于服务器返回的时间则浏览器直接从缓存中获取数据,而不用再次发送请求。
    cache-control常见的取值:private, public, no-cache, max-age, no-store
    private : 客户端可以缓存
    public : 客户端和代理服务器都可缓存
    max-age= : 缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)
    no-cache : 并不是不缓存,是会被缓存的,只不过每次在向浏览器提供相应数据时,浏览器每次都要向服务器发送请求,有服务器来决策评估缓存的有效性。
    no-store : 所有内容都不缓存。

    对比缓存定义:服务器对比判断文件是否修改,告诉浏览器是否可以使用本地缓存。对比生效时,服务器返回给浏览器的http code 为304,服务器只返回http header信息,并无响应正文。浏览器收到304的返回,知道本地缓存并无修改,直接使用本地缓存。

    Last-Modified或者if-Modified-Since,服务器响应浏览器请求,告诉浏览器资源的最后修改时间

    ETag是实体标签(Entity Tag)的缩写, 根据实体内容生成的一段hash字符串(类似于MD5或者SHA1之后的结果),可以标识资源的状态。可以理解为一个资源的唯一标识符,只要文件发生变化Etag的值也变化。

    http请求头缓存相关字段

    If-Modified-Since

    客户端存取的该资源最后一次修改的时间,来自上次服务端的Last-Modified。

    If-None-Match

    客户端存取的该资源的检验值,来自上次服务端的ETag。

    cache-control:no-cache

    no-cache: 跳过本地强制缓存和告诉服务器跳过对比缓存,重新请求资源。

    web缓存的实现方式类型:

    • 数据库数据缓存
    • 服务器段缓存(包括代理服务器缓存和CDN缓存)
    • 浏览器端缓存
    • web应用层缓存
  • http和https的区别

    http用80端口,https用443

    https运行在SSL/TLS上,SSL/TLS运行在TCP上;http直接运行在TCP上

    HTTPS协议可以理解为HTTP协议的升级(SSL+Http协议),就是在HTTP的基础上增加了数据加密。数据保密,数据防篡改,证书验证(CA)。

    https比http的无状态连接要慢

  • http1.0 -1.1- spdy-2.0 大致的区别

    1.0-》1.1:

    引入更多的缓存处理(如Entity tag)

    带宽优化(range头域)

    错误通知(新增了错误状态码)

    Host头处理(相比之前的虚拟主机,必须包含头域)

    支持了长连接和请求的流水线处理,在一个TCP连接上可以多请求多响应

    1.1-》spdy

    降低延迟

    请求优先级(防阻塞)

    header压缩,避免重复header。

    基于https的加密协议传输

    服务端推送

    spdy-》2.0

    2.0支持明文http传输,spdy只能用https

    消息头的压缩算法优化

    新的二进制格式

    多路复用(连接共享),比长连接优化

除此之外暂时想不到其他的了。缓存字段和200、404、304之类非常常用的状态码一定要记住。

2.tcp的三次握手和四次挥手

tcp三次握手

img

第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
SYN:同步序列编号(Synchronize Sequence Numbers)
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手.
完成三次握手建立连接,客户端与服务器开始传送数据

四次挥手

img

1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

常见面试题
【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?

答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

【问题3】为什么不能用两次握手进行连接?

答:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

三、 html和css基础部分

1.盒模型概念

盒模型的组成,由里向外分别是content,padding,border,margin

盒子模型在页面中占的实际宽度是:(margin+padding+border)*2 + width,高度同理。

盒模型有标准盒模型和ie盒模型,二者的区别是

标准盒模型的内容大小就是content的大小,而ie盒模型的大小则是content+padding+border总的大小。通过设置 box-sizing:content-box(W3C)/border-box(IE)就可以达到自由切换的效果。

2.position定位属性和相关的关系

https://blog.csdn.net/mus123/article/details/104254388

1、static(静态定位):默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。
2、fixed(固定定位):生成绝对定位的元素,相对于浏览器窗口进行定位。元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。可通过z-index进行层次分级。
3、relative(相对定位):生成相对定位的元素(相对于他原来应该在的位置),通过top,bottom,left,right的设置相对于其正常(原先本身)位置进行定位。可通过z-index进行层次分级。  
4、absolute(绝对定位):生成绝对定位的元素(会脱离文档流),相对于 static 定位以外的第一个父元素进行定位。元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。可通过z-index进行层次分级。(可以结合父元素relative做相对定位)

3.块级、行内、行内块(display)

https://blog.csdn.net/qq_34821198/article/details/91359274

常见的块级元素有:<h1>~<h6>,<p>,<div>,<ul>,<ol>,<li>

​ 块级元素的特点:

  • 块级元素会独占一行
  • 高度,行高,外边距和内边距都可以单独设置
  • 宽度默认是容器的100%
  • 可以容纳内联元素和其他的块级元素

常见的行内元素有:<a>,<strong>,<b>,<em>,<del>,<span>

  • 和相邻的行内元素在一行上
  • 高度和宽度无效,但是水平方向上的padding和margin可以设置,垂直方向上的无效
  • 默认的宽度就是它本身的宽度
  • 行内元素只能容纳纯文本或者是其他的行内元素(a标签除外)

在行内元素中有几个特殊的标签,<img/>,<input/>,<td/>,可以设置它们的宽高度以及对齐属性

  • 和相邻的行内元素(行内块)在一行上,但是中间会有空白的间隙
  • 默认的宽度就是本身内容的宽度
  • 高度,行高,内边距和外边距都可以设置

显示模式的转换

块转行内:display-inline;

行内转块:display:block;

块,行内元素转换为行内块:display:inline-block

4.BFC和IFC

BFC(Block Formatting Context)叫做“块级格式化上下文”。

规则:

1.内部的盒子会在垂直方向,一个个地放置;

2.盒子垂直方向的距离由margin决定,属于同一个BFC的两个相邻Box的上下margin会发生重叠

3.每一个元素的左边,与包括的盒子的左边相接触,即使存在浮动也是如此;

4.BFC的区域不会与float重叠;

5.BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此;

6.计算BFC的高度时,浮动元素也參与计算。

产生BFC

1.根元素。

2.float的属性不为none;

3.position为absolute或fixed;

4.display为inline-block、table-cells、table-caption、flex;

5.overflow不为visible(hidden、auto、scroll)

IFC(Inline Formatting Context) 内敛格式化上下文。

IFC的line box(线框高度由其包含行内元素中最高的实际高度计算而来(不受到竖直方向的padding/margin影响)

IFC的inline box一般左右都贴紧整个IFC,但是因为float元素二扰乱。float元素会位于IFC与line box之间,使得line box宽度缩短。同个IFC下的多个line box高度会不同。IFC中不可能有块级元素,当插入块级元素时(如p中插入div)会产生两个匿名快与div分隔开,即产生两个IFC,每个IFC对外表现为块级元素,与div垂直排列。

作用

水平居中:当一个块要在环境中水平居中时候,设置其为inline-block则会在外层产生IFC,通过text-align:center则可以使其水平居中。

垂直居中:创建一个IFC,用其中一个元素撑开父元素的高度,然后设置其vertical-align:middle,其他行内元素则可以在此父元素下垂直居中。

4.三栏式布局:圣杯布局、双飞翼布局、flex布局、绝对定位布局

https://blog.csdn.net/Doubleu_/article/details/81082598

5.垂直居中

-1-table-cell方法(vertical-align:middle适用于行内块元素)

-2-绝对定位,top:50%;margin-top:负一半高度

-3-辅助div height:50%

-4-position:absolute;margin:auto

-5-line-height=height;只对单行文本

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3VXNtAOI-1586014814969)(C:\Users\mus\AppData\Roaming\Typora\typora-user-images\image-20200404140617730.png)]

-6-display:flex时用align-self:center

-7-用伪元素:befor

6.水平居中

-1-行内元素 text-align:center

-2-固定宽度时候用margin:0 auto;

-3-flex方式

-4-父子元素都确定

或者父元素用position:absolute创建BFC也行

-5-子元素不确定

-6-relative中float:left并margin-left

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MVOVOI8U-1586014814976)(C:\Users\mus\AppData\Roaming\Typora\typora-user-images\image-20200404141945344.png)]

-7-辅助div隐藏

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KeVLJrgn-1586014814977)(C:\Users\mus\AppData\Roaming\Typora\typora-user-images\image-20200404142038920.png)]

7.rem、em的使用

rem和em都是一种相对的尺寸,正常状态根节点下1em=1rrem=16px

但是em是继承式相对,而rem是根据根节点设置的font-size(默认16px)确定的相对大小

对于响应式布局和移动端有帮助

8.less等预处理语言(没学过orz)

https://blog.csdn.net/weixin_30421525/article/details/99210708?%3E

9.媒体查询

https://www.runoob.com/cssref/css3-pr-mediaquery.html

@media screen and (max-width: 300px) and(min-width:100px){
    
    
  body {
    
    
    background-color:lightblue;
  }
}

 
  
  
  • 1
  • 2
  • 3
  • 4
  • 5

10.h5的语义化部分


<section></section> 用于对网站或应用程序中页面上的内容进行分块。通常由内容及其标题组成。
<article></article> 代表文档、页面或应用程序中独立的、完整的、可以独自被外部引用的内容。当我们描述一件具体的事物的时候,通常使用article来代替section。如一个帖子,一段用户评论等。
<aside></aside>表示当前页面或者文章的附属信息部分。如与当前页面或主要内容相关的引用、侧边栏、广告、nav元素组等。
<nav></nav>用作页面导航的链接组,其中可以包括<ul><li><p>元素等。

<time></time>表示某个时间或者某个日期。其中pubdate属性代表了文档的发布日期,可以用到time标签里。

<header></header>整个页面或者页面内容区块的标题,可以包含其他内容。
<footer></footer>页脚,页面底部或者版块的内容。

<hgroup></hgroup>页面上标题的组合,通常对h1~h6进行分组。

<address></address>文档作者或者文档维护者的联系信息。
<figure></figure>通常用于图片,统计图或代码示例,带有可选标题。将其从网页上移除后不会对网页上其他内容产生影响。

<figcaption></figcaption>表示figure的标题,从属于figure元素。

<mark></mark>页面中需要凸显出或者高亮显示的,对于当前用户具有参考作用的一段文字。

<progress></progress>代表一个任务完成的进度。

<details></details>描述文档或者用户要求得到并且可以得到的细节信息。与summary元素配合使用。

<summary></summary>给details元素提供标题或者图例。标题是可见的,用户点击标题时,会显示细节信息。

<datelist></datelist>选项列表。与input元素配合使用,来定义input可能的值。

<keygen></keygen>给表单添加一个公钥.

<menu></menu>菜单列表。HTML4中不推荐使用。

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

11.css3的transform、transition、animate这些

transformhttps://www.runoob.com/cssref/css3-pr-transform.html

静态的2d或者3d的坐标轴转化

transitionhttps://www.w3school.com.cn/cssref/pr_transition.asp

过渡效果

animationhttps://www.w3school.com.cn/cssref/pr_animation.asp

animate是应用from-to结构的动画

区别:https://blog.csdn.net/weixin_39845746/article/details/79856512

transition、transform、animate的区别?

transition:过渡效果,它有4个属性:transition: property duration timing-function delay;

property :css属性的名称

duration :多长时间完成

timing-function:转速曲线

delay:开始的时候。

transform: 应用于元素的2D或3D转换。这个属性允许你将元素旋转,缩放,移动,倾斜等。

旋转:rotate()、缩放:scale()、移动:translate()、倾斜:skew()

//用@keyframes定义name

animate:动画效果。

animation: name duration timing-function delay iteration-count direction fill-mode play-state;

name :定义的名称

duration :多长时间完成

delay :开始前多长的延迟

iteration-count:播放几次

direction :指定是否应该轮流反向播放动画。

fill-mode:结束的状态

play-state:指定动画是否正在运行或已暂停。

12.css选择器的优先级

  • !important 特殊性最高

大致上****内联样式 > ID选择器 > 类选择器 = 属性选择器 = 伪类选择器 > 元素选择器 = 关系选择器 = 伪元素选择器 > 通配符选择器****

同级时下面比上面优先

13.清除浮动

https://blog.csdn.net/h_qingyi/article/details/81269667

1.额外标签法(在最后一个浮动标签后,新加一个标签,给其设置clear:both;)

如果我们清除了浮动,父元素自动检测子盒子最高的高度,然后与其同高。

优点:通俗易懂,方便

缺点:添加无意义标签,语义化差

2.父级添加overflow属性(父元素添加overflow:hidden)通过触发BFC方式,实现清除浮动

优点:代码简洁

缺点:内容增多的时候容易造成不会自动换行导致内容被隐藏掉,无法显示要溢出的元素

3.使用after伪元素清除浮动(推荐使用)

优点:符合闭合浮动思想,结构语义化正确

缺点:ie6-7不支持伪元素:after,使用zoom:1触发hasLayout.

4.使用before和after双伪元素清除浮动

优点:代码更简洁

缺点:用zoom:1触发hasLayout.

haslayout是IE7-浏览器的特有属性。hasLayout是一种只读属性,有两种状态:true或false。当其为true时,代表该元素有自己的布局,否则代表该元素的布局继承于父元素。(https://www.cnblogs.com/xiaohuochai/p/4845314.html)

14.canves(没学)

https://www.w3school.com.cn/tags/tag_canvas.asp

15.css实现响应式的方式

meta标签

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

  
   
   
  • 1
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">

  
   
   
  • 1

这段代码的几个参数解释:

§width = device-width:宽度等于当前设备的宽度

§initial-scale:初始的缩放比例(默认设置为1.0)

§minimum-scale:允许用户缩放到的最小比例(默认设置为1.0)

§maximum-scale:允许用户缩放到的最大比例(默认设置为1.0)

§user-scalable:用户是否可以手动缩放(默认设置为no,因为我们不希望用户放大缩小页面)

媒体查询

screen 用于电脑屏幕,平板电脑,智能手机等。
min-width 定义输出设备中的页面最小可见区域宽度。
min-resolution 定义设备的最小分辨率。
orientation 定义输出设备中的页面可见区域高度是否大于或等于宽度。
<link rel="stylesheet" type="text/css"media="screen and (min-width: 400px) and (max-device-width: 600px)" href="smallScreen.css" />

  
   
   
  • 1

另外有bootstrap工具

四、js部分

1.js的作用域作用域链

当我们在局部作用域中,访问一个变量时,系统首先会在当前作用域中寻找变量var的声明语句,如找到则直接使用。反之,则继续向上一级作用域中寻找var的声明语句,如找到则直接使用,反之,继续向上一级作用域中去寻找…直到全局作用域,如找到则直接使用,如未找到则直接在全局作用域中声明该变量,我们把这种链式查询关系就称之为为作用域链!

2.js的原型原型链

https://www.cnblogs.com/loveyaxin/p/11151586.html

实例对象的obj_proto_=Object.protorype上边的object()和Person.prototype都是Object的实例

var A = function(){
    
    };
var a = new A();
console.log(a.__proto__); //A {}(即构造器function A 的原型对象)
console.log(a.__proto__.__proto__); //Object {}(即构造器function Object 的原型对象)
console.log(a.__proto__.__proto__.__proto__); //null

 
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
子对象的_proto_指向父对象的prototype,prototype中包含(constructor和其自己的_proto_),最后object.prototype的_proto_是null

 
  
  
  • 1
查找先找自己的属性再找自己的_proto_对象的属性直到原型null

 
  
  
  • 1

3.js的dom元素操作

https://blog.csdn.net/mus123/article/details/104265530

4.js的垃圾回收机制

可达性:“可达性” 值就是那些以某种方式可访问或可用的值,它们被保证存储在内存中。

回收算法:

-1-标记-清除:从根开始访问打标记,结束后未标记的删除

一些优化:

  • 分代回收——对象分为两组:“新对象”和“旧对象”。许多对象出现,完成它们的工作并迅速结 束,它们很快就会被清理干净。那些活得足够久的对象,会变“老”,并且很少接受检查。
  • 增量回收——如果有很多对象,并且我们试图一次遍历并标记整个对象集,那么可能会花费一些时间,并在执行中会有一定的延迟。因此,引擎试图将垃圾回收分解为多个部分。然后,各个部分分别执行。这需要额外的标记来跟踪变化,这样有很多微小的延迟,而不是很大的延迟。
  • 空闲时间收集——垃圾回收器只在 CPU 空闲时运行,以减少对执行的可能影响。

-2-标记-压缩:和“标记-清除”相似,不过在标记阶段后它将所有活动对象紧密的排在堆的一侧(压缩),消除了内存碎片, 不过压缩是需要花费计算成本的。(减少内存碎片)

-3-引用计数:引用计数,就是记录每个对象被引用的次数,每次新建对象、赋值引用和删除引用的同时更新计数器,如果计数器值为0则直接回收内存。 很明显,引用计数最大的优势是暂停时间短。

-4-GC复制算法:将堆分为两个大小相同的空间 From 和 To, 利用 From 空间进行分配,当 From 空间满的时候,GC将其中的活动对象复制到 To 空间,之后将两个空间互换即完成GC。

-5-保守式GC:

有种情况是,非指针和堆里的对象地址一样;这时保守式GC “把可以的东西看做指针,稳妥处理”

保守式GC优点:GC不依赖于语言处理程序

5.js的String或者Array或者Math内部常用的方法

菜鸟教程吧字典里面挺多的

6.ajax请求详细怎么实现,和其中的响应状态。

var getXmlHttpRequest = function () {
    
    
    try{
    
    
        //主流浏览器提供了XMLHttpRequest对象
        return new XMLHttpRequest();
    }catch(e){
    
    
        //低版本的IE浏览器没有提供XMLHttpRequest对象,IE6以下
        //所以必须使用IE浏览器的特定实现ActiveXObject
        return new ActiveXObject("Microsoft.XMLHTTP");
    }
};
var xhr = getXmlHttpRequest();
// readyState 0=>初始化 1=>载入 2=>载入完成 3=>解析 4=>完成
// console.log(xhr.readyState);  0
xhr.open("TYPE", "URL", true);
// console.log(xhr.readyState);  1
//xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
//如果是POST
xhr.send();
// console.log(xhr.readyState);  1
xhr.onreadystatechange = function () {
    
    
    // console.log(xhr.status); //HTTP状态吗
    // console.log(xhr.readyState);  2 3 4
    if(xhr.readyState === 4 && xhr.status === 200){
    
    
        alert(xhr.responseText);
    }
};

 
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

7.js的基础类型和引用类型

es5中基础类型包括:number,string,null,undefined,Boolean。es6新增了一种基础类型symbol,基础类型的存储是存放在

基本类型值:按值访问,操作的是他们实际保存的值;

引用类型是指有多个值构成的对象,也就是对象类型比如:Object,Array,Function等

引用类型值:按引用访问,当查询时,我们需要先从栈中读取内存地址,然后再顺藤摸瓜地找到保存在堆内存中的值;

8.事件模型、事件委托、事件冒泡、事件捕获

事件捕获:当某个元素触发某个事件(如onclick),顶层对象document就会发出一个事件流,随着DOM树的节点向目标元素节点流去,直到到达事件真正发生的目标元素。在这个过程中,事件相应的监听函数是不会被触发的。

事件目标:当到达目标元素之后,执行目标元素该事件相应的处理函数。如果没有绑定监听函数,那就不执行。

事件冒泡:从目标元素开始,往顶层元素传播。途中如果有节点绑定了相应的事件处理函数,这些函数都会被一次触发。

标准的事件监听器该如何绑定:

addEventListener("eventType","handler","true|false");其中eventType指事件类型,注意不要加‘on’前缀,与IE下不同。第二个参数是处理函数,第三个即用来指定是否在捕获阶段进行处理,一般设为false来与IE保持一致(默认设置),除非你有特殊的逻辑需求。监听器的解除也类似: removeEventListner("eventType","handler","true|false");

addEventlistener和正常的οnclick=()=> 的区别?前者可以多事件,后者会覆盖只保留一个

9.js中new和object.creat区别

new操作符会将那样构造函数的prototype指定的原型对象赋值给新对象的[[Prototype]]
Object.create将参数proto指定的原型对象赋值给新对象的[[Prototype]]。
如果参数为null的话,Object.create则会创建空对象。

特别需要指出的是Object.create(null)和new Object()的区别:两者都是创建空对象,但是new创建出的空对象会绑定Object的prototype原型对象,但是Object.create(null)的空对象是没有任何属性的。

Object.create(proto, [propertiesObject])

proto:新创建对象的原型对象。

propertiesObject: 可选。如果没有指定为 undefined,则是要添加到新创建对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应Object.defineProperties()的第二个参数。

返回值:一个新对象带着指定的原型对象和属性。
例外:如果propertiesObject参数是 null 或非原始包装对象,则抛出一个 TypeError 异常。

new object()

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。new 关键字会进行如下的操作:

创建一个空的简单JavaScript对象(即{});

链接该对象(即设置该对象的构造函数)到另一个对象 ;

将步骤1新创建的对象作为this的上下文 ;

如果该函数没有返回对象,则返回this。

o = new Constructor();
// 上面的一句就相当于:
o = Object.create(Constructor.prototype);

 
  
  
  • 1
  • 2
  • 3
//当你执行
var o = new Foo();

//实际上执行了
var o = new Object();
o.proto = Foo.prototype;
Foo.apply(o);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

10.常用BOM方法

https://blog.csdn.net/u011486491/article/details/95059323

window常用对象
所有浏览器都支持 window 对象。它表示浏览器窗口。

所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员。

window
window尺寸

有三种方法能够确定浏览器窗口的尺寸(浏览器的视口,不包括工具栏和滚动条)。

对于Internet Explorer、Chrome、Firefox、Opera 以及 Safari:

window.innerHeight - 浏览器窗口的内部高度

window.innerWidth - 浏览器窗口的内部宽度

对于 Internet Explorer 8、7、6、5:

document.documentElement.clientHeight

document.documentElement.clientWidth

或者

document.body.clientHeight

document.body.clientWidth

其他操作window方法(不常用)

window.open() - 打开新窗口

window.close() - 关闭当前窗口

window.moveTo() - 移动当前窗口

window.resizeTo() - 调整当前窗口的尺寸

navigator
浏览器的信息,最常用的属性包括:

navigator.appName:浏览器名称;

navigator.appVersion:浏览器版本;

navigator.language:浏览器设置的语言;

navigator.platform:操作系统类型;

navigator.userAgent:浏览器设定的User-Agent字符串。

screen
屏幕的信息,常用的属性有:

screen.width:屏幕宽度,以像素为单位;

screen.availWidth:屏幕的可用宽度,以像素为单位

screen.height:屏幕高度,以像素为单位;

screen.availHeight:屏幕的可用高度,以像素为单位

screen.colorDepth:返回颜色位数,如8、16、24。

Location
当前页面的URL信息。常用属性有:

location.protocol; // ‘http’

location.host; // ‘www.example.com’

location.port; // ‘8080’

location.pathname; // ‘/path/index.html’

location.search; // ‘?a=1&b=2’

location.hash; // ‘TOP’

事件
常用事件
onload:当页面加载时

onscroll:当页面滚动时

onresize:页面重新定义大小时

onkeydown:当键盘按键按下的时候触发。能够响应用户输入的元素才支持键盘事件,和焦点事件一样。如果按下不抬起来会连续触发。

onkeyup:当键盘按键抬起时触发。

oncontextmenu:当右键菜单显示出来时触发。

事件绑定与取消
事件绑定:

div.addEventListener(事件名称,事件处理函数,捕获/冒泡);

事件取消:

div.removeEventListener(事件名称,事件处理函数,捕获/冒泡)

事件流
具体参考

https://blog.csdn.net/u011486491/article/details/90266090

cookie
通过cookie向访问者的电脑上存储数据,每个浏览器存储的位置不同,所以不同浏览器存储的cookie不能互相通用。

一个域名下存放cookie的个数是有限制的,不同浏览器存放的个数不同。每个cookie存放的内容大小也是有限制的,也是根据浏览器不同限制也不同。cookie的周期是整个浏览器结束进程的时候。如果想长时间存放一个cookie,需要在设置这个cookie的时候同时给他设置一个过期的时间。当过期后cookie就会被销毁。

//获取cookie
function getCookie(key){
    
    
    var arr1 = document.cookie.split(';');
    for(var i = 0;i < arr1.length;i++){
    
    
        var arr2 = arr1[i].split('=');
        if(arr2[0] == key){
    
    
            return decodeURI(arr[1]);
        }
    }
}
//设置cookie
function setCookie(key,value,t){
    
    
    var oDate = new Date();
    oDate.setDate(oDate.getDate() + t);
    document.cookie = key + '=' + value + ';expires=' + oDate.toGMTString();
}
//删除cookie
function removeCookie(key){
    
    
    setCookie(key,'',-1);
}

 
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

11.浏览器输入url之后最后网页渲染出来经过了

https://blog.csdn.net/xiaozhuxmen/article/details/52014901

响应

​ 1、输入网址。
 2、浏览器查找域名的IP地址。

3. 浏览器给web服务器发送一个HTTP请求
  4. 网站服务的永久重定向响应
  5. 浏览器跟踪重定向地址 现在,浏览器知道了要访问的正确地址,所以它会发送另一个获取请求。
  6. 服务器“处理”请求,服务器接收到获取请求,然后处理并返回一个响应。
  7. 服务器发回一个HTML响应
  8. 浏览器开始显示HTML
  9. 浏览器发送请求,以获取嵌入在HTML中的对象。在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签。这时,浏览器会发送一个获取请求来重新获得这些文件。这些文件就包括CSS/JS/图片等资源,这些资源的地址都要经历一个和HTML读取类似的过程。所以浏览器会在DNS中查找这些域名,发送请求,重定向等等…

渲染

  1. 用户输入网址(假设是个html页面,并且是第一次访问),浏览器向服务器发出请求,服务器返回html文件;
  2. 浏览器开始载入html代码,发现<head>标签内有一个<link>标签引用外部CSS文件;
  3. 浏览器又发出CSS文件的请求,服务器返回这个CSS文件;
  4. 浏览器继续载入html中<body>部分的代码,并且CSS文件已经拿到手了,可以开始渲染页面了;
  5. 浏览器在代码中发现一个<img>标签引用了一张图片,向服务器发出请求。此时浏览器不会等到图片下载完,而是继续渲染后面的代码;
  6. 服务器返回图片文件,由于图片占用了一定面积,影响了后面段落的排布,因此浏览器需要回过头来重新渲染这部分代码;
  7. 浏览器发现了一个包含一行Javascript代码的<script>标签,赶快运行它;
  8. Javascript脚本执行了这条语句,它命令浏览器隐藏掉代码中的某个<div> (style.display=”none”)。突然少了这么一个元素,浏览器不得不重新渲染这部分代码;
  9. 终于等到了</html>的到来,浏览器泪流满面……
  10. 等等,还没完,用户点了一下界面中的“换肤”按钮,Javascript让浏览器换了一下<link>标签的CSS路径;
  11. 浏览器召集了在座的各位<div><span><ul><li>们,“大伙儿收拾收拾行李,咱得重新来过……”,浏览器向服务器请求了新的CSS文件,重新渲染页面。

12.浏览器的同源策略及跨域实现

同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。它的核心就在于它认为自任何站点装载的信赖内容是不安全的。当被浏览器半信半疑的脚本运行在沙箱时,它们应该只被允许访问来自同一站点的资源,而不是那些来自其它站点可能怀有恶意的资源。

所谓同源是指:域名、协议、端口相同。

另外,同源策略又分为以下两种:

  1. DOM 同源策略:禁止对不同源页面 DOM 进行操作。这里主要场景是 iframe 跨域的情况,不同域名的 iframe 是限制互相访问的。
  2. XMLHttpRequest 同源策略:禁止使用 XHR 对象向不同源的服务器地址发起 HTTP 请求。

跨域限制主要的目的就是为了用户的上网安全

跨域的解决方法

CORS与JSONP的使用目的相同,但是比JSONP更强大。

JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

Jsonp:javaScript标签获取数据不受同源策略限制

function addScriptTag(src){
    
    
    var script = document.createElement('script');
    script.src = src; //跨域网址
    document.body.appendChild(script);  
    // 往页面插入元素后,会向跨域网址发出请求(src指定了跨域网址,得到响应后立即执行
}

window.onload = function(){
addScriptTag("http://example.com/ip?callback = foo’); //当页面加载完毕,即往页面中插入script元素
}

function foo(data){
console.log('your public ip address is: ‘+ data.ip)
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

或者用jq实现

<script type="text/javascript">
     jQuery(document).ready(function(){
    
     
        $.ajax({
    
    
             type: "get",
             async: false,
             url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
             dataType: "jsonp",
             jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
             jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
             success: function(json){
    
    
                 alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
             },
             error: function(){
    
    
                 alert('fail');
             }
         });
     });
     </script>

 
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

CORS(跨域资源共享):CORS(Cross-origin resource sharing,跨域资源共享)是一个 W3C 标准,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通。CORS 背后的基本思想,就是使用自定义的 HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。

简单请求

非简单请求

node.js express实现cors


var express = require('express');
var app = express();
//设置跨域访问
app.all('*', function(req, res, next) {
    
    
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    res.header("X-Powered-By",' 3.2.1')
    res.header("Content-Type", "application/json;charset=utf-8");
    next();
});

app.get(’/auth/:id/:password’, function(req, res) {
res.send({ id:req.params.id, name: req.params.password});
});

app.listen(3000);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

13.浏览器的回流和重绘

回流:即对于整个网页重新渲染一遍。

重绘:对某个元素重新绘制

会回流的操作

  • 页面首次渲染
  • 浏览器窗口大小发生改变
  • 元素尺寸或位置发生改变
  • 元素内容变化(文字数量或图片大小等等)
  • 元素字体大小变化
  • 添加或者删除可见DOM元素
  • 激活CSS伪类(例如::hover

重绘的操作

  • 修改color/background-color/visibility

(回流必重绘),要减少回流:

CSS(

避免table布局、

尽可能DOM树末端改变class,

避免多层内联样式

动画用脱离文档流的position:absolute|fixed

避免css表达式

JS(

避免频繁操纵style,最好一次性重写

避免频繁操纵dom

可以设置元素display:none,操作结束后再显示(操作过程中无回流重绘)

避免频繁读取会引发回流重绘的属性,比如dom节点,可以用变量缓存

复杂动画用绝对定位脱离文档流

14.call、bind、apply区别。

call()、apply()、bind()是用来改变this的指向的。

callapply的用法几乎一样,唯一的不同就是传递的参数不同,call只能一个参数一个参数的传入。
apply则只支持传入一个数组,哪怕是一个参数也要是数组形式。

bind方法,他是直接改变这个函数的this指向并且返回一个新的函数,之后再次调用这个函数的时候this都是指向bind绑定的第一个参数,需要手动执行。bind传参方式跟call方法一致。

  • fun.call(thisArg, arg1, arg2, ...)

  • fun.apply(thisArg, [argsArray])

  • fun.bind(thisArg[, arg1[, arg2[, ...]]])

15.js方法参数argument

这个就比较简单了,个人推荐看看剩余运算符...和展开运算符

https://www.cnblogs.com/LMJBlogs/p/6024148.html

16.深拷贝和浅拷贝

浅拷贝是拷贝地址,一般对引用型变量使用等号都可以;

深拷贝要通过一写方法实现;

https://www.jianshu.com/p/a8dc699e9534(深拷贝)

-插一个看着比较好的深拷贝

const deepClone =(initalObj) =>
    {
    
    
        const obj = {
    
    };
        if (typeof initalObj !== 'object') {
    
    
            return initalObj
        }
        for (const key in initalObj) {
    
    
            if (typeof initalObj[key] === 'object') {
    
    
                //对数组特殊处理
                if (Array.isArray(initalObj[key])) {
    
    
                    //用map方法返回新数组,将数组中的元素递归
                    obj[key] = initalObj[key].map(item => deepClone(item))
                } else {
    
    
                    //递归返回新的对象
                    obj[key] = deepClone(initalObj[key]);
                }
            } else if (typeof initalObj[key] === 'function') {
    
    
                //返回新函数
                obj[key] = initalObj[key].bind(obj);
            } else {
    
    
                //基本类型直接返回
                obj[key] = initalObj[key];
            }
        }
        return obj;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

-另外 JSON.stringify 把对象转成字符串,再用 JSON.parse 把字符串转成新的对象(不能实现里面的函数)

-然后深拷贝也能通过Object.creat()的原型方法实现

五.看看es6,推荐阮一峰es6教程:https://es6.ruanyifeng.com/

1.promise

promise可以避免回调地狱,总之就是可以用.then的办法解决你异步程序中的顺序问题

对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。

resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

2.闭包

https://blog.csdn.net/weixin_43586120/article/details/89456183

1、概念
闭包函数:声明在一个函数中的函数,叫做闭包函数。

闭包:内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。

2、特点
让外部访问函数内部变量成为可能;

局部变量会常驻在内存中;

可以避免使用全局变量,防止全局变量污染;

会造成内存泄漏(有一块内存空间被长期占用,而不被释放)

3、闭包的创建:­­­
闭包就是可以创建一个独立的环境,每个闭包里面的环境都是独立的,互不干扰。闭包会发生内存泄漏,每次外部函数执行的时 候,外部函数的引用地址不同,都会重新创建一个新的地址。但凡是当前活动对象中有被内部子集引用的数据,那么这个时候,这个数据不删除,保留一根指针给内部活动对象。

闭包内存泄漏为: key = value,key 被删除了 value 常驻内存中; 局部变量闭包升级版(中间引用的变量) => 自由变量;

结论:闭包找到的是同一地址中父级函数中对应变量最终的值

升华一点下面的例子

上边如果不用自动执行函数的话就会发现最后输出都是55555

一种解决就是如上面我们写成自动执行的;

另一种办法就是把上面的for循环体中的var改成let

3.let 、const,以及var与函数的提升

https://es6.ruanyifeng.com/#docs/let

let和const有一个区别是const的引用值(地址)不能变,不过可以给引用的对象操作。

var声明的变量在全局范围有效

let和const对块作用有效而且有死区,不存在变量提升,不允许重复声明,不被当做顶层属性

ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。

在作用域内的函数会被提升到当前函数顶部。

ES6可以在块内定义函数类似let(es6的浏览器会当成var)

应该还可以加一个Symbol

4.Generator

Generator一般和iterator、for…of一起用,举个例子

其中的yield和next的组合使用还是挺棒的,最好还是去链接里面看

https://es6.ruanyifeng.com/#docs/generator#next-%E6%96%B9%E6%B3%95%E7%9A%84%E5%8F%82%E6%95%B0

5.Symbol

为了防止属性名冲突的新类型

还可以消除魔术字符串

可以用Object.getOwnPropertySymbols(obj)获取到

然后好玩的来了 Symbol.for()和Symbol.keyFor()这一对儿可以让描述和我们的symbol对应起来

另外有一些内置Symbol

-Symbol.species属性,指向一个构造函数。创建衍生对象时,会使用该属性

-Symbol.species属性,指向一个构造函数。创建衍生对象时,会使用该属性

-对象的Symbol.replace属性,指向一个方法,当该对象被String.prototype.replace方法调用时,会返回该方法的返回值。

-对象的Symbol.search属性,指向一个方法,当该对象被String.prototype.search方法调用时,会返回该方法的返回值。

-对象的Symbol.split属性,指向一个方法,当该对象被String.prototype.split方法调用时,会返回该方法的返回值。

-对象的Symbol.iterator属性,指向该对象的默认遍历器方法。

-对象的Symbol.toPrimitive属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。

-Symbol.toPrimitive被调用时,会接受一个字符串参数,表示当前运算的模式,一共有三种模式。

  • Number:该场合需要转成数值
  • String:该场合需要转成字符串
  • Default:该场合可以转成数值,也可以转成字符串

-对象的Symbol.toStringTag属性,指向一个方法。在该对象上面调用Object.prototype.toString方法时,如果这个属性存在,它的返回值会出现在toString方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制[object Object][object Array]object后面的那个字符串。

-对象的Symbol.unscopables属性,指向一个对象。该对象指定了使用with关键字时,哪些属性会被with环境排除。

https://es6.ruanyifeng.com/#docs/symbol

6.set类型可以实现数组去重(极方便)

7.箭头函数

注意点:箭头函数有几个使用注意点。

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

8.解构赋值

https://es6.ruanyifeng.com/#docs/destructuring

也可以结合require使用引入对象方法。

9.正则扩展

其中正则表达式的基础我觉得也挺重要(虽然每次看完都记不住)

y全局连续匹配

y :也是全局匹配,首次匹配和g修饰符效果一样,但是第二次往后就不一样了,
g修饰符不一定要求匹配下标紧接着上一次开始匹配的去找,只要找到了就行;
而y修饰符是规定要求匹配下标紧接着上一次匹配的开始 去匹配,不合适条件就为匹配失败为null。

使用lastIndex属性,可以更好地说明y修饰符。

u修饰符就是拿来处理Unicode字符的。

引入s修饰符,使得.可以匹配任意单个字符。

六、其他

1.js单线程和js具体怎么实现异步的。大概的技术名词有事件队列、执行栈、宏任务、微任务。

单线程和异步https://www.jianshu.com/p/ba711650944e

可以异步的原因:浏览器、node是多线程的

1.引入异步的原因

JS是单线程语言,浏览器只分配给JS一个主线程,用来执行任务(函数), 但一次只能执行一个任务,这些任务形成一个任务队列排队等候执行。但是前端的很多任务都是非常耗时的,比如http请求、定时器、事件监听等。如果让他们都按照同步原理顺序执行,那么执行效率会非常低,甚至导致页面的假死。

2.浏览器模型

用户界面(User Interface): 包括地址栏、前进/后退按钮、书签菜单等

浏览器引擎 (Browser engine):在用户界面和呈现引擎之间传送指令

呈现引擎 (Rendering engine):又称渲染引擎,也被称为浏览器内核,在线程方面又称为UI线程

网络 (Networking):用于网络调用,比如 HTTP 请求

用户界面后端 :用于绘制基本的窗口小部件,UI线程和JS共用一个线程

JavaScript解释器 (Javascript Interpreter):用于解析和执行 JavaScript 代码

数据存储 (Data Persistence):这是持久层。浏览器需要在硬盘上保存各种数据,例如 Cookie

  1. 浏览器对JS异步的支持

浏览器内核允许多个线程异步执行,这些线程在内核控制下相互配合以保持同步。

三个常驻线程:

a). JavaScript引擎线程
b). 页面渲染线程
c). 浏览器事件触发线程

执行完就终止的线程

a). HTTP请求线程等
b). 定时触发器线程

  1. 任务队列

顾名思义: 排着任务的队列。所谓任务就是webAPIs(浏览器为异步任务单独开辟的线程统一称为webAPIs)返回的一个个通知,让JS主线程在读取任务队列的时候得知这个异步任务已经完成,下一步该执行这个任务的回调函数了。主线程拥有多个任务队列,不同的任务队列用来排列来自不同任务源的任务。

  • 任务源: 像setTimeout / Promise / DOM 事件等都是任务源。来自同类任务源的任务我们称它是同源的, 比如setTimeout和setInterval就是同源的。
  1. 事件循环(event loop)

由三大模块组成: 函数调用栈、webAPIs、任务队列

执行过程:

-主线程在遇到ajax或者setTimeout 这种异步操作时会交给浏览器的webAPIs,然后继续执行后面的代码,直到执行栈为空。

-浏览器会在不确定的时间将完成的任务返回,排到相应的任务队列后。

-执行栈为空时,主线程会到任务队列中去取任务,这些任务会告诉下一步应该执行那些回调函数。任务队列是具有优先级的,按照优先级顺序决定访问的先后循序。而优先级在不同的环境中又有所不同,不能一概而论。

-每访问一个队列,执行栈会执行完这个任务队列的的所有代码,然后再取下一个任务队列需要执行的任务代码。如果在执行中遇到了属于当前任务的异步队列时,此次任务的返回不会排到当前的任务队列之后,因为这属于两次单独的事件循环,会被区分开来。
就这样循环执行,直到三大块全为空,称为事件循环

  1. AJAX请求是否异步

ajax请求内容的时候是异步的,当请求完成后,会触发请求完成的事件,然后把回调函数放到任务队列中,等到主线程执行该回调函数时还是单线程的。

  1. 界面渲染线程是单独开辟的线程,是不是DOM一变化,界面就立刻重新渲染?

答案: 不是。
如果DOM一变化界面就重新渲染,效率必然很低,所以浏览器的机制规定界面渲染线程和主线程是互斥的,主线程执行任务时,浏览器渲染线程处于挂起状态。

我觉得下面这篇写得比较清楚

https://www.jianshu.com/p/a05dd3ac0150

执行栈管理同步任务、任务队列管理异步任务。同步任务没啥,异步任务分为异步宏任务和异步微任务

常见的宏任务有setTimeout、setInterval;
常见的微任务有 Promise、nextTick(node.js 环境)。

console.log(1)     //同步任务A

setTimeout( //同步任务B
() => { console.log(2) } //任务B产生的异步宏任务
, 300)

new Promise( //同步任务C
(resolve) => { console.log(3); resolve(4); }
)
.then( //任务C执行过程中resolve(4)语句产生的异步微任务
(num) => { console.log(num) }
)

setTimeout( //同步任务D
()=> { console.log(5) } //任务D产生的异步宏任务
, 800)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

所以上面代码的打印顺序是1->3->4->2->5。

执行栈是一开始排队的地方,然后还有一个宏任务队列,一个微任务队列

首先同步任务A肯定是最先执行的,然后遇见了setTimeout的任务B会300ms后产生异步宏任务(会挂起)

然后是任务C创建一个新的Promise,产生一个异步微任务加到微任务队列

遇见任务D又是一个800ms后产生宏任务

300s到的时候第一个宏任务创建成功,进入宏任务队列

此时执行栈是空的,此时去微任务执行队列执行完微任务

然后把宏任务队列的任务放回到执行栈

总结:先同步任务栈搞完,中间碰上宏任务和微任务放到各自的队列中,等同步执行完,先微任务再宏任务,并且每次执行完宏任务都会清空微任务,直到两个队列全清空(形成EventLoop事件循环)

2.webworke做多线程

HTML5提出了WebWork允许用户另开线程来进行复杂的逻辑计算处理。

在新的标准中,提供的新的WebWork API,让前端的异步工作变得异常简单。

其实和import引入一个JS文件进行处理,然后export的用法有点像,不过这里是指定了postmessage方法和onmessage方法,webwork使用会占一定系统资源,而且work中不能访问及操作dom,。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a7jVdUgi-1586014815032)(C:\Users\mus\AppData\Roaming\Typora\typora-user-images\image-20200404201504981.png)]

网页端

var work=new Worker(‘js路径’)

work.postMessage(数据a)

work.onmessage = function(res)//res.data=数据b
{
console.log(res.data);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
onmessage = function(e){
    
    
let sum = 0,num = e.data;//e.data=数据a

postMessage(数据b);
}

  • 1
  • 2
  • 3
  • 4
  • 5

3.网络安全问题及处理

https://blog.csdn.net/qq_37636695/article/details/79266232

1、XSS(Cross Site Script)

把token存储在cookie中,同时设置httpOnly。

2、CSRF(cross-site request forgery)

​ 2.1、判断reffer。系统改动最小,通过filter就可以完成。

​ 2.2、在参数中传token。

​ 2.3、通过header传递token。(推荐)

XSS:
跨站脚本(Cross-site scripting,通常简称为XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了HTML以及用户端脚本语言。

CSRF/XSRF:
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
简单来说:
XSS: 通过客户端脚本语言(最常见如:JavaScript)
在一个论坛发帖中发布一段恶意的JavaScript代码就是脚本注入,如果这个代码内容有请求外部服务器,那么就叫做XSS!

CSRF:又称XSRF,冒充用户发起请求(在用户不知情的情况下),完成一些违背用户意愿的请求(如恶意发帖,删帖,改密码,发邮件等)。

XSS防御
1.在输出html时,加上Content Security Policy的Http Header,比如Content-Type: text/javascript;

(作用:可以防止页面被XSS攻击时,嵌入第三方的脚本文件等)

(缺陷:IE或低版本的浏览器可能不支持)

2.在设置Cookie时,加上HttpOnly参数

(作用:可以防止页面被XSS攻击时,Cookie信息被盗取,可兼容至IE6)

(缺陷:网站本身的JS代码也无法操作Cookie,而且作用有限,只能保证Cookie的安全)

CSRF 防御
1.验证码(可以伪造)

2.所有需要用户登录之后才能执行的操作属于重要操作,这些操作传递参数应该使用post方式,更加安全;

3.在开发API时,检验请求的Referer参数

(作用:可以在一定程度上防止CSRF攻击)

(缺陷:IE或低版本的浏览器中,Referer参数可以被伪造)
4.Token
使用Anti-CSRF Token 在URL中保持原参数不变,新增一个参数Token。Token的值是随机的(必须使用足够安全的随机数生成算法,或者采用真随机数生成器),其为用户与服务器所共同持有,可以放在用户的Session中,或者浏览器的Cookie中。 注意保密,尽量把Token放在表单中(构造一个隐藏的input元素),以POST提交,避免Token泄露。

4.数据结构的栈、队列、链表

数据结构基础的东西学校还是教了的

最简单的理解:

栈:先进后出

队列:先进先出

链表:通过.next方式串联节点

深层次的还是刷一些数据结构的题比较靠谱

5.设计模式

https://www.cnblogs.com/imwtr/p/9451129.html

学习设计模式,有助于写出可复用和可维护性高的程序

设计模式的原则是“找出 程序中变化的地方,并将变化封装起来”,它的关键是意图,而不是结构。

不过要注意,使用不当的话,可能会事倍功半。

1.单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点

2.策略模式:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

3.代理模式:为一个对象提供一个代用品或占位符,以便控制对它的访问

4.迭代器模式:迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

5.发布-订阅模式:也称作观察者模式,定义了对象间的一种一对多的依赖关系,当一个对象的状态发 生改变时,所有依赖于它的对象都将得到通知

6.命令模式:用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。命令(command)指的是一个执行某些特定事情的指令

7.组合模式:是用小的子对象来构建更大的 对象,而这些小的子对象本身也许是由更小 的“孙对象”构成的

8.模板方法模式:模板方法模式一般的实现方式为继承

9.享元模式:享元(flyweight)模式是一种用于性能优化的模式,它的目标是尽量减少共享对象的数量

10.职责链模式:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系,将这些对象连成一条链,并沿着这条链 传递该请求,直到有一个对象处理它为止

11.中介者模式:所有的相关 对象都通过中介者对象来通信,而不是互相引用,所以当一个对象发生改变时,只需要通知中介者对象即可

12.装饰着模式:以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象。

是一种“即用即付”的方式,能够在不改变对象自身的基础上,在程序运行期间给对象动态地添加职责

13.状态模式:事物内部状态的改变往往会带来事物的行为改变。在处理的时候,将这个处理委托给当前的状态对象即可,该状态对象会负责渲染它自身的行为

14.适配器模式:是解决两个软件实体间的接口不兼容的问题,对不兼容的部分进行适配

15.外观模式:为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使子系统更加容易使用

5.bootstrap栅格原理

https://www.cnblogs.com/suwings/p/6079178.html

通过行和列

行(row)必须放在.container(固定宽度)或.container-fluid(100%宽度)内,以便为其赋予合适的排列(aligment)和内补(padding);
通过“行(row)”在水平方向创建一组“列(col)”;
你的内容应当放置在“列(col)”内,并且,只有“列(col)”可以作为行的直接子元素。
类似.row和.col-xs-4这种预定义的类,可以用来快速创建栅格系统布局。Bootstrap源码中定义的mixin也可以用来创建语义化的布局。
通过为“列(col)”设置padding属性,从而创建列与列之间的间隔。通过为.row元素设置负值margin从而抵消掉为.container元素设置的padding,也就间接为“行(row)”所包含的“列(col)”抵消掉了padding
负值的margin就是下面的示例为什么是 向外突出的原因。在栅格列中内容排成一行。
栅格系统中的列是通过指定1到12的值来表示其跨越的范围。例如,三个等宽的列可以使用三个.col-xs-4。
如果一“行(row)”中包含了的“列(col)”大于12,多余的“列(col)”所在的元素被作为一个整体另外一行排列。

@media (min-width: 992px) {
    
    
  .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
    
    
    float: left;
  }
  .col-md-12 {
    
    
    width: 100%;
  }
  .col-md-11 {
    
    
    width: 91.66666667%;
  }
  .col-md-10 {
    
    
    width: 83.33333333%;
  }
  .col-md-9 {
    
    
    width: 75%;
  }
  .col-md-8 {
    
    
    width: 66.66666667%;
  }
  .col-md-7 {
    
    
    width: 58.33333333%;
  }
  .col-md-6 {
    
    
    width: 50%;
  }
  .col-md-5 {
    
    
    width: 41.66666667%;
  }
  .col-md-4 {
    
    
    width: 33.33333333%;
  }
  .col-md-3 {
    
    
    width: 25%;
  }
  .col-md-2 {
    
    
    width: 16.66666667%;
  }
  .col-md-1 {
    
    
    width: 8.33333333%;
  }
  .col-md-pull-12 {
    
    
    right: 100%;
  }
  .col-md-pull-11 {
    
    
    right: 91.66666667%;
  }
  .col-md-pull-10 {
    
    
    right: 83.33333333%;
  }
  .col-md-pull-9 {
    
    
    right: 75%;
  }
  .col-md-pull-8 {
    
    
    right: 66.66666667%;
  }
  .col-md-pull-7 {
    
    
    right: 58.33333333%;
  }
  .col-md-pull-6 {
    
    
    right: 50%;
  }
  .col-md-pull-5 {
    
    
    right: 41.66666667%;
  }
  .col-md-pull-4 {
    
    
    right: 33.33333333%;
  }
  .col-md-pull-3 {
    
    
    right: 25%;
  }
  .col-md-pull-2 {
    
    
    right: 16.66666667%;
  }
  .col-md-pull-1 {
    
    
    right: 8.33333333%;
  }
  .col-md-pull-0 {
    
    
    right: auto;
  }
  .col-md-push-12 {
    
    
    left: 100%;
  }
  .col-md-push-11 {
    
    
    left: 91.66666667%;
  }
  .col-md-push-10 {
    
    
    left: 83.33333333%;
  }
  .col-md-push-9 {
    
    
    left: 75%;
  }
  .col-md-push-8 {
    
    
    left: 66.66666667%;
  }
  .col-md-push-7 {
    
    
    left: 58.33333333%;
  }
  .col-md-push-6 {
    
    
    left: 50%;
  }
  .col-md-push-5 {
    
    
    left: 41.66666667%;
  }
  .col-md-push-4 {
    
    
    left: 33.33333333%;
  }
  .col-md-push-3 {
    
    
    left: 25%;
  }
  .col-md-push-2 {
    
    
    left: 16.66666667%;
  }
  .col-md-push-1 {
    
    
    left: 8.33333333%;
  }
  .col-md-push-0 {
    
    
    left: auto;
  }
  .col-md-offset-12 {
    
    
    margin-left: 100%;
  }
  .col-md-offset-11 {
    
    
    margin-left: 91.66666667%;
  }
  .col-md-offset-10 {
    
    
    margin-left: 83.33333333%;
  }
  .col-md-offset-9 {
    
    
    margin-left: 75%;
  }
  .col-md-offset-8 {
    
    
    margin-left: 66.66666667%;
  }
  .col-md-offset-7 {
    
    
    margin-left: 58.33333333%;
  }
  .col-md-offset-6 {
    
    
    margin-left: 50%;
  }
  .col-md-offset-5 {
    
    
    margin-left: 41.66666667%;
  }
  .col-md-offset-4 {
    
    
    margin-left: 33.33333333%;
  }
  .col-md-offset-3 {
    
    
    margin-left: 25%;
  }
  .col-md-offset-2 {
    
    
    margin-left: 16.66666667%;
  }
  .col-md-offset-1 {
    
    
    margin-left: 8.33333333%;
  }
  .col-md-offset-0 {
    
    
    margin-left: 0;
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159

6.webpack的配置

https://www.runoob.com/w3cnote/webpack-tutorial.html

https://www.cnblogs.com/minghui007/p/7390247.html

var webpack = require('webpack');
module.exports = {
    
    
    entry: [
        'webpack/hot/only-dev-server',
        './js/app.js'//入口文件
    ],
    output: {
    
    
        path: './build',//输出路径
        filename: 'bundle.js'//输出
    },
    module: {
    
    
        loaders: [
            //loaders通过正则匹配文件后缀名
        {
    
     test: /\.js?$/, loaders: ['react-hot', 'babel'], exclude:     /node_modules/ },
        {
    
     test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
        {
    
     test: /\.css$/, loader: "style-loader!css-loader" },
        {
    
     test: /\.less/,loader: 'style-loader!css-loader!less-loader'}
        {
    
     test: /\.(png|jpg)$/,loader: 'url-loader?limit=10000'}
        ]
    },
    resolve:{
    
    
        extensions:['','.js','.json']//自行补全的文件后缀
    },
     externals: {
    
    //添加一些其他的类库或者api
     "jquery": "jQuery"
	 } //项目中可以:var jQuery = require(“jquery”);
    plugins: [
        new webpack.NoErrorsPlugin()
    ],
	devServer: {
    
    
        inline: false,
        port: 8181//默认端口号,缺省值为8080
  }
};

 
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

七.那个大佬的干货结语

大概也就是这些知识点吧。除此之外,你在面试阶段不需要写太多的项目经验,除非你非常厉害写了很多,参加了n多的导师的上线项目,当然很多普通的同学们也都不会有那么多机会去实践,但是都没有什么好怕的。之前滴滴的前端leader和我说,其实你们实习生的问题都很同一,项目经验很少,我们其实更要求的是你处理问题的方式,和你扎实的基础。不需要那么多其他的东西。而且可能很多人会挂在最后一面,其实很多时候不是你的技术问题。是你不敢去说。你会多少东西,就以你自己的见识和知识去尽力解决,就算你真的不知道,哪怕知道一点点,也尝试着去表达。我记得我有一个终面的leader就是说,这个问题本身也不是给你准备的,就是想看看你敢不敢表达,还有你的推理和类比能力怎么样。大概的套路基本是一面纯纯基础技术面试、二面也可能是纯基础技术面试,或者给你出很多情景题,让你用你的知识去解决,如果是这样的话基本不用怕的。因为公司的实习生的要求都比较低的,毕竟大家经验都不可能很多。否则还去实习干嘛。尽自己能力表现就行了,还有一点非常非常重要。和面试官打好关系,如果你觉得没问题,微信号必须要,维护好之后的关系,如果他在部门内部力挺你,你技术还不是很差,基本就稳了。

也不知道是哪年的了,早上起来就再看这篇文,晚上十二点才差不多过了一遍,有的也没深挖

该博主看起来挺厉害的百度携程滴滴头条360的offer都有,

我马上也要人生第一次前端实习面试了是美团的所以刷题看看人家的面经~

链接:https://m.sohu.com/a/236608417_690895
这个各方面都有吧能找到答案的我一般都做了传送门

文章目录

一、算法部分

如果你算法不好就可以直接告诉面试官。不需要过多作假,面试官其实也很聪明的,如果你作弊很快就能发现的。

1、基本排序的方式

img

冒泡、快排、桶排、堆排序、归并排序、插入排序。

(1)冒泡:排序思路:遍历数组,每次遍历就将最大(或最小)值推至最前。越往后遍历查询次数越少, 跟插入排序刚好相反。

(2)快排:选择一个元素作为基数(通常是第一个元素),把比基数小的元素放到它左边,比基数大的元素放到它右边(相当于二分),再不断递归基数左右两边的序列。

(3)桶排:取 n 个桶,根据数组的最大值和最小值确认每个桶存放的数的区间,将数组元素插入到相应的桶里,最后再合并各个桶。(n个容量至少为1的桶,从大到小,每次的数字放到对应桶的排序好的位置)

(4)堆排序:因为js模拟二叉树比较麻烦,所以堆排序的优势用js语言无法体现, 相对而言C语言的链表在实现上更能表现堆排序,堆排序或许更适合指针类的计算机语言

形成大顶堆,然后顶和末尾叶节点交换,堆容量递减。并且每次构建完上边的堆要回去看一下其子堆有没有受到影响,(太麻烦了不写了,我解读一个别人的吧)

(5)归并排序:递归将数组分为两个序列,有序合并这两个序列(递归向下)

写的时候一直死递归,超出堆栈(但是我明明谢了结束条件了啊,发现有一个地方逗号写成了.然后块级作用域变量left、right忘了加let导致污染,真是难顶)

(6)插入排序:以第一个元素作为有序数组,其后的元素通过在这个已有序的数组中找到合适的位置并插入。

var arr=[1,3,6,9,2,7,5,4,8,3];//十位数
console.log(arr);
function swap(a,i,j){
    
    
    let t=a[i];
    a[i]=a[j];
    a[j]=t;
}
/** */

猜你喜欢

转载自blog.csdn.net/Better_Xing/article/details/113571877