当前位置:   article > 正文

2022年最新前端大厂常考必考 180 题_大厂前端笔试题

大厂前端笔试题

2022年最新前端大厂常考必考 180 题

1、HTTP 和 HTTPS
https 的 SSL 加密是在传输层实现的。
(1)http 和 https 的基本概念
http: 超文本传输协议,是互联网上应用最为广泛的一种网络协议,是一个客户端和
服务器端请求和应答的标准(TCP),用于从 WWW 服务器传输超文本到本地浏览器的传
输协议,它可以使浏览器更加高效,使网络传输减少。
https: 是以安全为目标的 HTTP 通道,简单讲是 HTTP 的安全版,即 HTTP 下加入 SSL
层,HTTPS 的安全基础是 SSL,因此加密的详细内容就需要 SSL。
https 协议的主要作用是:建立一个信息安全通道,来确保数组的传输,确保网站的真
实性。
(2)http 和 https 的区别?
http 传输的数据都是未加密的,也就是明文的,网景公司设置了 SSL 协议来对 http 协
议传输的数据进行加密处理,简单来说 https 协议是由 http 和 ssl 协议构建的可进行
加密传输和身份认证的网络协议,比 http 协议的安全性更高。
主要的区别如下:
Https 协议需要 ca 证书,费用较高。
http 是超文本传输协议,信息是明文传输,https 则是具有安全性的 ssl 加密传输协
议。
使用不同的链接方式,端口也不同,一般而言,http 协议的端口为 80,https 的端口
为 443
http 的连接很简单,是无状态的;HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传
输、身份认证的网络协议,比 http 协议安全。
(3)https 协议的工作原理
客户端在使用 HTTPS 方式与 Web 服务器通信时有以下几个步骤,如图所示。
客户使用 https url 访问服务器,则要求 web 服务器建立 ssl 链接。
web 服务器接收到客户端的请求之后,会将网站的证书(证书中包含了公钥),返回或
者说传输给客户端。
客户端和 web 服务器端开始协商 SSL 链接的安全等级,也就是加密等级。
客户端浏览器通过双方协商一致的安全等级,建立会话密钥,然后通过网站的公钥来
加密会话密钥,并传送给网站。
web 服务器通过自己的私钥解密出会话密钥。
web 服务器通过会话密钥加密与客户端之间的通信。
(4)https 协议的优点
使用 HTTPS 协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;
HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,要比
http 协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。
HTTPS 是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻
击的成本。
谷歌曾在 2014 年 8 月份调整搜索引擎算法,并称“比起同等 HTTP 网站,采用 HTTPS
加密的网站在搜索结果中的排名将会更高”。
(5)https 协议的缺点
https 握手阶段比较费时,会使页面加载时间延长 50%,增加 10%~20%的耗电。
https 缓存不如 http 高效,会增加数据开销。
SSL 证书也需要钱,功能越强大的证书费用越高。
SSL 证书需要绑定 IP,不能再同一个 ip 上绑定多个域名,ipv4 资源支持不了这种消
耗。
  • 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
2、position 的值, relative 和 absolute 分别是相对于谁进行定位的?
absolute:生成绝对定位的元素, 相对于 最近一级的定位不是 static 的父元素来进行定位。

fixed:(老IE不支持)生成绝对定位的元素,通常 相对于浏览器窗口或 frame 进行定位。

relative:生成相对定位的元素, 相对于其在普通流中的位置进行定位。

static: 默认值。没有定位,元素出现在正常的流中

sticky:生成粘性定位的元素,容器的位置根据正常文档流计算得出
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
3、如何解决跨域问题
1.什么是跨域
.网页所在url的协议、域名、端口号,和Ajax请求url的协议、域名、端口号有一个对应不上,就发生跨域
.跨域是浏览器对ajax做出的限制


CORS全称Cross-Origin Resource Sharing,意为跨域资源共享。当一个资源去访问另一个不同域名或者同域名不同端口的资源时,就会发出跨域请求。如果此时另一个资源不允许其进行跨域资源访问,那么访问就会遇到跨域问题。

跨域指的是浏览器不能执行其它网站的脚本。是由浏览器的同源策略造成的,是浏览器对JavaScript 施加的安全限制。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
2、解决办法:
1、 jsonp方式
	JSONP(JSON with Padding)JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。 由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML<script> 元素是一个例外。利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。

核心用法
利用<script src="远程服务网址></script>
返回值语法固定的:callback(JSON数据)



2、 cors方式
	

3、 proxy代理转发

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
4、Heap 排序方法的原理?复杂度?
5、几种常见的排序算法,手写
 //希尔排序
        var list = [2,93,5,125,66,1];
        //找出间隔分组
        //初始的间隔大小
        var interval = Math.round(list.length);
        while(interval > 0) {
          //根据间隔大小,进行插入排序
          inserSort(list,interval);
          //将间隔减半,取整
          interval = parseInt(interval/2);
        }
          function inserSort(list ,interval) {
        for(var i=1; i < list.length; i++) {
            var m = i;
            while(m - interval >=0 && list[m] < list[m-interval]) { //当后一个位置小于前一个位置时交换
              swap(list,m,m-interval);
              m -= interval;
            }
        }
     }
// 插入排序

 var list = [2,93,5,125,66,1];

 for(var i = 1; i<list.length; i++) {
    var m = i;
    while(m-1 >= 0 && list[m] < list[m-1]) {
      swap(list,m,m-1);
      m--;
    }
 }

 // 冒泡排序

 var list =  [2,93,5,125,66,1];

 for(var i = 0;i <list.length-1; i++) {
    for(var j = 0;j < list.length-i-1; i++){
      if(list[j] > list[j+1]){
        swap(list,j,j+1);
      }
    }
 }


 // 选择排序

  var list =  [2,93,5,125,66,1];
  for(var i = 0; i < list.length-1; i++) {
    min = list[i];
    index = i;
    for( var j = i; j < list.length; j++) {
      if(list[j] < min) {
        min = list[j];
        index = j;
      }
    }
    swap(list,i,index);
  }

      //快速排序
       var list1 = [2,93,5,125,66,1];

       function quicksort(list) {
        if(list.length <=1) return list;
        var index = parseInt(list.length/2);
        var temp = list[index];
        var left = [];
        var right = [];
        for(var i=0; i<list.length; i++) {
          if( i == index) continue;
          if( list[i] < temp) left.push(list[i]);
          else right.push(list[i]);
        }
        return quicksort(left).concat(temp).concat(quicksort(right));
   }

  • 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
6、数组的去重,尽可能写出多个方法
一、给传入数组arr排序,排序后相同值相邻,新建数组arrSort,遍历arrSort时,如果后一个数组元素与当前数组元素相同,则删除当前元素。
function uniqArr1(arr) {
    let arrSort = arr.sort();
    let i = 0, l = arrSort.length;
    while (i < l) {
        if (arrSort[i + 1] == arrSort[i]) {
            arrSort.splice(i, 1)
            l--;
        } else {
            i++
        }
    }
    return arrSort;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
二、新建数组temp,如果传入数组arr的第i项在arr中第一次出现的位置不是i, 那么表示第i项是重复的,忽略掉,否则就push进temp中。
function uniqArr2(arr) {
    let temp = [];
    temp = arr.filter((item, index) => {
        return arr.indexOf(item) == index
    })
    return temp;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
三、与二同理
function uniqArr3(arr) {
    let temp = [];
    for (let i = 0; i < arr.length; i++) {
        if (arr.indexOf(arr[i]) == i) {
            temp.push(arr[i]);
        }
    }
    return temp;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
四、 新建数组temp,遍历传入数组arr,数组元素不在temp中时,把当前元素push进temp中。
function uniqArr4(arr) {
    let temp = [];
    for (let i = 0; i < arr.length; i++) {
        if (temp.indexOf(arr[i]) == -1) {
            temp.push(arr[i]);
        }
    }
    return temp;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
五、新建数组temp,给传入数组arr排序,遍历arr时,temp只push不与前一值相同的值。
function uniqArr5(arr) {
    arr.sort();
    let temp = [arr[0]];
    for (let i = 1; i < arr.length; i++) {
        if (arr[i] !== temp[temp.length - 1]) {
            temp.push(arr[i]);
        }
    }
    return temp;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
六、新建数组temp、空对象obj,遍历arr时,利用对象的属性不会重复这一特性,如果obj的arr[i]属性不存在,则给obj新增arr[i]属性,并且把 arr[i] push进temp中。
function uniqArr6(arr) {
    let obj = {};
    let temp = [];
    for (let i = 0, l = arr.length; i < l; i++) {
        if (!obj[arr[i]]) {
            obj[arr[i]] = true;
            temp.push(arr[i])
        }
    }
    return temp;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
七、set方式去重
function uniqArr7(arr) {
    return Array.from(new Set(arr))
}
  • 1
  • 2
  • 3

接下来生成随机数组arr来测试一下7种方法的性能。

// 生成随机数组
function setArr() {
    let arr = [];
    for (let i = 0; i < 50000; i++) {
        arr.push(Math.floor(Math.random() * 10000))
    }
    return arr;
}
const arr = setArr();
let start, end;
start = new Date().getTime()
uniqArr1(arr)
end = new Date().getTime()
console.log('uniqArr1耗时', end - start)
start = new Date().getTime()
uniqArr2(arr)
end = new Date().getTime()
console.log('uniqArr2耗时', end - start)
start = new Date().getTime()
uniqArr3(arr)
end = new Date().getTime()
console.log('uniqArr3耗时', end - start)
start = new Date().getTime()
uniqArr4(arr)
end = new Date().getTime()
console.log('uniqArr4耗时', end - start)
start = new Date().getTime()
uniqArr5(arr)
end = new Date().getTime()
console.log('uniqArr5耗时', end - start)
start = new Date().getTime()
uniqArr6(arr)
end = new Date().getTime()
console.log('uniqArr6耗时', end - start)
uniqArr7(arr)
end = new Date().getTime()
console.log('uniqArr7耗时', end - start)
start = new Date().getTime()
  • 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

结果如下:

可见方法六“利用对象的属性不会重复这一特性”和方法七“set方式去重”性能较好。方法五“先sort,再去重”性能也比较好,但是由于sort是在原数组上进行排序,会打乱原数组的顺序。

7、如果有一个大的数组,都是整型,怎么找出最大的前 10 个数
8、说说你对作用域链的理解
作用域链的作用是保证执行环境下对变量和函数的访问是有序的;
作用域链的变量只能向上访问,当变量访问到window对象时即被终止;
(注意:Javascript没有块级作用域。可以通过(function(){})()立即执行的形式实现块级作用域;当然ES6可以通过{}搭配let const形成块级作用域);

函数的作用域内的变量,如果在本作用域内没有找到定义,则会往一层一层上一级查找,直到找到全局作用域,如果都没有则返回undefiened,这种一层一层的类似锁链的关系,叫作用域链
  • 1
  • 2
  • 3
  • 4
  • 5
9、创建 Ajax的过程
(1)创建`XMLHttpRequest`对象,也就是创建一个异步调用对象.

(2)创建一个新的`HTTP`请求,并指定该`HTTP`请求的方法、`URL`及验证信息.

(3)设置响应`HTTP`请求状态变化的函数.

(4)发送`HTTP`请求.

(5)获取异步调用返回的数据.

(6)使用JavaScript和DOM实现局部刷新.

var xmlHttp = new XMLHttpRequest();

xmlHttp.open('GET','demo.php','true');

xmlHttp.send()

xmlHttp.onreadystatechange = function(){

    if(xmlHttp.readyState === 4 & xmlHttp.status === 200){

    }

}

  • 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
10、渐进增强和优雅降级
1、概述
渐进增强和优雅降级这两个概念是在 CSS3 出现之后火起来的。由于低级浏览器不支持 CSS3,但是 CSS3 特效太优秀不忍放弃,所以在高级浏览器中使用CSS3,而在低级浏览器只保证最基本的功能。二者的目的都是关注不同浏览器下的不同体验,但是它们侧重点不同,所以导致了工作流程上的不同。

2、详细解释
2.1 渐进增强(Progressive Enhancement)
一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。

2.2 优雅降级(Graceful Degradation)
一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览。

其实渐进增强和优雅降级并非什么新概念,只是旧的概念换了一个新的说法。在传统软件开发中,经常会提到向上兼容和向下兼容的概念。
渐进增强相当于向上兼容,而优雅降级相当于向下兼容。

3、简析
两者并无好坏之分,只是开发理念上的不同!

优雅降级观点认为应该针对那些最高级、最完善的浏览器来设计网站。而将那些被认为“过时”或有功能缺失的浏览器下的测试工作安排在开发周期的最后阶段,并把测试对象限定为主流浏览器(如 IE、Mozilla 等)的前一个版本。在这种设计范例下,旧版的浏览器被认为仅能提供“简陋却无妨 (poor, but passable)” 的浏览体验。你可以做一些小的调整来适应某个特定的浏览器。但由于它们并非我们所关注的焦点,因此除了修复较大的错误之外,其它的差异将被直接忽略。

渐进增强观点则认为应关注于内容本身。请注意其中的差别:我甚至连“浏览器”三个字都没提。内容是我们建立网站的诱因。有的网站展示它,有的则收集它,有的寻求,有的操作,还有的网站甚至会包含以上的种种,但相同点是它们全都涉及到内容。这使得渐进增强成为一种更为合理的设计范例
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
11、在 Bootstrap 中,下面栅格系统的标准用法中哪个是错误的?
12、你觉得 jQuery 或 Zepto 源码有哪些地方写得好?
1、jquery源码封装在一个匿名函数的自执行环境中,有助于防止变量的全局污染,然后通过传入window对象参数,可以使window对象作为局部变量使用,好处是当jquery中访问window对象的时候,就不用将作用域链退回到顶层作用域了,从而可以更快的访问window对象。同样,传入undefined参数,可以缩短查找undefined时的作用域链
(function( window, undefined ) {

         //用一个函数域包起来,就是所谓的沙箱

         //在这里边var定义的变量,属于这个函数域内的局部变量,避免污染全局

         //把当前沙箱需要的外部变量通过函数参数引入进来

         //只要保证参数对内提供的接口的一致性,你还可以随意替换传进来的这个参数

        window.jQuery = window.$ = jQuery;

    })( window );
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
2、jquery将一些原型属性和方法封装在了jquery.prototype中,为了缩短名称,又赋值给了jquery.fn,这是很形象的写法
3、有一些数组或对象的方法经常能使用到,jQuery将其保存为局部变量以提高访问速度
4、jquery实现的链式调用可以节约代码,所返回的都是同一个对象,可以提高代码效率
13、浏览器页面有哪三层构成,分别是什么,作用是什么?
构成:结构层、表示层、行为层

分别是:HTML、CSS、JavajScript

作用:HTML实现页面结构、CSS完成页面的表现与风格、JavaScript实现客户端的一些功能和业务

 

1、网页的结构层(structural layer)由HTML或XHTML之类的标记语言负责创建,标签就是那些出现在尖括号里的单词,对网页的语义含义做出了描述,但这些标签不包含任何关于如何显示有关的信息,例如p标签表达了这样一种语义:“这是一段文本段”。之前页面布局都习惯采用div标签,这是一个没有任何语义的标签,现在页面制作都倾向于标签的语义化,可以使爬虫更容易捕获到网页信息。

2、网页的表示层(presentation layer)由CSS负责创建、CSS对“如何显示有关内容”作了回答。

3、网页的行为层(behavior layer)负责回答“内容应该如何对事件作出反应”这一问题。这是JavaScript语言和DOM主宰的领域。

网页的表示层和行为层总是存在的,即使我们未明确地给出任何具体的指令也是如此。此时,Web浏览器将把它的默认样式和默认事件处理函数施加在网页的结构层上。例如,浏览器会在呈现“文本段”元素时留出页边距,有些浏览器会在用户把鼠标指针悬停在某个元素的上方时弹出一个显示着该元素的 title 属性值的提示框,等等。 分离在所有的产品设计活动中,选择最适用的工具去解决问题是最基本的原则。具体到网页设计工作。 使用 (X)HTML去搭建文档的结构。  使用 CSS 去设置文档的呈现效果。 使用DOM 脚本去实现文档的行为。      

        不过,在这三种技术之间存在着一些潜在的重叠区域,如:DOM技术可以用来改变网页的结构。在 CSS身上也可以找到这种技术相互重叠的例子。诸如 :hover 和 :focus 之类的预定义符号(伪class属性)使我们可以根据用户触发事件来改变呈现效果。改变元素的呈现效果当然是表示层的“势力范围”,但对用户触发事件做出反应却是行为层的领地。表示层和行为层的这种重叠形成了一个灰色地带。伪 class 属性是 CSS 正在深入 DOM 领地证据,但 DOM在这方面也不是毫无作为。我们完全可以利用 DOM 技术把样式信息施加在HTML 元素身上。分离的效果要做到即使去掉表示层和行为层,文档的内容也依然可以访问,因为“内容才是一切”。而且网页的行为层(javascript) 与其结构(XHTML) 是彼此互不干扰的,不能混杂在一起。还要给行为层“预留退路”,要考虑到如果你的用户禁用了Javascript会怎样?网页是否还可以正常运作。这些理论的东西是基本的思想,具体的大家要在不断的实践过程中去慢慢体会。总之,这三种技术就像是一个凳子的三条腿,要想成为一名技能全面的全栈Web 工程师,就必须熟练掌握这三种技术,并知道每种技术最适用于哪一类问题。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
14、HTML5 的优点与缺点?
优点:

网络标准

HTML5本身是由W3C推荐出来的,它的开发是通过谷歌,苹果,诺基亚,中国移动等几百家公司一起酝酿的技术,这个技术最大的好处在于它是一个公开的技术。换句话说,每一个公开的标准都可以根据W3C的资料库找寻根源。另一方面,W3C通过的HTML5标准也就意味着每一个浏览器或每一个平台都会去实现。

多设备跨平台

使用平台,甚至可以通过HTML5的优点主要在于,这个封装的技术发放到App Store或Google Play上,所以它的跨平台性非常强大,这也是大多数人对HTML5有兴趣的主要原因。

自适应网页设计

很早就有人设想,能不能“一次设计,普遍适用”,让同一张网页自动适应不同大小的屏幕,根据屏幕宽度,自动调整布局(布局)。

2010年,Ethan Marcotte提出了“自适应网页设计”这个名词,指可以自动识别屏幕宽度,并做出相应调整的网页设计。

这就解决了传统的一种局面 - 网站为不同的设备提供不同的网页,比如专门提供一个个移动版本,或者iPhone / iPad版本。这样做固然保证了效果,但是比较麻烦,同时要维护好几个版本,而且如果一个网站有多个入口(入口),会大大增加架构设计的复杂度。

即时更新

游戏客户端每次都要更新,很麻烦。可是更新HTML5游戏就好像更新页面一样,是马上的,即时的更新。

优点概括:a,网络标准统一,HTML5本身是由W3C推荐出来的。

          B,多设备,跨平台 

          C,即时更新。

          d,提高可用性和改进用户的友好体验;

          e,有几个新的标签,这将有助于开发人员定义重要的内容; 

          f,可以给站点带来更多的多媒体元素(视频和音频);  

          g,可以很好的替代闪存和Silverlight中;

          h,涉及到网站的抓取和索引的时候,对于SEO很友好; 

          i,被大量应用于移动应用程序和游戏。 

 

缺点:

          a,安全:像之前Firefox4的web socket和透明代理的实现存在严重的安全问题,同时web storage,web socket这样的功能很容易被黑客利用,来盗取用户的信息和资料。 

          B,完善性:许多特性各浏览器的支持程度也不一样。 

          c,技术门槛:HTML5简化开发者工作的同时代表了有许多新的属性和API需要开发者学习,像web worker,web socket,web storage等新特性,后台甚至浏览器原理的知识,机遇的同时也是巨大的挑战 

          d,性能:某些平台上的引擎问题导致HTML5性能低下。 

          E,浏览器兼容性:最大缺点,IE9以下浏览器几乎全军覆没。
  • 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
15、介绍模块化发展历程
1、IIFE
利用闭包实现模块化,把代码包装到单独的函数作用域中执行。核心思想是建一个管理中心,提供注册模块和获取模块的方法,注册的模块需要记录起来,通过依赖注入的方式注入到依赖的模块中。整个实现过程很简单,在《你不知道的javascript(上)》中有详细实现过程。IIFE只是一种解决思想,它是不够完善的,如没有异步加载js模块。
  • 1
2、AMD规范

​ requireJS是其实现库,先看一下它的模块定义方式

define('./module.js', function(expr) {
  // 模块主体
})
  • 1
  • 2
  • 3

​ 其中module.js是模块的依赖项,expr是依赖模块的返回值。感觉上跟IIFE是很类似的,只是在IIFE的基础上增加了异步加载模块的。commonJS只在第一次引用时执行,之后会被缓存。

3、commomJS

​ node的模块加载方式,在浏览器端的实现是webpack

require('module')	// 加载模块
module.exports = {} // 导出模块
  • 1
  • 2

​ 这里的模块可以是任意一个文件,它的加载是同步的。node是执行时同步加载,webpack是提前编译打包处理。module其实是commonJS运行时注入到每一个模块的

4、CMD规范

​ seaJS是其实现库,先看一下它的模块定义方式

define(function(require, exports, module) {
	// require加载模块的函数,有异步跟同步的加载
	// exports导出对象,是module.exports的一个键引用,所以千万不要改变它的指针
	// module模块的定义函数主体,提供了一些模块操作的方法
})
  • 1
  • 2
  • 3
  • 4
  • 5

​ 特定很明显啦,模块的导出和引用方式跟commonJS一模一样,同时支持了异步加载模块的方式。所以说它是集合了commonJs和AMD规范

5、ES6模块化标准

​ ES6制定的模块化标准,目前在浏览器上使用需要使用Babel转成es5

import {moduleName} from 'xxx' // 引入模块
export moduleName = xxx // 导出模块
  • 1
  • 2

​ 有一些注意点:模块内容只会执行一次,但是模块接口是静态定义,它在编译阶段生成,每次引用都是新的返回值

16、对前端模块化的认识

AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
AMD 是提前执行,CMD 是延迟执行。
AMD推荐的风格通过返回一个对象做为模块对象,CommonJS的风格通过对module.exports或exports
的属性赋值来达到暴露模块对象的目的。

CMD模块方式
define(function(require, exports,module) {
// 模块代码
});
  • 1
  • 2
  • 3
  • 4
17、Javascript 垃圾回收方法
1、标记清除(mark and sweep)
这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回
收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”。
垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中
变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了

2、引用计数(reference counting)
在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的
策略是跟踪记录每个值被使用的次数,当声明了一个变量并将一个引用类型赋值给该变量的时候这个值
的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变
为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回
收器会在运行的时候清理掉引用次数为0的值占用的空间。
在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回
收垃圾的,
也就是说只要涉及BOM及DOM就会出现循环引用问题。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
18、TCP 和 UDP 的区别
1.TCP
1.1 TCP的优点
可靠,稳定。
TCP的可靠体现在TCP在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制,在数据传完后,还会断开连接用来节约系统资源。

1.2 TCP的缺点
慢,效率低,占用系统资源高,易被攻击。
TCP在传递数据之前,要先建连接,这会消耗时间,而且在数据传递时,确认机制、重传机制、拥塞控制机制等都会消耗大量的时间,而且要在每台设备上维护所有的传输连接,事实上,每个连接都会占用系统的CPU、内存等硬件资源。 而且因为TCP有确认机制、三次握手机制,这些也导致TCP容易被人利用,实现DOS、DDOS、CC等攻击。

2.UDP
2.1 UDP的优点
快,比TCP稍安全。
UDP没有TCP的三次握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议,所以它在传递数据时非常快。没有TCP的这些机制,UDP较TCP被攻击者利用的漏洞就要少一些。但UDP也是无法避免攻击的,比如:UDP Flood攻击。

2.2 UDP的缺点
不可靠,不稳定 。
因为UDP没有TCP那些可靠的机制,在数据传递时,如果网络质量不好,就会很容易丢包。

3.TCP与UDP区别
TCP	UDP
面向连接	面向非连接
可靠(保证数据正确性)	不可靠(可能丢包)
效率低(慢)	效率高(快)
保证数据顺序	不保证数据顺序
占用系统资源高	占用系统资源低
面向字节流	面向报文
传输大量数据	传输少量数据
全双工可靠信道	不可靠信道
浏览器、文件传输	微信视频、语音
4.总结
1、TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接。

2、TCP提供可靠的服务。通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。

3、TCP面向字节流,实际上是TCP把数据看成一连串无结构的字节流;UDP是面向报文的。
UDP没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等)

4、每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信

5、TCP首部开销20字节;UDP的首部开销小,只有8个字节

6、TCP的逻辑通信信道是全双工的可靠信道,UDP则是不可靠信道

5.应用场景
5.1 什么时候应该使用TCP?
当对网络通讯质量有要求的时候使用TCP,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。 在日常生活中,常见使用TCP协议的应用如下: 浏览器,用的HTTP FlashFXP,用的FTP Outlook,用的POP、SMTP Putty,用的Telnet、 QQ文件传输 。

5.2 什么时候应该使用UDP?
当对网络通讯质量要求不高的时候使用UDP,要求网络通讯速度能尽量的快,这时就可以使用UDP。 比如,日常生活中,常见使用UDP协议的应用如下: QQ语音 QQ视频 (实时传递)
有些应用场景对可靠性要求不高会用到UPD,比如长视频,要求速率
  • 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
19、谈谈性能优化问题
代码层面:避免使用css表达式,避免使用高级选择器,通配选择器。
缓存利用:缓存Ajax,使用CDN,使用外部js和css文件以便缓存,添加Expires头,服务端配置Etag,
减少DNS查找等
请求数量:合并样式和脚本,使用css图片精灵,初始首屏之外的图片资源按需加载,静态资源延迟加
载。
请求带宽:压缩文件,开启GZIP,
代码层面的优化
用hash-table来优化查找
少用全局变量
用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能
用setTimeout来避免页面失去响应
缓存DOM节点查找的结果
避免使用CSS Expression
避免全局查询
避免使用with(with会创建自己的作用域,会增加作用域链长度)
多个变量声明合并
避免图片和iFrame等的空Src。空Src会重新加载当前页面,影响速度和效率
尽量避免写在HTML标签中写Style属性
移动端性能优化
尽量使用css3动画,开启硬件加速。
适当使用touch事件代替click事件。
避免使用css3渐变阴影效果。
可以用transform: translateZ(0)来开启硬件加速。
不滥用Float。Float在渲染时计算量比较大,尽量减少使用
不滥用Web字体。Web字体需要下载,解析,重绘当前页面,尽量减少使用。
合理使用requestAnimationFrame动画代替setTimeout
CSS中的属性(CSS3 transitions、CSS3 3D transforms、Opacity、Canvas、WebGL、Video)会触发
GPU渲染,请合理使用。过渡使用会引发手机过耗电增加
PC端的在移动端同样适用
  • 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
20、什么是 Etag?
Etag由服务器端生成,客户端通过If-Match或者说If-None-Match这个条件判断请求来验证资源是否修改。常见的是使用If-None-Match。

Etag的作用:主要为了解决 Last-Modified 无法解决的一些问题。

请求流程如下:

当发送一个服务器请求时,浏览器首先会进行缓存过期判断。浏览器根据缓存过期时间判断缓存文件是否过期。

情景一:若没有过期,则不向服务器发送请求,直接使用缓存中的结果,此时我们在浏览器控制台中可以看到 200 OK(from cache) ,此时的情况就是完全使用缓存,浏览器和服务器没有任何交互的。  

情景二:若已过期,则向服务器发送GET请求,此时请求中会带上文件修改时间和Etag。


然后,进行资源更新判断。服务器根据浏览器传过来的文件修改时间,判断自浏览器上一次请求之后,文件是不是没有被修改过;根据Etag,判断文件内容自上一次请求之后,有没有发生变化。



情形一:若两种判断的结论都是文件没有被修改过,则服务器就不给浏览器发index.html的内容了,直接告诉它,文件没有被修改过,你用你那边的缓存吧—— 304 Not Modified,此时浏览器就会从本地缓存中获取index.html的内容。此时的情况叫协议缓存,浏览器和服务器之间有一次请求交互。

情形二:若修改时间和文件内容判断有任意一个没有通过,则服务器会受理此次请求,之后的操作同情景一。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
21、javascript 继承的 6 种方法
1、原型链继承

该方法共享同一块内存空间,可以继承父属性原型链上的方法,makeMoney()

function Parent(name, age){
    this.name = 'bob';
    this.age ='age';
    this.hobby = ['play','reading','learn']
}
Parent.prototype.makeMoney = function(){
    console.log('12334556');
}
function Child(){
    this.hobby=['Book', 'Moive']
}
Child.prototype = new Parent();
var Child1 = new Child()
console.log(Child1);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
2、构造函数继承

构造函数继承的方式不能访问父亲原型链上面的属性和方法

function Parent(name, age){
    this.name = 'name';
    this.age =age;
    this.hobby = ['play','reading','learn']
}
Parent.prototype.makeMoney = function(){
    console.log('12334556');
}
function Child(){
    Parent.call(this)
}
var Child1 = new Child('bob',18)
console.log(Child1.name);
console.log(Child1.makeMoney());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
3、组合继承

组合继承是继承方式一和二的组合,但是两次开辟空间,存在空间上的浪费

function parent(name, age){
    this.name = name;
    this.age =age;
    this.hobby = ['play','reading','learn']
}
// 父亲原型链上定义的方法
parent.prototype.makeMoney = function(){
    console.log('12334556');
}
 
function Child(){
    // 第一次调用
    parent.call(this)
}
// 第二次调用
Child.prototype = new parent();
Child.prototype.constructor = Child;
 
var Child1 = new Child()
console.log(Child1.hobby);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
4、原型式继承
var person = {
    name : "李白",
    friends : ["杜甫","杜牧"]
};
 
var child = Object.create(person);
console.log(child.name);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

和原型链继承存在同样的缺陷,最终指向了同一块引用地址,存在篡改可能

5、寄生式继承

先使用原型式继承可以获得一份目标的浅拷贝对象,然后利用浅拷贝能力进行增强添加其他方法。优缺点和原型式继承一样,但是相比原型式继承添加了更多方法

const o = {
    name:'bob',
    age:18,
    hobby:['reading','learn','paly']
}
// 寄生式继承
function clone(o){
    let clone = Object.create(o);
    clone.getHoddy = function(){
        return this.hobby
    }
    return clone
}
let person = clone(o)
console.log(person.age);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
6、寄生组合式继承(最优)

ES6实现继承的底层逻辑(extends)

function clone(parent, child){
    // 改用object.create
    child.prototype = Object.create(parent.prototype);
    child.prototype.constructor = child;
}
function parent() {
    this.name = 'parent';
    this.play = ['reading','learn']
}
parent.prototype.getName = function(){
    return this.name
}
function child(){
    parent.call(this);
    this.firend = 'pp'
}
clone(parent, child);
child.prototype.getFirend = function (){
    return this.firend
}
 
let child1 = new child();
console.log(child1.firend);
console.log(child1.name);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
22、创建 ajax 的过程
(1)创建`XMLHttpRequest`对象,也就是创建一个异步调用对象.

(2)创建一个新的`HTTP`请求,并指定该`HTTP`请求的方法、`URL`及验证信息.

(3)设置响应`HTTP`请求状态变化的函数.

(4)发送`HTTP`请求.

(5)获取异步调用返回的数据.

(6)使用JavaScript和DOM实现局部刷新.

var xmlHttp = new XMLHttpRequest();

xmlHttp.open('GET','demo.php','true');

xmlHttp.send()

xmlHttp.onreadystatechange = function(){

    if(xmlHttp.readyState === 4 & xmlHttp.status === 200){

    }

}
  • 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
23、异步加载和延迟加载
1、异步加载
(function() {
var s = document.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'http://yourdomain.com/script.js';
var x = document.getElementsByTagName('script')[0];
 x.parentNode.insertBefore(s, x);
})();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

异步加载也叫非阻塞模式加载,浏览器在下载js的同时,同时还会执行后续的页面处理。
在script标签内,用js创建一个script元素并插入到document中,这种就是异步加载js文件了。

同步加载流程是瀑布模型,异步加载流程是并发模型。

2、延迟加载
前面解决了异步加载(async loading)问题,再谈谈什么是延迟加载。
延迟加载:有些 js 代码并不是页面初始化的时候就立刻需要的,而稍后的某些情况才需要的。延迟加载就是一开始并不加载这些暂时不用的js,而是在需要的时候或稍后再通过js 的控制来异步加载。
也就是将 js 切分成许多模块,页面初始化时只加载需要立即执行的 js ,然后其它 js 的加载延迟到第一次需要用到的时候再加载。
特别是页面有大量不同的模块组成,很多可能暂时不用或根本就没用到。
就像图片的延迟加载,在图片出现在可视区域内时(在滚动条下拉)才加载显示图片
  • 1
  • 2
  • 3
  • 4
  • 5
24、ie 各版本和 chrome 可以并行下载多少个资源
IE6:2个;
IE7:4个;
IE8+:6个
FireFox,Chrome:6个。

补充:同一时间针对同一域名下的请求有一定数量限制,超过限制数目的请求会被阻塞。大多数浏览器的并发数量都控制在6以内。有些资源的请求时间很长,因而会阻塞其他资源的请求。因此,对于一些静态资源,如果放到不同的域名下面就能实现与其他资源的并发请求。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
25、Flash、Ajax 各自的优缺点,在使用中如何取舍?
Flash ajax 对比
(1)Flash 适合处理多媒体、矢量图形、访问机器;对CSS、处理文本上不足,不容易被搜索。
(2)ajax 对 CSS、文本支持很好,支持搜索;多媒体、矢量图形、机器访问不足。
共同点:与服务器的无刷新传递消息、用户离线和在线状态、操作 DOM
  • 1
  • 2
  • 3
  • 4
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/994668
推荐阅读
相关标签
  

闽ICP备14008679号