我的笔试与面试题目

by Teobler on 05/11/2017

undefined views

8月9月发生了很多事,一度停止了所有活动,包括学习。

10月份来到成都寻找自己人生中的第一份工作。这一个月里跑了成都几乎所有的大学,电子科大清水河校区很大,但是现在我已经不需要导航了,感觉自己已经摸清了每一条达大道;川大望江校区古朴的校园景色可能我爸会很喜欢吧;西南交大安保很严,门口的小吃街很不错;成信感觉比电子科大还要远。

这一个月最大的遗憾是被thoughtworks刷掉,追问个清楚之后只能说技不如人,甘拜下风。最后选择了没有大家那么夸张,但是可能是现在的自己能拿到的算是不错的offer。静下心来,回顾下这一个月来的得失,总结总结那些题目,好好沉淀,相信自己会有更好的提升。

回忆下这一个月来遇到的有印象的所有笔试面试题,大概就是下面这些了,也附上自己后知后觉的答案,部分答案来自网络,如有侵权,请联系我,答案仅供参考。

前端相关

数组与字符串的操作中,slice、splice、split、join是干什么的,详细说明。

  • slice方法接收一个或者两个参数。只有一个参数时,该方法返回该参数位置到数组末尾的所有项;两个参数时返回两个参数中间的所有项(不包括第二参数所在项)。该方法不影响原数组
  • splice方法用于数组的删除、插入和修改,splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项(如果没有删除任何项,则返回一个空数组,该方法会影响原数组,其用法如下:
    • 删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。 例如,splice(0,2)会删除数组中的前两项
    • 插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、0(要删除的项数) 和要插入的项。 如果要插入多个项, 可以再传入第四、第五, 以至任意多个项。 例如, splice(2,0,"red","green")会从当前数组的位置 2 开始插入字符串"red"和"green"
    • 替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起 始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如, splice (2,1,"red","green")会删除当前数组位置 2 的项,然后再从位置 2 开始插入字符串 "red"和"green"
  • split方法接收两个参数,第一个参数为字符串或正则,将字符串按照相应的字符串或正则划分成若干个元素的数组,第二个参数为该数组的元素个数,默认为划分全部
  • join方法接收一个参数,以该参数来分隔数组中的每一个元素,使其成为一个字符串,该方法不会影响原数组

水平居中与垂直居中你知道哪些方法,以及如何居中一个浮动元素?

/*水平居中*/
.target {
  width: n px;
  margin: 0 auto;
}

.target {
  width: fit-content;
  margin: 0 auto;
}

.father {
  text-align:center;
  
  target {
    display: inline-block;
  }
}

.grandfather {
  float: left;
  width: 100%;
  position: relative;
  overflow: hidden;
  
  .father {
    float: left;
    position: relative;
    left:50%
    
    .target {
      float:left;
      position: relative;
      right: 50%;
    }
  }
}

.grandfather {
  position: relative;

  .father {
    position: absolute;
    left: 50%;
    
    .target {
      float: left;
      position: absolute;
      right: 50%;
    }
  }
}

.father {
  display: flex;
  justify-content: center;//水平方向
  align-items: center; //垂直方向
  
  .target {}
}

/*垂直*/
.father{
  display: table;
  
  .target{
    display: table-cell;
    vertical-align: middle;
  }
}

.target{
  height: n px;
  position: absolute;
  top: 50%;
  margin-top: -n/2 px;
}

.target{
  height: 200px;
  position: absolute;
  top: 0; bottom: 0; left: 0; right: 0;
  margin: auto;
}

.target{ 
  height: 200px;
  line-height: 200px;
}

创建一个对象的几种方法

  • 工厂模式
  • 构造函数模式
  • 原型模式
  • 构造函数和原型组合模式
  • 动态原型模式
  • 寄生构造模式
  • 稳妥构造模式

实在不想总结代码了

清除浮动的几种方法

.container {
  .left {
    float: left;
  }
  .right {
    float: right;
  }
  .clear {
    clear: both;
  }
}

.container {
  overflow: hidden;
  zoom: 1;  //兼容IE
  
  .left {
    float: left;
  }
  .right {
    float: right;
  }
}

.container {
  zoom: 1;
  
  .left {
    float: left;
  }
  .right {
    float: right;
  }
  &:after{
    content: ""; 
    display: block; 
    height: 0; 
    clear: both; 
    visibility: hidden; 
  }
}

position的各个属性

  • static:默认值,元素按照默认的块级或内联样式进行显示
  • relative:相对定位,设置了该属性后,元素会根据具体的top、bottom、left、right进行偏移,但是原位置仍保留
  • absolute:绝对定位,设置了该属性后,元素脱离文档流,原位置也就不保留,根据相应的top、bottom、left、right进行定位,同时会被加上一个块级框
  • fixed:相对于浏览器窗口进行定位,展现方式类似于absolute

需要注意的是,relative的元素,其包含块是其第一个块级父元素;而absolute元素的包含块为第一个position不是static的祖先元素,没有的话就是根元素;相应的fixed元素的包含块则为浏览器窗口。

他们的偏移都是相对于其包含块进行偏移的。

display的常用属性

  • block:块级显示。一个块级元素会新开一行并尽可能的撑满容器
  • inline:行内显示。一个行内元素可以在段落中包裹一些内容而不打乱段乱的布局,宽高无用。例如 a 标签
  • none:隐藏显示,不会保留该元素的占位。visibility 属性则保留
  • inline-block:行内块元素,同时具有块元素的宽高属性和行内元素的同行属性
  • table:此元素会作为块级表格来显示(类似table),表格前后带有换行符
  • inline-table:此元素会作为内联表格来显示(类似table),表格前后没有换行符

说说你对盒子模型的理解

  • 块级元素:html文档中的每个元素都被描绘成矩形盒子,这些矩形盒子通过一个模型来描述其占用空间,这个模型称为盒模型。盒模型通过四个边界来描述:margin(外边距),border(边框),padding(内边距),content(内容区域)
  • 行内元素:
    1. 对于非替换元素,比如a,span标签等 (1)可以设置margin-left和margin-right属性,无法设置margin-top和margin-bottom属性 (2)行内元素border和padding可以设置,但是border-top和padding-top到页面顶部后就不再增加
    2. 对于替换元素,比如input,img标签,margin,padding,border都有效果
  • IE盒模型:IE的盒模型有一点不同的是,其width等于content + padding;而标准盒模型width等于content

cookie、sessionStorage、localStorage的区别

  • cookie 数据始终在同源的 http 请求中携带(即使不需要),即 cookie 在浏览器和服务器间来回传递;cookie 数据还有路径(path)的概念,可以限制cookie只属于某个路径下。存储大小限制也不同,cookie 数据不能超过4k,同时因为每次http请求都会携带 cookie,所以 cookie 只适合保存很小的数据,如会话标识
  • sessionStorage 和 localStorage 不会自动把数据发给服务器,仅在本地保存。sessionStorage 和 localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大
  • 数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie 只在设置的 cookie 过期时间之前一直有效,即使窗口或浏览器关闭
  • 作用域不同,sessionStorage 不在不同的浏览器窗口中共享,即使是同一个页面;localStorage 在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。Web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者。Web Storage 的 api 接口使用更方便

cookie 和session 的区别

  • cookie数据存放在客户的浏览器上,session数据放在服务器上
  • cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
  • 所以如果考虑到安全应当使用session
  • 但是session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
  • 所以如果考虑到减轻服务器性能方面,应当使用COOKIE
  • 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie

H5新增标签有哪几个

  • <article>标签定义外部的内容。比如来自一个外部的新闻提供者的一篇新的文章,或者来自 blog 的文本,或者是来自论坛的文本。亦或是来自其他外部源内容
  • <aside>标签定义 article 以外的内容。aside 的内容应该与 article 的内容相关
  • <audio> 标签定义声音,比如音乐或其他音频流
  • <canvas> 标签定义图形,比如图表和其他图像。这个 HTML 元素是为了客户端矢量图形而设计的。它自己没有行为,但却把一个绘图 API 展现给客户端 JavaScript 以使脚本能够把想绘制的东西都绘制到一块画布上
  • <command> 标签定义命令按钮,比如单选按钮、复选框或按钮
  • <datalist> 标签定义可选数据的列表。与 input 元素配合使用,就可以制作出输入值的下拉列表
  • <details> 标签定义元素的细节,用户可进行查看,或通过点击进行隐藏。与 <legend> 一起使用,来制作 detail 的标题。该标题对用户是可见的,当在其上点击时可打开或关闭 detail
  • <embed> 标签定义嵌入的内容,比如插件
  • <figcaption> 标签定义 figure 元素的标题。”figcaption” 元素应该被置于 “figure” 元素的第一个或最后一个子元素的位置
  • <figure> 标签用于对元素进行组合。使用 <figcaption> 元素为元素组添加标题
  • <footer> 标签定义 section 或 document 的页脚。典型地,它会包含创作者的姓名、文档的创作日期以及/或者联系信息
  • <header> 标签定义 section 或 document 的页眉
  • <hgroup> 标签用于对网页或区段(section)的标题进行组合
  • <keygen> 标签定义生成密钥
  • <mark>主要用来在视觉上向用户呈现那些需要突出的文字。<mark>标签的一个比较典型的应用就是在搜索结果中向用户高亮显示搜索关键词
  • <meter> 标签定义度量衡。仅用于已知最大和最小值的度量。必须定义度量的范围,既可以在元素的文本中,也可以在 min/max 属性中定义
  • <nav> 标签定义导航链接的部分
  • <output> 标签定义不同类型的输出,比如脚本的输出
  • <progress> 标签运行中的进程。可以使用 <progress> 标签来显示 JavaScript 中耗费时间的函数的进程
  • <rp> 标签在 ruby 注释中使用,以定义不支持 ruby 元素的浏览器所显示的内容
  • <rt> 标签定义字符(中文注音或字符)的解释或发音
  • <ruby> 标签定义 ruby 注释(中文注音或字符)
  • <section> 标签定义文档中的节(section、区段)。比如章节、页眉、页脚或文档中的其他部分。
  • <source> 标签为媒介元素(比如 <video><audio>)定义媒介资源
  • <summary> 标签包含 details 元素的标题,”details” 元素用于描述有关文档或文档片段的详细信息。”summary” 元素应该是 “details” 元素的第一个子元素
  • <time> 标签定义日期或时间,或者两者
  • <video> 标签定义视频,比如电影片段或其他视频流

转自大前端

从输入URL到网页渲染的过程

  • DNS解析:将URL地址解析为IP地址
  • TCP连接:三次握手
  • 发送HTTP请求
  • 服务器处理请求并返回HTTP报文
  • 浏览器解析渲染页面
  • 连接结束:四次挥手

http请求头与响应头的内容

  • 请求头:Accept, Accept-Charset, Accept-Encoding, Accept-Language, Content-Type, Authorization, Cookie, User-Agent
  • 响应头:Server, Connection...

跨域问题与jsonp原理

浏览器的同源策略会导致跨域,这里同源策略又分为以下两种:

  1. DOM同源策略:禁止对不同源页面DOM进行操作。主要场景是iframe跨域的情况,不同域名的iframe是限制互相访问的。
  2. XmlHttpRequest同源策略:禁止使用XHR对象向不同源的服务器地址发起HTTP请求。只要协议、域名、端口有任何一个不同,都被当作是不同的域,之间的请求就是跨域操作。

同时解决跨域问题一般也有两种:

  1. 跨域资源共享:
  • 对于客户端,需要设置ajax请求的xhr属性withCredentials = true
  • 对于服务器端,需要在 response header中设置如下两个字段: Access-Control-Allow-Origin: http://www.yourhost.com Access-Control-Allow-Credentials:true
  1. jsonp实现跨域:基本原理就是通过动态创建script标签,然后利用src属性进行跨域,例如:
// 定义一个fun函数
function fun(fata) {
    console.log(data);
};
// 创建一个脚本,并且告诉后端回调函数名叫fun
var body = document.getElementsByTagName('body')[0];
var script = document.gerElement('script');
script.type = 'text/javasctipt';
script.src = 'demo.js?callback=fun';
body.appendChild(script);

//返回的脚本会直接执行,我们也就拿到了想要的数据
fun({"name": "name"})

什么是闭包,闭包的作用是什么

浅显点来说,闭包指的是定义在函数内部的函数,它能够访问函数外部无法访问到的变量,那么如果将其返回到外部作用域,则我们就能够在外部作用域访问到函数内的变量了。换句话说,所谓闭包函数,即这个函数封闭了它自己的定义时的环境,形成了一个闭包。当然这样的说法是很不严谨的,具体请看MDN

作用:访问内部变量、实现封装(私有方法)、保存某个变量的值

typeof返回的类型

  • object
  • string
  • number
  • function
  • symbol
  • undefined
  • boolean

谈谈你对作用域链的理解

我们先来看一段代码

function person(hobby){
  var name = '小明';
  var age = '12';
  console.log(name, age, hobby);
}
  1. person定义以后生成函数对象,函数对象有一个[[scope]]属性指向定义person时的作用域空间,也就是person定义时所在的变量对象
  2. person运行时生成当前变量对象,变量对象会把传参和内部定义的局部变量和函数全部设置为自己的属性
  3. 比如person('打羽毛球')运行时要查找name,就是去当前变量对象查找name属性,如果查找不到,就查找person函数对象的[[scope]]属性引用的变量对象
  4. 综上,函数运行时查找资源,是先查当前变量对象,查找不到就找该函数对象[[scope]]属性引用的变量对象,以此类推,一直向上找,直到全局对象,如果还查找不到,就报出语法错误

你对前端性能优化有什么看法

这个比较多了,请移步我的另一篇文章

谈谈你对原型链的理解

function Person(name,age){
    this.name=name;
    this.age=age;
}

Person.prototype={
    "constructor":Person,
    "showName":function(){
        console.log(this.name);
    },
    "showAge":function(){
        console.log(this.age);
    }
}
var newPerson=new Person('小明',21);

代码中我们通过new构造函数Person,生成实例化对象newPerson,那么newPerson就有一个隐形属性__proto__指向Person.prototype原型对象。

  1. 现在访问newPerson.name,因为newPerson对象上有name属性,值为“小明”,这个可以直接访问到
  2. 现在我们访问newPerson.showName方法呢,newPerson对象上并没有直接定义showName方法,访问不到,然后newPerson就会通过__proto__属性找到Person.prototype,也就是Person的原型对象,看看能不能访问到showName方法,现在是可以访问到了。
  3. 如果Person.prototype对象里面也没有showName方法呢?那就通过Person.prototype对象的__proto__继续找,在原型链查找中,一般到Object.prototype.__proto__还查找不到时,就会终止查找,因为ECMA规范里说明Object.prototype.__proto__是原型链终点,值为null,而这个时候那个没有访问到的属性值设置为undefined,并不爆出语法错误,这是原型链查找和作用域链查找的一个显著区别

什么是ajax

简单来说ajax就是一种在不刷新整个网页的前提下向服务器发送请求,并接收数据填充页面的一种技术。关键在于异步请求数据,局部刷新页面内容。我们来看一个例子:

// ajax基于XMLHttpRequest对象
var request = new XMLHttpRequest();

// 当请求成功后监听状态变化
request.onreadystatechange = function() {
  if (this.readyState == 4 && this.status == 200) {
    console.log(request.responseText) // 此处为返回内容
  }
};

// 设置请求参数
request.open("GET", "filename", true);

// 发送请求
request.send();

谈谈你对webpack的看法

WebPack 是一个模块打包工具,你可以使用WebPack管理你的模块依赖,并编绎输出模块们所需的静态文件。它能够很好地管理、打包Web开发中所用到的HTML、JavaScript、CSS以及各种静态文件(图片、字体等),让开发过程更加高效。对于不同类型的资源,webpack有对应的模块加载器。webpack模块打包器会分析模块间的依赖关系,最后 生成了优化且合并后的静态资源。

webpack的两大特色:

  1. code splitting(可以自动完成)
  2. loader 可以处理各种类型的静态文件,并且支持串联操作 webpack 是以commonJS的形式来书写脚本滴,但对 AMD/CMD 的支持也很全面,方便旧项目进行代码迁移。

webpack具有requireJs和browserify的功能,但仍有很多自己的新特性:

  1. 对 CommonJS 、 AMD 、ES6的语法做了兼容
  2. 对js、css、图片等资源文件都支持打包
  3. 串联式模块加载器以及插件机制,让其具有更好的灵活性和扩展性,例如提供对CoffeeScript、ES6的支持
  4. 有独立的配置文件webpack.config.js
  5. 可以将代码切割成不同的chunk,实现按需加载,降低了初始化时间
  6. 支持 SourceUrls 和 SourceMaps,易于调试
  7. 具有强大的Plugin接口,大多是内部插件,使用起来比较灵活
  8. webpack 使用异步 IO 并具有多级缓存。这使得 webpack 很快且在增量编译上更加快

安全相关

这方面的知识说实话到写文章之前我没有经过任何实践,但是遇到了问题也没办法,只能先理解概念,日后有机会了慢慢实践吧

sql注入原理

就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。总的来说有以下几点:

  1. 永远不要信任用户的输入,要对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引号和双"-"进行转换等
  2. 永远不要使用动态拼装SQL,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取
  3. 永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接
  4. 不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息

XSS原理及防范

Xss(cross-site scripting)攻击指的是攻击者往Web页面里插入恶意 html 标签或者 javascript 代码。比如:攻击者在论坛中放一个看似安全的链接,骗取用户点击后,窃取cookie中的用户私密信息;或者攻击者在论坛中加一个恶意表单,当用户提交表单的时候,却把信息传送到攻击者的服务器中,而不是用户原本以为的信任站点。

XSS防范方法:

  • 首先代码里对用户输入的地方和变量都需要仔细检查长度和对< > , ; , ’ 等字符做过滤;其次任何内容写到页面之前都必须加以encode,避免不小心把 html、 tag 弄出来。这一个层面做好,至少可以堵住超过一半的 XSS 攻击
  • 其次,避免直接在cookie 中泄露用户隐私,例如email、密码等等
  • 再次,通过使 cookie 和系统 ip 绑定来降低 cookie 泄露后的危险。这样攻击者得到的 cookie 没有实际价值,不可能拿来重放
  • 如果网站不需要再浏览器端对cookie 进行操作,可以在Set-Cookie 末尾加上 HttpOnly 来防止javascript 代码直接获取cookie
  • 最后,尽量采用 POST 而非 GET 提交表单

XSS与CSRF有什么区别吗?

XSS是获取信息,不需要提前知道其他用户页面的代码和数据包。CSRF是代替用户完成指定的动作,需要知道其他用户页面的代码和数据包。

要完成一次CSRF攻击,受害者必须依次完成两个步骤:

  1. 登录受信任网站A,并在本地生成Cookie
  2. 在不登出A的情况下,访问危险网站B。

CSRF的防御:

  • 服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数
  • 通过验证码的方法
  • Web Worker 和webSocket

worker主线程:

1.通过 worker = new Worker( url ) 加载一个JS文件来创建一个worker,同时返回一个worker实例。

2.通过worker.postMessage( data ) 方法来向worker发送数据。

3.绑定worker.onmessage方法来接收worker发送过来的数据。

4.可以使用 worker.terminate() 来终止一个worker的执行。

WebSocket是Web应用程序的传输协议,它提供了双向的,按序到达的数据流。他是一个Html5协议,WebSocket的连接是持久的,他通过在客户端和服务器之间保持双工连接,服务器的更新可以被及时推送给客户端,而不需要客户端以一定时间间隔去轮询。

HTTP和HTTPS有什么区别,为什么HTTPS要安全

HTTP协议通常承载于TCP协议之上,在HTTP和TCP之间添加一个安全协议层(SSL或TSL),这个时候,就成了我们常说的HTTPS。

默认HTTP的端口号为80,HTTPS的端口号为443。

因为网络请求需要中间有很多的服务器路由器的转发。中间的节点都可能篡改信息,而如果使用HTTPS,密钥在你和终点站才有。https之所以比http安全,是因为他利用ssl/tsl协议传输。它包含证书,卸载,流量转发,负载均衡,页面适配,浏览器适配,refer传递等。保障了传输过程的安全性

网络相关

TCP协议的三次握手与四次挥手你知道吗

TCP连接作为一种可靠的连接协议,为了保证连接的可靠性,在连接和断开连接时分别进行了3次和4次连接和断开确定,具体内容如下:

三次握手:

  1. 建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认
  2. 服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态
  3. 客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手

四次挥手:

  1. 当主机A的应用程序通知TCP数据已经发送完毕时,TCP向主机B发送一个带有FIN附加标记的报文段(FIN表示英文finish)
  2. 主机B收到这个FIN报文段之后,并不立即用FIN报文段回复主机A,而是先向主机A发送一个确认序号ACK,同时通知自己相应的应用程序:对方要求关闭连接(先发送ACK的目的是为了防止在这段时间内,对方重传FIN报文段)
  3. 主机B的应用程序告诉TCP:我要彻底的关闭连接,TCP向主机A送一个FIN报文段
  4. 主机A收到这个FIN报文段后,向主机B发送一个ACK表示连接彻底释放

一些标志位的解释:

  • SYN:同步标志。同步序列编号(Synchronize Sequence Numbers)栏有效。该标志仅在三次握手建立TCP连接时有效。它提示TCP连接的服务端检查序列编号,该序列编号为TCP连接初始端(一般是客户端)的初始序列编号。在这里,可以把TCP序列编号看作是一个范围从0到4,294,967,295的32位计数器。通过TCP连接交换的数据中每一个字节都经过序列编号。在TCP报头中的序列编号栏包括了TCP分段中第一个字节的序列编号
  • ACK:确认标志。确认编号(Acknowledgement Number)栏有效。大多数情况下该标志位是置位的。TCP报头内的确认编号栏内包含的确认编号(w+1,Figure:1)为下一个预期的序列编号,同时提示远端系统已经成功接收所有数据
  • FIN:结束标志。带有该标志置位的数据包用来结束一个TCP回话,但对应端口仍处于开放状态,准备接收后续数据。 服务端处于监听状态,客户端用于建立连接请求的数据包(IP packet)按照TCP/IP协议堆栈组合成为TCP处理的分段(segment)

OSI七层模型是哪七层,TCP、IP、http协议分别在哪层,数据包在里边是怎么传输的

数据包在协议层中一层层加上该层的数据头,之后在网络节点中寻找下一跳的目标,到达目标节点后解包到对应的协议传输层获取下一跳的目的地,之后重新打包发送,到达最后的目的地之后又层层解包,得到最初发送的数据。

TCP和UDP的区别

TCP(Transmission Control Protocol,传输控制协议)是基于连接的协议,也就是说,在正式收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次“对话”才能建立起来

UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去

UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境。

关于Http 2.0 你知道多少?

  • HTTP/2引入了“服务端推(server push)”的概念,它允许服务端在客户端需要数据之前就主动地将数据发送到客户端缓存中,从而提高性能
  • HTTP/2提供更多的加密支持
  • HTTP/2使用多路技术,允许多个消息在一个连接上同时交差
  • 它增加了头压缩(header compression),因此即使非常小的请求,其请求和响应的header都只会占用很小比例的带宽

编程通识

面向对象的理解,面向对象的三要素,是什么意思

首先我们需要明确的是,面向对象是相对于面向过程来讲的,我在知乎上看到过一个例子,说的很形象,这里分享下:

假如你要充话费,那么你可以下个支付宝,然后绑定银行卡,然后在淘宝充值,这个叫做面向过程。然后你的女朋友也要充值话费了,但是她跟你想的是不一样的,她会想,谁会充话费呢?当然是你了,她就给你电话号码,然后你把之前的做了一遍,然后她就充值成功了。这就是面向对象。女的思维大部分是面向“对象”的!她不关心处理的细节,只关心谁可以,和结果。印证了面向对象的那句经典的话:你办事,我放心!

三要素:封装、继承、多态

  • 封装就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。 简单的说,一个类就是一个封装了数据以及操作这些数据的代码的逻辑实体。在一个对象内部,某些代码或某些数据可以是私有的,不能被外界访问。通过这种方式,对象对内部数据提供了不同级别的保护,以防止程序中无关的部分意外的改变或错误的使用了对象的私有部分
  • 继承是指可以让某个类型的对象获得另一个类型的对象的属性的方法。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”,被继承的类称为“基类”、“父类”或“超类”。继承的过程,就是从一般到特殊的过程。要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。继承概念的实现方式有二类:实现继承与接口继承。实现继承是指直接使用基类的属性和方法而无需额外编码的能力;接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力
  • 多态就是指一个类实例的相同方法在不同情形有不同表现形式。多态机制使具有不同内部结构的对象可以共享相同的外部接口。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用(继承与多态是一个整体不可分割的概念,可以参考我之前的这篇文章

栈和队列的区别?

  • 栈的插入和删除操作都是在一端进行的,而队列的操作却是在两端进行的
  • 队列先进先出,栈先进后出
  • 栈只允许在表尾一端进行插入和删除,而队列只允许在表尾一端进行插入,在表头一端进行删除
  • 栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等
  • 堆区(heap) — 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收
  • 堆(数据结构):堆可以被看成是一棵树,如:堆排序
  • 栈(数据结构):一种先进后出的数据结构

你所熟知的数据结构、差别、使用场景

  1. 单向链表:典型的应用场合是各类缓冲池和栈的实现,适用于只从一端单向访问的场合,这种场合一般来说:
  • 删除时,只适合删除第一个元素
  • 添加时,只直接添加到最后一个元素的后面或者添加到第一个元素的前面
  • 属于单向迭代器,只能从一个方向走到头(只支持前进或后退,取决于实现),查找效率极差。不适合大量查询的场合。
  1. 双向链表:这种典型的应用场景是各种不需要排序的数据列表管理,相比单向链表,拥有前向和后向两个指针地址,所以适合以下场合:
  • 删除时,可以删除任意元素,而只需要极小的开销
  • 添加时,当知道它的前一个或后一个位置的元素时,只需要极小的开销
  • 属于双向迭代器,可以从头走到尾或从尾走到头,但同样查找时需要遍历,效率与单向链表无改善,不适合大量查询的场合。
  1. 数组:这种数据结构使用一段连续的空间来存贮元素,所以可以直接通过索引来获取到某个元素,而且可以通过对元素的内容进行排序,然后使用二分法查找,从而提供查找效率。其适合的场合主要是:
  • 不会频繁增删元素的场合,因为增删元素都牵涉到元素空间的重新分配,频繁的内存分配操作会大幅降低操作效率。但添加操作时,可以通过预分配足够的空间来优化添加时的效率
  • 属于随机迭代器,可以随机访问任意元素。对于已排序的元素查找起来效率较高
  1. 二叉树:(含红黑树、平衡二叉树等)这个数据结构类似于双向链表,任意插入元素时都会自动排序,红黑树和平衡二叉树都使二叉树尽量平衡,从而使查询时和二分法类似。它适合的场合主要是:
  • 需要时刻保证列表元素的有序排列
  • 需要频繁的增删和查询操作
  • 属于双向迭代器,不能随机访问任意元素
  1. 哈希桶:这个数据结构使用数组和链表来管理元素,在好的桶尺寸和哈希算法支持下,理想上可以达到接近数组的随机访问效率。其适合的场合主要是:
  • 不需要保证元素的顺序(因为它是按哈希值决定插入到那个桶里,与原始数据内容无关)
  • 需要频繁的增删和查询操作
  • 属于单向或双向迭代器(取决于具体实现),不能随机访问任意元素

XML和JSON的区别?

  1. 数据体积方面,JSON相对于XML来讲,数据的体积小,传递的速度更快些
  2. 数据交互方面,JSON与JavaScript的交互更加方便,更容易解析处理,更好的数据交互
  3. 数据描述方面,JSON对数据的描述性比XML较差
  4. 传输速度方面,JSON的速度要远远快于XML

算法

二叉树求和

let sum = 0;
preOrder = (Node) => {
  if(Node) {
    sum += Node;
    preOrder(Node.children[0]);
    preOrder(Node.children[1]);
  }
}

数组去重

// 法1
let arr = [1,1,'1','1',null,null,undefined,undefined];
let newArr = Array.from(new Set(arr));

// 法2
unique = (arr) => {
  let res = arr.filter((item, index, arr) => {
    return arr.indexOf(item) === index;
  })
}

在记录了两个算法以后实在是觉得抛开一线互联网公司,一般的公司其实前端的算法题目在所有技术岗中算是比较“弱智”,而自己的实力实在是够不到一线的边,所以目前来说遇到的算法题目觉得没有太多记录的必要,需要的小伙伴建议刷刷《剑指offer》和 leetcode 好了,这里就不再记录我遇到的算法题目了。