PDD
笔试题型:单选12道、填空4、问答4
1.数组
var arraynew = new Array(5)
arraynew[1]=1
arraynew[5]=2
console.log(arraynew.length)//6
2.flex-flow由哪两个属性组成
flex-flow是flex-direction和flex-wrap的简写
3.requestAnimationFrame
4.proxy和reflect
5.readyState状态码
readyState,是指运行Ajax所经历过的几种状态,无论访问是否成功都将响应的步骤,可以理解成为Ajax运行步骤,使用“ajax.readyState”获得。
readyState是XMLHttpRequest对象的一个属性,用来标识当前XMLHttpRequest对象处于什么状态。
readyState总共有5个状态值,分别为0~4,每个值代表了不同的含义。
0:未初始化,尚未调用open()方法
1:启动,已经调用open()方法,尚未调用send()方法
2:发送,已经调用send()方法,但尚未收到响应
3:接受,已经接收到部分响应数据
4:完成,已经接收到全部响应数据,而且已经可以在客户端使用了
只要readyState属性的值由一个值变成另一个值,都会触发一次readystatechange
事件。可以利用这个事件来检测每次状态变化后readyState的值。通常,我们只对readyState
值为4的阶段感兴趣,因为这时所有数据都已经就绪。不过,必需在调用open()
前指定onreadystatechange
事件处理程序才能确保跨浏览器兼容性。如下示例:
var xhr= new XMLHttpRequest()
xhr.onreadystatechange=function () {
if (xhr.readyState==4){
if ((xhr.status>=200 && xhr.status<300) || xhr.status==304){
console.log(xhr.responseText)
}else {
console.log("request was unsuccessful:"+xhr.status)
}
}
}
xhr.open("get”,”example.txt”,true)
xhr.send(null);
以上代码利用DOM 0级方法为XHR对象添加了事件处理程序,原因是并非所有浏览器都支持DOM 2级方法。与其他事件处理程序不同,这里没有像onreadystatechange事件处理程序中传递event对象;必须通过XHR对象本身来确定下一步该怎么做,因为如果使用了this对象(onreadystatechange事件处理作用域的问题),在有的浏览器中会导致函数执行失败或者导致错误发生。因此使用实际的XHR对象实例变量是较为可靠的一种方式。
6.html预加载link中的rel属性是什么值?
link
元素规定了外部资源与当前文档的关系。常用于链接样式表,创建网站图标,预加载资源等。
用于前端界面性能优化,rel 的属性值可以为preload、prefetch、dns-prefetch。
preload
控制当前界面的资源下载优先级,浏览器必须下载资源。
举个例子: 网站的一个界面 A的 css 样式文件中使用了外部字体文件,正常情况下该字体的下载是在 css 解析的时候完成的。想想字体文件好像在 css 样式文件解析之前下载到本地比较好。那么我们就可以在head标签设置字体的 preload。
<link rel="preload" href="https://example.com/fonts/font.woff" as="font">
prefetch 预获取
用户在使用当前界面时,浏览器空闲时先把下个界面要使用的资源下载到本地缓存。浏览器下不下载不可知。
举个例子: 网站有A,B 两个界面。当用户访问界面 A 时有很大的概率会访问 B 界面(比如登录跳转)那么我们可以在用户访问界面 A 的时候,提前将 B 界面需要的某些资源下载到本地,性能会得到很大的提升。那么我们只需要在界面 A.html 文件中设置如下代码:
<link rel="prefetch" href="/uploads/images/pic.png">
dns-prefetch
先把要跳转的域名解析,减少时间。
7.至少写三种清除浮动的方式
//使用伪元素清除浮动
.clearfix:after{
content:"";/*设置内容为空*/
clear:both;/*清除浮动*/
display:block;/*将文本转为块级元素*/
height:0;/*高度为0*/
visibility:hidden;/*将元素隐藏*/
}
.clearfix{
zoom:1;/*为了兼容IE*/
}
开启BFC——overflow:hidden
开启BFC——float:left
8.读代码
var num1=1
var num2=2
function cal(){
var num1=10,num2=20;
console.log(this.num1+this.num2)
}
new cal()//NaN
cal()//3
var calbind=cal.bind({num1=100,num2=200})
//Uncaught SyntaxError: Invalid shorthand property initializer
9.http和https的区别
- (1)https协议需要到ca申请证书,一般免费证书很少,需要交费。
- (2)http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
- (3)http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
- (4)http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
10.垂直水平居中
画一个圆垂直水平居中,圆中显示当前电脑的时间(XXXX-YY-ZZxx-yy-zz格式)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
#wrap{
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -50px;
width: 100px;
height:100px;
}
#inner{
display:flex;
width:100%;
height:100%;
align-items:center;
background:pink;
border-radius: 50%;
text-align: center;
}
</style>
</head>
<body>
<div id="wrap"><div id="inner"></div></div>
<script src="pdd.js"></script>
</body>
</html>
var circle=document.getElementById('inner')
var date=new Date()
var year=date.getFullYear(); //获取当前年份
var mon=date.getMonth()+1; //获取当前月份
var da=date.getDate(); //获取当前日
var day=date.getDay(); //获取当前星期几
var h=date.getHours(); //获取小时
var m=date.getMinutes(); //获取分钟
var s=date.getSeconds(); //获取秒
circle.innerHTML=year+'-'+mon+'-'+da+'\n'+h+'-'+m+'-'+s
携程
选择题20道、编程题3道(没有js选择),整体题型偏数据结构、操作系统
1.进程间的通信方式
进程之间有直接通信和间接通信两种方式。
管道
一个进程向存储空间的一端写入信息,另一个进程存储空间的另外一端读取信息,这个就是管道。
信号
信号是在软件层次上对中断机制的一种模拟,是一种异步通信方式。
信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。它可以在任何时候发给某一进程,而无需知道该进程的状态。
在计算机中,信号就是一个内核对象或者是一个内核数据结构。发送方将该数据结构的内容填好,并指明该信号的目标进程后,发出特定的软件中断(这就是一个发电报的操作)。OS接收到特定的中断请求后,知道是有进程要发送信号,于是到特定的内核数据结构里查找信号接收方,并进行通知。接到通知的进程则对信号进行相应处理。
信号量
信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
在计算机中,信号量实际上就是一个简单整数。一个进程在信号变为0或1的情况下推进,并将信号变为1或0来防止别的进程同时推进。当该进程完成任务后,则将信号再改为0或1,从而允许其他进程执行。从而我们也可以看出,信号量已经不只是一种通信机制,更是一种同步机制。
共享内存
共享内存(shared memory)可以说是最有用的进程间通信方式,也是最快的IPC形式。两个不同进程A、B共享内存的意思是,同一块物理内存被映射到进程A、B各自的进程地址空间。进程A可以即时看到进程B对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。
套接口
套接口(socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。
消息队列
消息队列是一列具有头和尾的消息排列,新来的消息放在队列尾部,而读取消息则从队列头部开始。这样看来,它和管道十分类似,一头读,一头写?的确,看起来很像管道,但又不是管道:
(1)消息队列无固定的读写进程,任何进程都可以读写;而管道需要指定谁读和谁写;
(2)消息队列可以同时支持多个进程,多个进程可以读写消息队列;即所谓的多对多,而管道是点对点;
(3)消息队列只在内存中实现,而管道还可以在磁盘上实现;
2.二叉树遍历
二叉树的重要性质
性质一:在二叉树的第 i 层上最多有2^(i-1)个结点(i≥1)。
性质二:深度为 k 的二叉树最多有2^k-1个结点(k≥1)。
性质三:对任一二叉树,叶子结点数为X,度为2的结点数为Y,则X=Y+1。
衍生(分类)
- 满二叉树(full binary tree):一棵深度为 k 且有 2^k-1个结点的二叉树称为满二叉树。
- 完全二叉树(complete binary tree):一棵深度为 k 的满二叉树的第 k 层的右边几个结点不存在则为完全二叉树。
- 平衡二叉树:它的左右两个子树的高度差的绝对值不超过 1,并且左右两个子树都是一棵平衡二叉树。
- 二叉搜索树(也叫二叉查找树或者二叉排序树):若它的左子树不为空,则左子树上所有节点的值均小于它的根节点的值;若它的右子树不为空,则右子树上所有节点的值均大于它的根节点的值;它的左、右子树也分别是二叉排序树。说明它是一颗有顺序的树,左子树节点的值小于根节点的值,右子树节点的值大于根节点的值。
二叉树存储
- 顺序存储
二叉树的顺序存储结构就是用一维数组存储二叉树中的节点,并且节点的存储位置,也就是数组的下标要能体现节点之间的逻辑关系。如果某个节点的索引为 i,(假设根节点的索引为 0)则在它左子节点的索引会是 2i+1,以及右子节点会是 2i+2。
- 链式存储
因为在二叉树中,一个父节点最多只允许 2 个子节点,所以我们只需要一个存储数据和左右子节点的指针,这样的结构就是链式存储,也叫二叉链表。
完全二叉树
完全二叉树除了具有普通二叉树的性质,它自身也具有一些独特的性质:
性质四:n 个结点的完全二叉树的深度为 ⌊log2 n⌋+1。
性质五:对于任意一个完全二叉树来说,如果将含有的结点按照层次从左到右依次标号(如图 3a)),对于任意一个结点 i ,完全二叉树还有以下3个结论成立:
- 当 i>1 时,父亲结点为结点 [i/2] 。(i=1 时,表示的是根结点,无父亲结点)
- 如果 2×i>n(总结点的个数) ,则结点 i 肯定没有左孩子(为叶子结点);否则其左孩子是结点 2×i 。
- 如果 2×i+1>n ,则结点 i 肯定没有右孩子;否则右孩子是结点 2×i+1
二叉树遍历
- 前序遍历
根左右
先访问根节点,然后前序遍历左子树,再前序遍历右子树。根据上面的二叉树前序遍历结果是 ECBADGFH。
- 中序遍历
左根右
从根节点开始(注意并不是先访问根节点),中序遍历根节点的左子树,然后是访问根节点,最后中序遍历右子树。根据上面的二叉树中序遍历结果是 ABCDEFGH。
- 后序遍历
左右根
从左到右先叶子节点后父节点的方式遍历访问左右子树,最后是访问根节点。根据上面的二叉树后序遍历结果是 ABDCFHGE。
- 层序遍历
从树的第一层,也就是根节点开始访问,从上而下逐层遍历,在同一层中,按从左到右的顺序对节点逐个访问。根据上面的二叉树层序遍历结果是 ECGBDFHA。
3.哈夫曼编码
4.快速排序
//思想:挖坑填数+分治
// 分治,将原始数组分为较小的数组
//选择中间值作为主元
//创建两个指针,左指针指向数组第一个元素,右指针指向数组最后一个元素
//移动左指针找到一个比主元大的值,移动右指针找到一个比主元小的值,然后交换,重复,直到左指针超过右指针
//接着,对划分的小数组重复上述操作
var arr = [49, 38, 65, 97, 76, 13, 27, 49];
console.log('arr:' + arr); //打印排序前的数组
quickSort(arr, 0, arr.length-1);
console.log('sortArr:' + arr); //打印排序后的数组
function quickSort(arr,low,high){ //数组 排序部分的初始索引 排序部分的结尾索引
var key = arr[low]; //设置起始索引值为基准值
var start = low;
var end = high;
while(end > start) {
while (end > start && arr[end] >= key) end--; //从右侧开始搜索
if (arr[end] < key) { //需要判断,因为可能右侧没有比基准值小的
var temp = arr[end];
arr[end] = arr[start];
arr[start] = temp;
}
while (end > start && arr[start] <= key) start++;
if (arr[start] > key) { //可能左侧没有比基准值大的
var temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
}
}
console.log('newArr:' + arr); //每次排完打印一次,显示几条就说明排了几次
//排完后start等于end,即基准值在此次排序中的最终位置
if (start > low+1) quickSort(arr, low, start - 1);
//如果start小等于low+1,说明左侧只有0或者1个数字,不需要再进行排序
if (end < high-1) quickSort(arr, end + 1, high);
//同理可得
}
5.归并排序
6.TCP连接,客户端和服务端通信过程
从 TCP 连接的视角看 Socket 过程:
来源
TCP 三次握手的 Socket 过程:
- 服务器调用
socket()
、bind()
、listen()
完成初始化后,调用accept()
阻塞等待; - 客户端 Socket 对象调用
connect()
向服务器发送了一个 SYN 并阻塞; - 服务器完成了第一次握手,即发送 SYN 和 ACK 应答;
- 客户端收到服务端发送的应答之后,从
connect()
返回,再发送一个 ACK 给服务器; - 服务器 Socket 对象接收客户端第三次握手 ACK 确认,此时服务端从
accept()
返回,建立连接。
接下来就是两个端的连接对象互相收发数据。
TCP 四次挥手的 Socket 过程:
- 某个应用进程调用
close()
主动关闭,发送一个 FIN; - 另一端接收到 FIN 后被动执行关闭,并发送 ACK 确认;
- 之后被动执行关闭的应用进程调用
close()
关闭 Socket,并也发送一个 FIN; - 接收到这个 FIN 的一
- 端向另一端 ACK 确认。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。