前端面试知识自己的一些整理 ---持续更新中

— title: 自己整理的面试复习资料
date: 2019-03-20 12:27:51
tags: 面试 前端


CSS3+H5

[CSS3.0 帮助文档.chm](CSS3.0 帮助文档.chm)

注意:CSS3不支持IE6,7,8。兼容性

flex弹性布局:

<参考资料:http://www.runoob.com/w3cnote/flex-grammar.html>

**兼容性问题:**Webkit内核的浏览器,必须加上-webkit前缀。

.box{
  display: -webkit-flex; /* Safari */
  display: flex;
}

注意:设为Flex布局以后,子元素的float、clear和vertical-align属性将失效。

1.基本概念

采用Flex布局的元素,称为Flex容器(flex container),简称”容器”。它的所有子元素自动成为容器成员,称为Flex项目(flex item),简称”项目”。

主轴:橫 交叉轴:竖

2.容器具有的属性
flex-direction

决定主轴的方向(项目的排列方向)

  • row(默认值):主轴为水平方向,起点在左端。
  • row-reverse:主轴为水平方向,起点在右端。
  • column:主轴为垂直方向,起点在上沿。
  • column-reverse:主轴为垂直方向,起点在下沿。
flex-wrap

定义如果一条轴线排不下,如何换行。

  • nowrap(默认值) :不换行(会把项目压缩
  • wrap :换行
  • wrap-reverse: 换行,第一行在下面
flex-flow

属性和flex-wrap属性的简写形式

.box {
  flex-flow: flex-direction flex-wrap;
}
justify-content

项目在主轴上的对齐方式。

  • flex-start(默认值):左对齐
  • flex-end:右对齐
  • center: 居中
  • space-between:两端对齐,项目之间的间隔都相等。
  • space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
align-items

定义项目在交叉轴上如何对齐

  • flex-start:交叉轴的起点对齐。
  • flex-end:交叉轴的终点对齐。
  • center:交叉轴的中点对齐。
  • baseline: 项目的第一行文字的基线对齐。
  • stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
align-conten

定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用

3.项目具有的属性****
  1. order:定义项目的排列顺序。数值越小,排列越靠前,默认为0。

  2. flex-grow:定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

  3. flex-shrink:定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

  4. flex-basis:

    定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。

    设为跟width或height属性一样的值(比如350px),则项目将占据固定空间。

  5. flex:flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。

  6. align-self:允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto表示继承父元素的align-items属性,如果没有父元素,则等同于stretc

    该属性可取6个值,除了auto,其他都与align-items属性完全一致。

    .item {
      align-self: auto | flex-start | flex-end | center | baseline | stretch;
    }
    

transtion:过渡

语法格式:

transition: 要过渡的属性  花费时间  运动曲线  何时开始;
属性描述CSS
transition简写属性,用于在一个属性中设置四个过渡属性。3
transition-property规定应用过渡的 CSS 属性的名称。3
transition-duration定义过渡效果花费的时间。默认是 0。3
transition-timing-function规定过渡效果的时间曲线。默认是 “ease”。3
transition-delay规定过渡效果何时开始。默认是 0。3
img {
  width:80px; height: 80px; border:8px solid #ccc; border-radius: 50%;
  transition:transform 0.5s ease-in 0s;
}
img:hover {
  transform:rotate(180deg);
}

响应式开发相关

布局方式:固定宽度布局 流式布局栅 格化布局 响应式布局(主流)

响应式布局:缺点。代码冗余,性能拥挤,但是开发效率高

适用于官网博客,新闻资讯等内容性网站

@media 媒体查询

针对不同媒体类型(或者说屏幕宽度)自适应采用不同的样式规则。当你重置浏览器大小的过程中,页面会根据浏览器的宽度和高度重新渲染页面。

用于响应式布局,根据设备屏幕不同

常用区间值

超小屏幕(移动设备)xsw<768px
小屏设备(平板)sm768px-992px768<=w<992
中等屏幕(电脑1024)md992px-1200px992=<w<1200
宽屏设备lg1200px以上w>=1200

使用 @media 查询,你可以针对不同的媒体类型定义不同的样式。

@media 可以针对不同的屏幕尺寸设置不同的样式,特别是如果你需要设置设计响应式的页面,@media 是非常有用的。

当你重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面

向上兼容:如果设置了小的,小的会传递到大的

向下覆盖:宽度大的覆盖前面宽度更小的

书写顺序建议

如果判断最小值:从小到大写

如果判断最大值:从大到小写

  1. 媒体查询的基本实现方式:常用属性设置: http://www.runoob.com/cssref/css3-pr-mediaquery.html

a) CSS 语法

@media mediatype and|not|only (media feature) {
   CSS-Code;
}

1、and 可以将多个媒体特性连接到一起,相当于“且”的意思。

2、not 排除某个媒体类型,相当于“非”的意思,可以省略。

3、only指定某个特定的媒体类型,可以省略。

<!--你也可以针对不同的媒体使用不同 stylesheets :  -->
<link rel="stylesheet" media="mediatype and|not|only (media feature)" href="mystylesheet.css">

b) 媒体类型

描述
all用于所有设备
print用于打印机和打印预览
screen用于电脑屏幕,平板电脑,智能手机等。
speech应用于屏幕阅读器等发声设备

c) 媒体功能

描述
device-width定义输出设备的屏幕可见宽度。
max-device-height定义输出设备的屏幕可见的最大高度。
max-device-width定义输出设备的屏幕最大可见宽度。
min-device-width定义输出设备的屏幕最小可见宽度。
min-device-height定义输出设备的屏幕的最小可见高度。
max-height定义输出设备中的页面最大可见区域高度。
max-width定义输出设备中的页面最大可见区域宽度。
min-height定义输出设备中的页面最小可见区域高度。
min-width定义输出设备中的页面最小可见区域宽度。
device-height描述定义输出设备的屏幕可见高度。

bootstrap框架(针对bootstrap3)

  • col- 针对所有设备
  • .col-sm- 平板 - 屏幕宽度等于或大于 576px
  • .col-md- 桌面显示器 - 屏幕宽度等于或大于 768px)
  • .col-lg- 大桌面显示器 - 屏幕宽度等于或大于 992px)
  • .col-xl- 超大桌面显示器 - 屏幕宽度等于或大于 1200px)

boostrap是 向上兼容的

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

栅格原理是本质是设置百分比,即流式布局

offset:通过margin,因此会影响其他元素导致换行

列排序

push:通过定位,可能会重叠

pull:通过定位,可能会出现

hidden-xs:在某一屏幕隐藏

less

LESS 是动态的样式表语言,通过简洁明了的语法定义,使编写 CSS 的工作变得非常简单,本质上,LESS 包含一套自定义的语法及一个解析器。

安装

1、安装Nodejs环境 Node Package Manager (验证 node -v npm -v) npm:node packge manager

2、打开控制台(cmd),执行npm install -g less (验证 lessc -v) node packet manager

3、命令行编译 lessc path/xxx.less path/xxx.css

编译

浏览器只能识别CSS,LESS只是用来提升CSS可维护性的一个工具,所最终需要将LESS编译成CSS,然而通过命令行编译效率比较低下,一般都会借助于编辑器来完成编译,以sublime_text为例,sublime_text默认并不支持LESS的编译操作,需要安装插件实现。

1、执行npm install -g less-plugin-clean-css(使用sublime_text才用)

2、ctrl+shit+p打开命令面板

3、输入install package然后回车

4、安装 LESS、lessc、Less2Css三个插件

5、alt+s快捷键即可实现编译

less语法

//语法修改
//变量定义 @变量名:;
@baseColor:#e92322;
div {
    color:@baseColor;
}
//混入:可以将一个定义好的样式引入另一个样式中 类似函数的调用

.addRadius(@r:10px){
    border-radius: @r;
    -webkit-border-radius: @r;
    -moz-border-radius: @r;
}
div{
    width: 200px;
    height: 200px;
    //引入已经写好的圆角样式
    .addRadius();
}
//嵌套:实现选择器的继承,减少代码量,同时使代码结构更加清晰
.jd_header{
    width: 200px;
    height: 200px;
    .addRadius();
    > div{
        &::before{
            content: "";
        }
        width: 100%;
        > h3{
            height: 20px;
            &:hover{
                height: 50px;
            }
        }
    }
}

垂直水平居中

1.水平居中

脱离文档流

  • margin:o auto;
  • 负margin法:先left:50%,然后在给一个负margin-left居中元素宽度的一半
  • transform: translateX:-50%
  • 给父容器设置text-align :center, 然后给子容器加上display:inline-block;

2.垂直居中

脱离文档流

  • margin: auto 0;
  • 负margin法:先top:50%,然后在给一个负margin-top居中元素宽度的一半
  • transform: translateY:-50%

3.table-cell法 和flex弹性盒子法

table-cell法(对低版本IE兼容比较良好)

div {
    display: table-cell;
    width: 200px;
    height: 200px;
    text-align: center;
    vertical-align: middle;
}

flex法:

.container{
width: 300px;
height: 200px;
display: -webkit-flex;        //兼容weikit
display: flex;
-webkit-align-items: center;  //兼容weikit
align-items: center;
-webkit-justify-content: center;   //兼容weikit
justify-content: center;
}

三角形画法

从底向上

#triangle-up {
    width: 0;
    height: 0;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom:100px solid red;
}

transparent属性相当于rgba(0,0,0,0,)全透明的颜色

清除浮动的方法

  • BFC消除浮动法:给父盒子加上overflow:hidden;

    优点: 代码简洁

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

  • 额外标签法:在浮动元素末尾添加一个空的标签例如
    ,或则其他标签br等亦可。

​ 优点: 通俗易懂,书写方便

​ 缺点: 添加许多无意义的标签,结构化较差。

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

  • .clearfix:after {  content: "."; display: block; height: 0; clear: both; visibility: hidden;  }   
     
    .clearfix {*zoom: 1;}   /* IE6、7 专有 */
    
    
  • 优点: 符合闭合浮动思想 结构语义化正确

    缺点: 由于IE6-7不支持:after,使用 zoom:1触发 hasLayout。

background属性详解

  • background-color 背景颜色

  • background-position 背景图片位置(精灵图常用)

  • background-size :规定背景图像的尺寸

  • background-repeat:属性设置是否及如何重复背景图像。(精灵图常用)

  • background-origin:相对于内容框来定位背景图像(目前不常用)background-origin

  • background-clip:规定背景的绘制区域(目前我不常用)

    background-clip: border-box|padding-box|content-box;
    
    
  • background-attachment:规定背景图像是否固定或者随着页面的其余部分滚动(可以用来视差滚动的效果)

  • background-image:设置背景图片(精灵图常用)

  • 缩写方式(更简洁明了,且对低版本的兼容性更高)

div {
    //   缩写必须按顺序来
    //(<颜色> <background-image背景图片> <background-repeat重复背景图片> 
              <background-attachment 背景固定方式>  <背景图片位置>)
	background: #ff0000 url(/i/eg_bg_03.gif) no-repeat fixed center;    
}


兼容性问题

​ 靠积累了这个,常见的要知道,比如CSS3新添加的动画和transition,IE6.7.8都不支持,以及一些H5标签的兼容性问题,JS的原生方法如getElementByClassName,IE低版本不支持,可以采用兼容性写法等等,这个要靠平时多积累

//1 getElementsByClassName方法在IE8以下版本不支持,因此采用这种写法
/
eg.getElementsByClassName = function (className, element) {
    //如果支持则直接返回该方法
    if (document.getElementsByClassName) {
        return (element || document).getElementsByClassName(className);
    }
    //如果不支持则采用兼容性写法
    var children = (element || document).getElementByTagName("*");
    var elements = new Array();

    for (var i = 0; i < children.length; ++i) {
        var child = children[i];
        var classNames = child.className.split(' ');
        //将class样式分割
        for (var j = 0; j < classNames.length; ++j) {
            if (classNames[j] == className) {
                elements.push(child);
                break;
            }
        }
    }
    return elements;
}
///

浏览器前缀

浏览器前缀浏览器
-webkit-Google Chrome, Safari, Android Browser
-moz-Firefox
-o-Opera
-ms-Internet Explorer, Edge
-khtml-Konqueror

H5相关

fetch API
标签语义化
H5新加入的API
localStorage、sessionStorage、Cookie
  • localStorage - 没有时间限制的数据存储
  • sessionStorage - 针对一个 session 的数据存储
canvas
SVG

web worker 是运行在后台的 JavaScript,不会影响页面的性能。(了解)

<参考:http://www.w3school.com.cn/html5/html_5_webworkers.asp>

地理定位(好像国内不常用?一般用百度的,不清楚,我的见识浅显,希望读者可以给我指出错误)

常用布局

圣杯布局

优先渲染中间栏适应

两边侧边栏固定,中间自适应

xxxxxxxxxx <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width, initial-scale=1.0">    <meta http-equiv="X-UA-Compatible" content	="ie=edge">    <title>圣杯布局</title>    <style>        div{            padding: 0;            margin: 0;        }        .container{            padding: 0 200px;            background-color: #eee;            height: 200px;            /* min-width: 400px; */            /* 加上一个最小像素可以让布局不乱 */        }        .left,        .right{            width: 200px;            height: 200px;            background-color: red;            float: left;        }        .main{            width: 100%;            height: 200px;            background-color: blue;            float: left;        }        .left{            margin-left: -100%;            position: relative;            left: -200px;        }        .right{            margin-left: -200px;            position: relative;            right: -200px;        }    </style></head><body>    <div class="container">        <!-- 先加载中间再加载两边 -->        <div class="main">中间中间间中间中间中间中间</div>        <div class="left">左边</div>        <div class="right">右边</div>    </div></body></html>HTML
双飞翼布局
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>双飞翼布局</title>
    <style>
        div{
            padding: 0;
            margin: 0;
        }
        .container{
            background-color: #eee;
            min-width: 400px;
            /* 加上一个最小像素可以让布局不乱 */
        }
        .left,
        .right{
            width: 200px;
            height: 200px;
            background-color: red;
            float: left;
        }
        .main{
            width: 100%;
            height: 200px;
            background-color: blue;
            float: left;
        }
        .left{
            margin-left: -100%;
        }
        .right{
            margin-left: -200px;
        }
        .main_w{
            margin: 0 200px;
         }
    </style>
</head>
<body>
    <div class="container">
        <!-- 先加载中间再加载两边 -->
        <div class="main">
            <div class="main_w">
                    中间栏
            </div>
        </div>
        <div class="left">左边栏</div>
        <div class="right">右边栏</div>
    </div>
</body>
</html>

BFC

BFC(Block formatting context)块级格式化上下文

display 属性为 block, list-item, table 的元素,能产生BFC.

同样,要给这些元素添加如下属性就可以触发BFC。

-float属性不为none

-position为absolute或fixed

-display为inline-block, table-cell, table-caption, flex, inline-flex

-overflow不为visible。

BFC元素所具有的特性

BFC布局规则特性:

1.在BFC中,盒子从顶端开始垂直地一个接一个地排列.

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

3.在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格式来说,则触碰到右边缘)。

  1. BFC的区域不会与浮动盒子产生交集,而是紧贴浮动边缘。
  2. 计算BFC的高度时,自然也会检测浮动或者定位的盒子高度。

它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。

BFC的主要用途

(1) 清除元素内部浮动

只要把父元素设为BFC就可以清理子元素的浮动了,最常见的用法就是在父元素上设置overflow: hidden样式,对于IE6加上zoom:1就可以了。

主要用到

计算BFC的高度时,自然也会检测浮动或者定位的盒子高度。


(2) 解决外边距合并问题

外边距合并的问题。

主要用到

盒子垂直方向的距离由margin决定。属于同一个BFC的两个相邻盒子的margin会发生重叠

属于同一个BFC的两个相邻盒子的margin会发生重叠,那么我们创建不属于同一个BFC,就不会发生margin重叠了。

(3) 制作右侧自适应的盒子问题

主要用到

普通流体元素BFC后,为了和浮动元素不产生任何交集,顺着浮动边缘形成自己的封闭上下文

BFC 总结

BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。包括浮动,和外边距合并等等,因此,有了这个特性,我们布局的时候就不会出现意外情况了。

渐进增强和优雅降级

渐进增强

progressive enhancement:

针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

优雅降级

graceful degradation:

一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

背景渐变

​ 在线性渐变过程中,颜色沿着一条直线过渡:从左侧到右侧、从右侧到左侧、从顶部到底部、从底部到顶部或着沿任何任意轴。

兼容性问题很严重,必须加上浏览器前缀。

线性渐变语法格式:

background:-webkit-linear-gradient(渐变的起始位置, 起始颜色, 结束颜色)
background:-webkit-linear-gradient(渐变的起始位置, 颜色 位置, 颜色位置....)

echarts图表

layer ui框架

JS

原生JS

1.最基本的:隐式转换、数组、字符串、正则 、Date相关方法及DOM操作

  • ​ dom操作:增删改查,操作节点
  • ​ bom:bom对象,事件,表单
  • ​ 错误处理

2.函数:作用域、闭包、垃圾回收

  • this相关:this指向问题
  • 手写bind()、call()、apply()

3.对象 :原型、原型链、构造函数、创建对象的模式、继承、包装对象、深拷贝、浅拷贝、深复制、浅复制

4.同步异步:async与await、定时器、微任务,宏任务

4.ES6相关:let和const、模板字符串、promise、类、super、static以及

5.ES6新加方法:Object.assign()

6.额外技能:github issue 、资料查阅工具等等

7.工作常用: 数组列表 分页

深拷贝

这个文章写得非常好https://www.jianshu.com/p/b08bc61714c7

日常开发常用深拷贝,序列化反序列化法

唯一局限性:只能深拷贝对象和数组,对于其他种类的对象,会失真。

function deepClone(obj){
    return JSON.parse(JSON.stringify(obj));
}

**搞事情深拷贝:能拷贝自身可枚举、自身不可枚举、自身 Symbol 类型键、原型上可枚举、原型上不可枚举、原型上的 Symol 类型键,循环引用也可以拷的深拷贝函数:**2333.

// 将之前写的 deepClone 函数封装一下
function cloneDeep(obj) {
    let family = {}
    let parent = Object.getPrototypeOf(obj)

    while (parent != null) {
        family = completeAssign(deepClone(family), parent)
        parent = Object.getPrototypeOf(parent)
    }

    // 下面这个函数会拷贝所有自有属性的属性描述符,来自于 MDN
    // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
    function completeAssign(target, ...sources) {
        sources.forEach(source => {
            let descriptors = Object.keys(source).reduce((descriptors, key) => {
                descriptors[key] = Object.getOwnPropertyDescriptor(source, key)
                return descriptors
            }, {})

            // Object.assign 默认也会拷贝可枚举的Symbols
            Object.getOwnPropertySymbols(source).forEach(sym => {
                let descriptor = Object.getOwnPropertyDescriptor(source, sym)
                if (descriptor.enumerable) {
                    descriptors[sym] = descriptor
                }
            })
            Object.defineProperties(target, descriptors)
        })
        return target
    }

    return completeAssign(deepClone(obj), family)
}


闭包

能够访问其他函数内部局部变量的函数

能将局部变量的值保存在内存中

在数组中保存函数

一个函数引用外部局部变量也是闭包

可以做一个预编译的函数

数组去重

第一种方法:indexOf():查找当前查询值在当前数组的索引,如果不存在则返回-1

建立新数组,拿到旧数组的每一位,如果新数组不存在,那么就push 进去

function unique1(arr){
    var newArr = [];
    var len =arr.length;
    for(var i =0; i<len ;i++){
        if(newArr.indexOf(arr[i]) == -1){
            newArr.push(arr[i]);
        }
    }
    return newArr;
}

第二种方法:

将数组的元素值作为对象的属性名,借助对象 obj{}:同个对象中不能有同样的属性名

function unique2(arr){
    var newArr = [];
    var obj = {};
    var len = arr.length;
    for(var i = 0;i<len ;++i){
        if(!obj[arr[i]]){
        newArr.push(arr[i]);
        obj[arr[i]] = 1; //只要赋值为一个bool为true的值
        }
    }
    return newArr;
}

第三种方法:ES6的symbol

new Set(arr);
//Set里的值都是独一无二的

DOM

原生JS添加类名 删除类名
为 <div> 元素添加 class:

document.getElementById("myDIV").classList.add("mystyle");

为 <div> 元素添加多个类:

document.getElementById("myDIV").classList.add("mystyle", "anotherClass", "thirdClass");

为 <div> 元素移除一个类:

document.getElementById("myDIV").classList.remove("mystyle");

为 <div> 元素移除多个类:

document.getElementById("myDIV").classList.remove("mystyle", "anotherClass", "thirdClass");

检查是否含有某个CSS类

myDiv.classList.contains('myCssClass'); //return true or false

代码优化

避免双重解释:js代码想解析js代码出现双重解释,非常浪费性能,会创建一个新的js解释器来解释内部的js代码

当使用eval()函数或是Function构造函数以及setTimeout()传一个字符串时都会发生这种情况。如下

//eval//
eval(alert("hello world!"));//避免
alert("hello world!");//修改
//Function//
var sayHi = new Function(alert("hello"));//避免
var sayHi = function(){  //修改
    alert("hello");
}
//setTimeout//
setTimeout('alert("hello");',500)//避免
setTimeout(function(){//修改
    alert("hello");
},500)

AJAX

同源策略

同源是指,域名,协议,端口相同。

浏览器这个策略的本质是一个域名的 JS ,在未经允许的情况下,不得读取另一个域名的内容。但浏览器并不阻止你向另一个域名发送请求,只是在接收加载资源之前对其来源进行了检查,然后限制加载。即拦截的是服务器响应回来的数据

cors跨域

http://www.cnblogs.com/moretry/p/4154479.html

​ 在我们日常的项目开发时使用AJAX,传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求。浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片或者脚本。但是Javascript脚本是不能获取这些资源的内容的,它只能被浏览器执行或渲染。主要原因还是出于安全考虑,浏览器会限制脚本中发起的跨站请求。(同源策略, 即JavaScript或Cookie只能访问同域下的内容)。跨域的解决方案有多重JSONP、Flash、Iframe等,当然还有CORS(跨域资源共享,Cross-Origin Resource Sharing)今天就来了解下CORS的原理,以及如何使用。

一、CORS概述

跨源资源共享标准通过新增一系列 HTTP 头,让服务器能声明那些来源可以通过浏览器访问该服务器上的各类资源(包括CSS、图片、JavaScript 脚本以及其它类资源)。另外,**对那些会对服务器数据造成破坏性影响的 HTTP 请求方法(特别是 GET 以外的 HTTP 方法,或者搭配某些MIME类型的POST请求),标准强烈要求浏览器必须先以 OPTIONS 请求方式发送一个预请求(preflight request),从而获知服务器端对跨源请求所支持 HTTP 方法。确认服务器允许该跨源请求的情况下,以实际的 HTTP 请求方法发送那个真正的请求。**服务器端也可以通知客户端,是不是需要随同请求一起发送信用信息(包括 Cookies 和 HTTP 认证相关数据)。

二、CORS原理

例如:域名A(http://a.example)的某 Web 应用程序中通过标签引入了域名B(http://b.foo)站点的某图片资源(http://b.foo/image.jpg)。这就是一个跨域请求,请求http报头包含Origin: http://a.example,如果返回的http报头包含响应头 Access-Control-Allow-Origin: http://a.example (或者Access-Control-Allow-Origin: http://a.example),表示域名B接受域名B下的请求,那么这个图片就运行被加载。否则表示拒绝接受请求。

三、CORS跨域请求控制方法

1.http请求头

Origin: 普通的HTTP请求也会带有,在CORS中专门作为Origin信息供后端比对,表明来源域。

Access-Control-Request-Method: 接下来请求的方法,例如PUT, DELETE等等

Access-Control-Request-Headers: 自定义的头部,所有用setRequestHeader方法设置的头部都将会以逗号隔开的形式包含在这个头中

2.http响应头

然后浏览器再根据服务器的返回值判断是否发送非简单请求。简单请求前面讲过是直接发送,只是多加一个origin字段表明跨域请求的来源。然后服务器处理完请求之后,会再返回结果中加上如下控制字段

Access-Control-Allow-Origin: 允许跨域访问的域,可以是一个域的列表,也可以是通配符"*"。这里要注意Origin规则只对域名有效,并不会对子目录有效。即http://foo.example/subdir/ 是无效的。但是不同子域名需要分开设置,这里的规则可以参照同源策略

Access-Control-Allow-Credentials: 是否允许请求带有验证信息,XMLHttpRequest请求的withCredentials标志设置为true时,认证通过,浏览器才将数据给脚本程序。

Access-Control-Expose-Headers: 允许脚本访问的返回头,请求成功后,脚本可以在XMLHttpRequest中访问这些头的信息

Access-Control-Max-Age: 缓存此次请求的秒数。在这个时间范围内,所有同类型的请求都将不再发送预检请求而是直接使用此次返回的头作为判断依据,非常有用,大幅优化请求次数

Access-Control-Allow-Methods: 允许使用的请求方法,以逗号隔开

Access-Control-Allow-Headers: 允许自定义的头部,以逗号隔开,大小写不敏感

四、浏览器支持情况

在大部分现代浏览器中有所支持,支持(部分支持)CORS协议的浏览器有IE8+, Firefox5+, Chrome12+, Safari4+,移动端几乎全支持。

img

注:Internet Explorer 8 、9使用 XDomainRequest 对象实现CORS。

五、CORS使用案例

案例环境:客户端使用jQuery,服务端WebApi(2.2)。因本人使用.net语言,所以服务端就使用webApi来演示了。

首先新建一个webApi项目,这里就不截图一步步介绍了,然后使用Nuget安装支持cors的扩展组件,

Install-Package Microsoft.AspNet.WebApi.Cors

然后打开App_Start问价夹下的WebConfig.cs配置文件类,在Register方法中配置一个全局的cors,为了方便我将一些参数配置到web.config配置文件中

img

    <add key="cors_allowOrigins" value="*"/>
    <add key="cors_allowHeaders" value="*"/>
    <add key="cors_allowMethods" value="*"/>

img

            var allowOrigins = ConfigurationManager.AppSettings["cors_allowOrigins"];
            var allowHeaders = ConfigurationManager.AppSettings["cors_allowHeaders"];
            var allowMethods = ConfigurationManager.AppSettings["cors_allowMethods"];
            var globalCors = new EnableCorsAttribute(allowOrigins, allowHeaders, allowMethods);
            config.EnableCors(globalCors);

如果不想使用全局的CORS,可以在某个方法或者ApiController上这样配置:[EnableCors(origins: “", headers: "”, methods: “*”)],可以使用具体的参数,多个参数以逗号分隔,不用说,肯定英文逗号。origins 域名要带上http的顶级域名。需要添加 using System.Web.Http.Cors;

一般请求来说,客户端的AJAX请求不需要做任何改变,只需要服务端稍作改变即可。

客户端js代码: apiRootPath是我预先设置的api的顶级域名。

$.ajax({
    url: apiRootPath + "api/Account/Register",
    type: "post",
    data: {
        "UserName": mobile,
        "Password": pwd
    },
    dataType: "json",
    success: function (data) {
        if (data.State == true) {
            RegSuccess(mobile, pwd);
        } else {
            $("#errorText").html(data.Message);
            $("#registerBtn").text("注册");
        }
    }
});

因为我配置了全局的CORS方法,而且服务端没有特别之处了,和普通的网站(不跨越)写法一致,这里就不予贴出了。

如果需要对请求进行身份验证,怎么办?我们一cookies实现这个验证。

$.ajax({
    url: apiRootPath + "api/Account/Login",
    type: "post",
    data: {
        "UserName": userName,
        "Password": password
    },
    crossDomain: true,
    xhrFields: {
        withCredentials: true
    },
    dataType: "json",
    success: function (data) {
        if (data.State == true) {
            MLogin(userName, password);
        } else {
            $("#loginBtn").text("登录");
            $("#errorText").html(data.Message);
        }
    }
});

注意这个两句话:crossDomain: true,xhrFields: {withCredentials: true}

六:安全隐患

如果程序猿偷懒将Access-Control-Allow-Origin设置为:Access-Control-Allow-Origin: * 允许任何来自任意域的跨域请求,那么久存在被 DDoS攻击的可能。

原型和构造函数

  • 原型是function对象的一个属性,该属性是一个对象

  • 原型是本身就存在的

    • 原型对象中有默认有两个属性,一个是constructor,该属性指向基于该原型的实例的构造函数,
    • 另一个属性是隐式属性 __proto__
  • 绝大多数对象的原型最终都指向Object,除了特殊创建的无原型对象,如下

  • var obj = Object.create(null);
    
    

    该方法创建出来的对象无原型,并且如果后期为其指定 __proto__属性,不会拥有继承特性!!

    null 和undefined是没有原型的

    tip:null为空对象指针,真正的空对象,{ }也是空的对象,但是还有原型属性

prototype的应用:

1.用于提取共有属性

当我们使用构造函数创建属性时,如果出现重复的属性应该用原型来创建,可以减少代码量和冗余,即重复多次使用的属性应该用原型指配,构造函数用来指配特定的对象

原型的增删改查

只能直接对原型进行操作才能成功,否则相当于直接对实例进行添加或修改

特殊情况:引用值属性

对于存在于父链上的引用值,如果进行增加可以使父链上的引用值本身发生变化,因为从子链上进行引用值取用,相当于直接对引用值本身进行操作

DOM阻塞相关

在这里插入图片描述

什么情况下会发生阻塞?

1.遇到script标签加载js的时候
会加载js并且执行完毕才开始渲染
2.遇到alert会阻塞
3.css也会阻塞
css是由单独的下载线程异步下载的。
总结:
1.css加载不会阻塞DOM树的解析
2.css加载会阻塞DOM树(render树)的渲染
3.css加载会阻塞后面js语句的执行

js是全阻塞,css会阻塞js的执行

JS 会阻塞后续 DOM 的解析和其它资源(如 CSS,JS 或图片资源)的加载。

css加载不会阻塞DOM树的解析,不会阻塞其它资源(如图片)的加载,CSS加载会阻塞DOM树的渲染,也会阻塞 JS 文件的执行。

为了避免让用户看到长时间的白屏时间,我们应该尽可能的提高css加载速度,比如可以使用以下几种方法:
使用CDN(因为CDN会根据你的网络状况,替你挑选最近的一个具有缓存内容的节点为你提供资源,因此可以减少加载时间)
对css进行压缩(可以用很多打包工具,比如webpack,gulp等,也可以通过开启gzip压缩)
合理的使用缓存(设置cache-control,expires,以及E-tag都是不错的,不过要注意一个问题,就是文件更新后,你要避免缓存而带来的影响。其中一个解决防范是在文件名字后面加一个版本号)

减少http请求数,将多个css文件合并,或者是干脆直接写成内联样式(内联样式的一个缺点就是不能缓存)

事件相关

事件委托

参考资料:https://www.cnblogs.com/liugang-vip/p/5616484.html(事件委托)

https://www.cnblogs.com/MarcoHan/p/5804362.html(事件绑定、及相关)

概述:

什么叫事件委托呢?它还有一个名字叫事件代理,JavaScript高级程序设计上讲:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。那这是什么意思呢?网上的各位大牛们讲事件委托基本上都用了同一个例子,就是取快递来解释这个现象,我仔细揣摩了一下,这个例子还真是恰当,我就不去想别的例子来解释了,借花献佛,我摘过来,大家认真领会一下事件委托到底是一个什么原理:

有三个同事预计会在周一收到快递。为签收快递,有两种办法:一是三个人在公司门口等快递;二是委托给前台MM代为签收。现实当中,我们大都采用委托的方案(公司也不会容忍那么多员工站在门口就为了等快递)。前台MM收到快递后,她会判断收件人是谁,然后按照收件人的要求签收,甚至代为付款。这种方案还有一个优势,那就是即使公司里来了新员工(不管多少),前台MM也会在收到寄给新员工的快递后核实并代为签收。

这里其实还有2层意思的:

第一,现在委托前台的同事是可以代为签收的,即程序中的现有的dom节点是有事件的;

第二,新员工也是可以被前台MM代为签收的,即程序中新添加的dom节点也是有事件的。

为什么要用事件委托:

一般来说,dom需要有事件处理程序,我们都会直接给它设事件处理程序就好了,那如果是很多的dom需要添加事件处理呢?比如我们有100个li,每个li都有相同的click点击事件,可能我们会用for循环的方法,来遍历所有的li,然后给它们添加事件,那这么做会存在什么影响呢?

在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能;

每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,自然性能就越差了(内存不够用,是硬伤,哈哈),比如上面的100个li,就要占用100个内存空间,如果是1000个,10000个呢,那只能说呵呵了,如果用事件委托,那么我们就可以只对它的父级(如果只有一个父级)这一个对象进行操作,这样我们就需要一个内存空间就够了,是不是省了很多,自然性能就会更好。

事件委托的原理:

事件委托是利用事件的冒泡原理来实现的,何为事件冒泡呢?就是事件从最深的节点开始,然后逐步向上传播事件,举个例子:页面上有这么一个节点树,div>ul>li>a;比如给最里面的a加一个click点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div,有这样一个机制,那么我们给最外面的div加点击事件,那么里面的ul,li,a做点击事件的时候,都会冒泡到最外层的div上,所以都会触发,这就是事件委托,委托它们父级代为执行事件。

事件委托怎么实现:

在介绍事件委托的方法之前,我们先来看一段一般方法的例子:

子节点实现相同的功能:

<ul id="ul1">
    <li>111</li>
    <li>222</li>
    <li>333</li>
    <li>444</li>
</ul>

实现功能是点击li,弹出123:

window.onload = function(){
    var oUl = document.getElementById("ul1");
    var aLi = oUl.getElementsByTagName('li');
    for(var i=0;i<aLi.length;i++){
        aLi[i].onclick = function(){
            alert(123);
        }
    }
}

上面的代码的意思很简单,相信很多人都是这么实现的,我们看看有多少次的dom操作,首先要找到ul,然后遍历li,然后点击li的时候,又要找一次目标的li的位置,才能执行最后的操作,每次点击都要找一次li;

那么我们用事件委托的方式做又会怎么样呢?

window.onload = function(){
    var oUl = document.getElementById("ul1");
   oUl.onclick = function(){
        alert(123);
    }
}

这里用父级ul做事件处理,当li被点击时,由于冒泡原理,事件就会冒泡到ul上,因为ul上有点击事件,所以事件就会触发,当然,这里当点击ul的时候,也是会触发的,那么问题就来了,如果我想让事件代理的效果跟直接给节点的事件效果一样怎么办,比如说只有点击li才会触发,不怕,我们有绝招:

Event对象提供了一个属性叫target,可以返回事件的目标节点,我们成为事件源,也就是说,target就可以表示为当前的事件操作的dom,但是不是真正操作dom,当然,这个是有兼容性的,标准浏览器用ev.target,IE浏览器用event.srcElement,此时只是获取了当前节点的位置,并不知道是什么节点名称,这里我们用nodeName来获取具体是什么标签名,这个返回的是一个大写的,我们需要转成小写再做比较(习惯问题):

window.onload = function(){
  var oUl = document.getElementById("ul1");
  oUl.onclick = function(ev){
    var ev = ev || window.event;
    var target = ev.target || ev.srcElement;
    if(target.nodeName.toLowerCase() == 'li'){
        	alert(123);
         alert(target.innerHTML);
    }
  }
}

这样改下就只有点击li会触发事件了,且每次只执行一次dom操作,如果li数量很多的话,将大大减少dom的操作,优化的性能可想而知!

上面的例子是说li操作的是同样的效果,要是每个li被点击的效果都不一样,那么用事件委托还有用吗?

<div id="box">
        <input type="button" id="add" value="添加" />
        <input type="button" id="remove" value="删除" />
        <input type="button" id="move" value="移动" />
        <input type="button" id="select" value="选择" />
    </div>
window.onload = function(){
            var Add = document.getElementById("add");
            var Remove = document.getElementById("remove");
            var Move = document.getElementById("move");
            var Select = document.getElementById("select");
            
            Add.onclick = function(){
                alert('添加');
            };
            Remove.onclick = function(){
                alert('删除');
            };
            Move.onclick = function(){
                alert('移动');
            };
            Select.onclick = function(){
                alert('选择');
            }
            
        }

[复制代码](javascript:void(0)?

上面实现的效果我就不多说了,很简单,4个按钮,点击每一个做不同的操作,那么至少需要4次dom操作,如果用事件委托,能进行优化吗?

[复制代码](javascript:void(0)?

window.onload = function(){
            var oBox = document.getElementById("box");
            oBox.onclick = function (ev) {
                var ev = ev || window.event;
                var target = ev.target || ev.srcElement;
                if(target.nodeName.toLocaleLowerCase() == 'input'){
                    switch(target.id){
                        case 'add' :
                            alert('添加');
                            break;
                        case 'remove' :
                            alert('删除');
                            break;
                        case 'move' :
                            alert('移动');
                            break;
                        case 'select' :
                            alert('选择');
                            break;
                    }
                }
            }
            
        }

[复制代码](javascript:void(0)?

用事件委托就可以只用一次dom操作就能完成所有的效果,比上面的性能肯定是要好一些的

现在讲的都是document加载完成的现有dom节点下的操作,那么如果是新增的节点,新增的节点会有事件吗?也就是说,一个新员工来了,他能收到快递吗?

看一下正常的添加节点的方法:

[复制代码](javascript:void(0)?

<input type="button" name="" id="btn" value="添加" />
    <ul id="ul1">
        <li>111</li>
        <li>222</li>
        <li>333</li>
        <li>444</li>
    </ul>

[复制代码](javascript:void(0)?

现在是移入li,li变红,移出li,li变白,这么一个效果,然后点击按钮,可以向ul中添加一个li子节点

[复制代码](javascript:void(0)?

window.onload = function(){
            var oBtn = document.getElementById("btn");
            var oUl = document.getElementById("ul1");
            var aLi = oUl.getElementsByTagName('li');
            var num = 4;
            
            //鼠标移入变红,移出变白
            for(var i=0; i<aLi.length;i++){
                aLi[i].onmouseover = function(){
                    this.style.background = 'red';
                };
                aLi[i].onmouseout = function(){
                    this.style.background = '#fff';
                }
            }
            //添加新节点
            oBtn.onclick = function(){
                num++;
                var oLi = document.createElement('li');
                oLi.innerHTML = 111*num;
                oUl.appendChild(oLi);
            };
        }

[复制代码](javascript:void(0)?

这是一般的做法,但是你会发现,新增的li是没有事件的,说明添加子节点的时候,事件没有一起添加进去,这不是我们想要的结果,那怎么做呢?一般的解决方案会是这样,将for循环用一个函数包起来,命名为mHover,如下:

[复制代码](javascript:void(0)?

window.onload = function(){
            var oBtn = document.getElementById("btn");
            var oUl = document.getElementById("ul1");
            var aLi = oUl.getElementsByTagName('li');
            var num = 4;
            
            function mHover () {
                //鼠标移入变红,移出变白
                for(var i=0; i<aLi.length;i++){
                    aLi[i].onmouseover = function(){
                        this.style.background = 'red';
                    };
                    aLi[i].onmouseout = function(){
                        this.style.background = '#fff';
                    }
                }
            }
            mHover ();
            //添加新节点
            oBtn.onclick = function(){
                num++;
                var oLi = document.createElement('li');
                oLi.innerHTML = 111*num;
                oUl.appendChild(oLi);
                mHover ();
            };
        }

[复制代码](javascript:void(0)?

虽然功能实现了,看着还挺好,但实际上无疑是又增加了一个dom操作,在优化性能方面是不可取的,那么有事件委托的方式,能做到优化吗?

[复制代码](javascript:void(0)?

window.onload = function(){
            var oBtn = document.getElementById("btn");
            var oUl = document.getElementById("ul1");
            var aLi = oUl.getElementsByTagName('li');
            var num = 4;
            
            //事件委托,添加的子元素也有事件
            oUl.onmouseover = function(ev){
                var ev = ev || window.event;
                var target = ev.target || ev.srcElement;
                if(target.nodeName.toLowerCase() == 'li'){
                    target.style.background = "red";
                }
                
            };
            oUl.onmouseout = function(ev){
                var ev = ev || window.event;
                var target = ev.target || ev.srcElement;
                if(target.nodeName.toLowerCase() == 'li'){
                    target.style.background = "#fff";
                }
                
            };
            
            //添加新节点
            oBtn.onclick = function(){
                num++;
                var oLi = document.createElement('li');
                oLi.innerHTML = 111*num;
                oUl.appendChild(oLi);
            };
        }

看,上面是用事件委托的方式,新添加的子元素是带有事件效果的,我们可以发现,当用事件委托的时候,根本就不需要去遍历元素的子节点,只需要给父级元素添加事件就好了,其他的都是在js里面的执行,这样可以大大的减少dom操作,这才是事件委托的精髓所在。

--------------------------------------------------华丽的分割线-------------- -----------------------------------------------------------------------------------------------------

在这里先感谢一下@苍茫大地NV 的提问,提的问题非常好!???

他的问题是:

现在给一个场景 ul > li > div > p,div占满li,p占满div,还是给ul绑定时间,需要判断点击的是不是li(假设li里面的结构是不固定的),那么e.target就可能是p,也有可能是div,这种情况你会怎么处理呢?

那我们现在就再现一下他给的场景

  <ul id="test">
        <li>
            <p>11111111111</p>
        </li>
        <li>
            <div>
                22222222
            </div>
        </li>
        <li>
            <span>3333333333</span>
        </li>
        <li>4444444</li>
    </ul>

如上列表,有4个li,里面的内容各不相同,点击li,event对象肯定是当前点击的对象,怎么指定到li上,下面我直接给解决方案:

  var oUl = document.getElementById('test');
    oUl.addEventListener('click',function(ev){
        var target = ev.target;
        while(target !== oUl ){
            if(target.tagName.toLowerCase() == 'li'){
                console.log('li click~');
                break;
            }
            target = target.parentNode;
        }
    })

核心代码是while循环部分,实际上就是一个递归调用,你也可以写成一个函数,用递归的方法来调用,同时用到冒泡的原理,从里往外冒泡,知道currentTarget为止,当当前的target是li的时候,就可以执行对应的事件了,然后终止循环,恩,没毛病!

这里看不到效果,大家可以复制过去运行一下!

--------------------------------------------------------------------华丽的分割线----------------------------------------------------------------

总结:

那什么样的事件可以用事件委托,什么样的事件不可以用呢?

适合用事件委托的事件:click,mousedown,mouseup,keydown,keyup,keypress。

值得注意的是,mouseover和mouseout虽然也有事件冒泡,但是处理它们的时候需要特别的注意,因为需要经常计算它们的位置,处理起来不太容易。

不适合的就有很多了,举个例子,mousemove,每次都要计算它的位置,非常不好把控,在不如说focus,blur之类的,本身就没用冒泡的特性,自然就不能用事件委托了。

Node.js

RESTful API

单线程

Node可以在不新增额外线程的情况下,依然可以对任务进行并发处理 —— Node.js是单线程的。它通过事件循环(event loop)来实现并发操作,对此,我们应该要充分利用这一点 —— 尽可能的避免阻塞操作,取而代之,多使用非阻塞操作。

非阻塞IO

V8虚拟机

事件驱

AMD,Common.js

首先,JavaScript是一个强大的脚本(函数式+面向对象)语言,它有很多快速高效的解释器,然而,它并没有一个用于更广泛应用程序的标准库。

CommonJS是个规范,这个规范中定义了许多API,用于普通应用程序(主要指非浏览器的应用)使用的API,从而填补了这个空白。它的终极目标是提供一个类似Python,Ruby和Java标准库。这样的话,开发者可以使用CommonJS API编写应用程序,然后这些应用可以运行在不同的JavaScript解释器和不同的主机环境中。

NodeJS就是CommonJS这个规范的实现者。

CommonJS其中就有一个Modules规范,这个Modules规范设计之初是为了server端设计的,它是一个同步的模式,这种模式并不适合浏览器端,所以AMD规范诞生了,它最大的特点就是可以异步的方式加载模块。

RequrieJS其实就是AMD现在用的最广泛,最流行的实现,其中,Require.js主要提供define和require两个方法来进行模块化编程,前者用来定义模块,后者用来调用模块。

VUE

vue的异步更新队列

当vue检测到数据变化时,不会马上去渲染dom,而是创建一个队列,将变化载入队列中,等待事件执行结束,即下次事件循环开始时,将队列里的事情取出执行。(其实也就是和js异步里的事件轮询(event loop)差不多,宏任务和微任务)。所以要获取dom时,要使用$nextTick()保证在dom渲染出来后再进行获取

网络基础

1.OSI,TCP/IP,五层协议的体系结构,以及各层协议

答:
OSI分层 (7层):物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。
TCP/IP分层(4层):网络接口层、 网际层、运输层、 应用层。
五层协议 (5层):物理层、数据链路层、网络层、运输层、 应用层。
每一层的协议如下:
物理层:RJ45、CLOCK、IEEE802.3 (中继器,集线器)
数据链路:PPP、FR、HDLC、VLAN、MAC (网桥,交换机)
网络层:IP、ICMP、ARP、RARP、OSPF、IPX、RIP、IGRP、 (路由器)
传输层:TCP、UDP、SPX
会话层:NFS、SQL、NETBIOS、RPC
表示层:JPEG、MPEG、ASII
应用层:FTP、DNS、Telnet、SMTP、HTTP、WWW、NFS
每一层的作用如下:
物理层:通过媒介传输比特,确定机械及电气规范(比特Bit)
数据链路层:将比特组装成帧和点到点的传递(帧Frame)
网络层:负责数据包从源到宿的传递和网际互连(包PackeT)
传输层:提供端到端的可靠报文传递和错误恢复(段Segment)
会话层:建立、管理和终止会话(会话协议数据单元SPDU)
表示层:对数据进行翻译、加密和压缩(表示协议数据单元PPDU)
应用层:允许访问OSI环境的手段(应用协议数据单元APDU)

OSI是Open System Interconnection的缩写,意为开放式系统互联。国际标准化组织(ISO)制定了OSI模型,该模型定义了不同计算机互联的标准,是设计和描述计算机网络通信的基本框架。OSI模型把网络通信的工作分为7层,分别是物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。
Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。TCP/IP 定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。通俗而言:TCP负责发现传输的问题,一有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地。而IP是给因特网的每一台联网设备规定一个地址。

2.IP地址的分类

答:
A类地址:以0开头, 第一个字节范围:1~127(1.0.0.0 - 127.255.255.255);
B类地址:以10开头, 第一个字节范围:128~191(128.0.0.0 - 191.255.255.255);
C类地址:以110开头, 第一个字节范围:192~223(192.0.0.0 - 223.255.255.255);
D类地址:以1110开头,第一个字节范围:224~239(224.0.0.0 - 239.255.255.255);(作为多播使用)
E类地址:保留
通过这张图可以很容易记住划分的范围,主要通过最开始的几个二进制位是0还是1,来进行区分。IP划分

其中A、B、C是基本类,D、E类作为多播和保留使用。

以下是留用的内部私有地址:
A类 10.0.0.0–10.255.255.255
B类 172.16.0.0–172.31.255.255
C类 192.168.0.0–192.168.255.255

IP地址与子网掩码相与得到网络号:
ip : 192.168.2.110
&
Submask : 255.255.255.0
网络号 :192.168.2 .0
注:主机号,全为0的是网络号(例如:192.168.2.0),主机号全为1的为广播地址(192.168.2.255)

IP地址
我们都已经知道,Internet是由几千万台计算机互相连接而成的。而我们要确认网络上的每一台计算机,靠的就是能唯一标识该计算机的网络地址,这个地址就叫做IP(Internet Protocol的简写)地址,即用Internet协议语言表示的地址。
在Internet里,IP地址是一个32位的二进制地址,为了便于记忆,将它们分为4组,每组8位,由小数点分开,用四个字节来表示,而且,用点分开的每个字节的数值范围是0~255,如202.116.0.1,这种书写方法叫做点数表示法。

3.ARP是地址解析协议,简单语言解释一下工作原理。

答:1:首先,每个主机都会在自己的ARP缓冲区中建立一个ARP列表,以表示IP地址和MAC地址之间的对应关系。
2:当源主机要发送数据时,首先检查ARP列表中是否有对应IP地址的目的主机的MAC地址,如果有,则直接发送数据,如果没有,就向本网段的所有主机发送ARP数据包,该数据包包括的内容有:源主机 IP地址,源主机MAC地址,目的主机的IP 地址。
3:当本网络的所有主机收到该ARP数据包时,首先检查数据包中的IP地址是否是自己的IP地址,如果不是,则忽略该数据包,如果是,则首先从数据包中取出源主机的IP和MAC地址写入到ARP列表中,如果已经存在,则覆盖,然后将自己的MAC地址写入ARP响应包中,告诉源主机自己是它想要找的MAC地址。
4:源主机收到ARP响应包后。将目的主机的IP和MAC地址写入ARP列表,并利用此信息发送数据。如果源主机一直没有收到ARP响应数据包,表示ARP查询失败。
广播发送ARP请求,单播发送ARP响应。

地址解析协议,即ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个TCP/IP协议。主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机ARP缓存中并保留一定时间,下次请求时直接查询ARP缓存以节约资源。地址解析协议是建立在网络中各个主机互相信任的基础上的,网络上的主机可以自主发送ARP应答消息,其他主机收到应答报文时不会检测该报文的真实性就会将其记入本机ARP缓存;由此攻击者就可以向某一主机发送伪ARP应答报文,使其发送的信息无法到达预期的主机或到达错误的主机,这就构成了一个ARP欺骗。ARP命令可用于查询本机ARP缓存中IP地址和MAC地址的对应关系、添加或删除静态对应关系等。相关协议有RARP、代理ARP。NDP用于在IPv6中代替地址解析协议。

MAC(Media Access Control或者Medium Access Control)地址,意译为媒体访问控制,或称为物理地址、硬件地址,用来定义网络设备的位置。在OSI模型中,第三层网络层负责 IP地址,第二层数据链路层则负责 MAC地址。因此一个主机会有一个MAC地址,而每个网络位置会有一个专属于它的IP地址。 MAC地址是网卡决定的,是固定的。

4.各种协议的介绍

答:ICMP协议: 因特网控制报文协议。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。
TFTP协议: 是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。
HTTP协议: 超文本传输协议,是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。
NAT协议:网络地址转换属接入广域网(WAN)技术,是一种将私有(保留)地址转化为合法IP地址的转换技术,
DHCP协议:动态主机配置协议,是一种让系统得以连接到网络上,并获取所需要的配置参数手段,使用UDP协议工作。具体用途:给内部网络或网络服务供应商自动分配IP地址,给用户或者内部网络管理员作为对所有计算机作中央管理的手段。

ICMP是(Internet Control Message Protocol)Internet控制报文协议。它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。
TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。端口号为69。
超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。
NAT(Network Address Translation,网络地址转换)是1994年提出的。当在专用网内部的一些主机本来已经分配到了本地IP地址(即仅在本专用网内使用的专用地址),但现在又想和因特网上的主机通信(并不需要加密)时,可使用NAT方法。
DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)是一个局域网的网络协议,使用UDP协议工作, 主要有两个用途:给内部网络或网络服务供应商自动分配IP地址,给用户或者内部网络管理员作为对所有计算机作中央管理的手段,在RFC 2131中有详细的描述。DHCP有3个端口,其中UDP67和UDP68为正常的DHCP服务端口,分别作为DHCP Server和DHCP Client的服务端口;546号端口用于DHCPv6 Client,而不用于DHCPv4,是为DHCP failover服务,这是需要特别开启的服务,DHCP failover是用来做“双机热备”的。

5.描述RARP协议

答:RARP是逆地址解析协议,作用是完成硬件地址到IP地址的映射,主要用于无盘工作站,因为给无盘工作站配置的IP地址不能保存。工作流程:在网络中配置一台RARP服务器,里面保存着IP地址和MAC地址的映射关系,当无盘工作站启动后,就封装一个RARP数据包,里面有其MAC地址,然后广播到网络上去,当服务器收到请求包后,就查找对应的MAC地址的IP地址装入响应报文中发回给请求者。因为需要广播请求报文,因此RARP只能用于具有广播能力的网络。

反向地址转换协议(RARP:Reverse Address Resolution Protocol) 反向地址转换协议(RARP)允许局域网的物理机器从网关服务器的 ARP 表或者缓存上请求其 IP 地址。网络管理员在局域网网关路由器里创建一个表以映射物理地址(MAC)和与其对应的 IP 地址。当设置一台新的机器时,其 RARP 客户机程序需要向路由器上的 RARP 服务器请求相应的 IP 地址。假设在路由表中已经设置了一个记录,RARP 服务器将会返回 IP 地址给机器,此机器就会存储起来以便日后使用。 RARP 可以使用于以太网、光纤分布式数据接口及令牌环 LAN

6.TCP三次握手和四次挥手的全过程

答:

三次握手:
第一次握手:客户端发送syn包(syn=x)到服务器,并进入SYN_SEND状态,等待服务器确认;
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。
握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。
四次挥手
与建立连接的“三次握手”类似,断开一个TCP连接则需要“四次握手”。
第一次挥手:主动关闭方发送一个FIN,用来关闭主动方到被动关闭方的数据传送,也就是主动关闭方告诉被动关闭方:我已经不 会再给你发数据了(当然,在fin包之前发送出去的数据,如果没有收到对应的ack确认报文,主动关闭方依然会重发这些数据),但是,此时主动关闭方还可 以接受数据。
第二次挥手:被动关闭方收到FIN包后,发送一个ACK给对方,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号)。
第三次挥手:被动关闭方发送一个FIN,用来关闭被动关闭方到主动关闭方的数据传送,也就是告诉主动关闭方,我的数据也发送完了,不会再给你发数据了。
第四次挥手:主动关闭方收到FIN后,发送一个ACK给被动关闭方,确认序号为收到序号+1,至此,完成四次挥手。

关于TCP的三次握手四次挥手

拓展资料:https://juejin.im/post/5ccd0dfc6fb9a0324a08bb73

SYN:握手建立信号

ACK:应答同意信号

FIN:挥手信号(断开连接信号)

seq:包的序列号用于分割发送时判断怎么合并

ack:确认号,发送包的序列号

tip:SYN攻击

SYN攻击就是在客户端发送SYN信号给服务器端建立连接,但是还未收到服务器端的答复时,被黑客伪造请求发送随机IP的SYN请求给服务器,造成服务器的请求队列爆满,使正常的SYN信号无法送达,从而使服务器崩溃瘫痪的攻击。

当出现大量的半连接状态时,且源IP地址是随机的,基本可以判断收到了SYN攻击

解决办法:一类是通过防火墙、路由器等过滤网关防护,另一类是通过加固TCP/IP协议栈防范.但必须清楚的是,SYN攻击不能完全被阻止,我们所做的是尽可能的减轻SYN攻击的危害,除非将TCP协议重新设计。

常见http请求头

HTTP2.0

了解:https://juejin.im/post/5a4dfb2ef265da43305ee2d0

7.在浏览器中输入www.baidu.com后执行的全部过程

答:1、客户端浏览器通过DNS解析到www.baidu.com 的IP地址220.181.27.48,通过这个IP地址找到客户端到服务器的路径。客户端浏览器发起一个HTTP会话到220.181.27.48,然后通过TCP进行封装数据包,输入到网络层。
2、在客户端的传输层,把HTTP会话请求分成报文段,添加源和目的端口,如服务器使用80端口监听客户端的请求,客户端由系统随机选择一个端口如5000,与服务器进行交换,服务器把相应的请求返回给客户端的5000端口。然后使用IP层的IP地址查找目的端。
3、客户端的网络层不用关心应用层或者传输层的东西,主要做的是通过查找路由表确定如何到达服务器,期间可能经过多个路由器,这些都是由路由器来完成的工作,我不作过多的描述,无非就是通过查找路由表决定通过那个路径到达服务器。
4、客户端的链路层,包通过链路层发送到路由器,通过邻居协议查找给定IP地址的MAC地址,然后发送ARP请求查找目的地址,如果得到回应后就可以使用ARP的请求应答交换的IP数据包现在就可以传输了,然后发送IP数据包到达服务器的地址。

8.TCP和UDP的区别?

答:TCP提供面向连接的、可靠的数据流传输,而UDP提供的是非面向连接的、不可靠的数据流传输。
TCP传输单位称为TCP报文段,UDP传输单位称为用户数据报。
TCP注重数据安全性,UDP数据传输快,因为不需要连接等待,少了许多操作,但是其安全性却一般。
TCP对应的协议和UDP对应的协议
TCP对应的协议:
(1) FTP:定义了文件传输协议,使用21端口。
(2) Telnet:一种用于远程登陆的端口,使用23端口,用户可以以自己的身份远程连接到计算机上,可提供基于DOS模式下的通信服务。
(3) SMTP:邮件传送协议,用于发送邮件。服务器开放的是25号端口。
(4) POP3:它是和SMTP对应,POP3用于接收邮件。POP3协议所用的是110端口。
(5)HTTP:是从Web服务器传输超文本到本地浏览器的传送协议。
UDP对应的协议:
(1) DNS:用于域名解析服务,将域名地址转换为IP地址。DNS用的是53号端口。
(2) SNMP:简单网络管理协议,使用161号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。
(3) TFTP(Trival File Transfer Protocal),简单文件传输协议,该协议在熟知端口69上使用UDP服务。

9.DNS域名系统,简单描述其工作原理。

答:当DNS客户机需要在程序中使用名称时,它会查询DNS服务器来解析该名称。客户机发送的每条查询信息包括三条信息:包括:指定的DNS域名,指定的查询类型,DNS域名的指定类别。基于UDP服务,端口53. 该应用一般不直接为用户使用,而是为其他应用服务,如HTTP,SMTP等在其中需要完成主机名到IP地址的转换。

DNS(Domain Name System,域名系统),万维网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。通过域名,最终得到该域名对应的IP地址的过程叫做域名解析(或主机名解析)。DNS协议运行在UDP协议之上,使用端口号53。在RFC文档中RFC 2181对DNS有规范说明,RFC 2136对DNS的动态更新进行说明,RFC 2308对DNS查询的反向缓存进行说明。

10.TCP的三次握手过程?为什么会采用三次握手,若采用二次握手可以吗?

答:建立连接的过程是利用客户服务器模式,假设主机A为客户端,主机B为服务器端。
(1)TCP的三次握手过程:主机A向B发送连接请求;主机B对收到的主机A的报文段进行确认;主机A再次对主机B的确认进行确认。
(2)采用三次握手是为了防止失效的连接请求报文段突然又传送到主机B,因而产生错误。失效的连接请求报文段是指:主机A发出的连接请求没有收到主机B的确认,于是经过一段时间后,主机A又重新向主机B发送连接请求,且建立成功,顺序完成数据传输。考虑这样一种特殊情况,主机A第一次发送的连接请求并没有丢失,而是因为网络节点导致延迟达到主机B,主机B以为是主机A又发起的新连接,于是主机B同意连接,并向主机A发回确认,但是此时主机A根本不会理会,主机B就一直在等待主机A发送数据,导致主机B的资源浪费。
(3)采用两次握手不行,原因就是上面说的失效的连接请求的特殊情况。

11.了解交换机、路由器、网关的概念,并知道各自的用途

答:1)交换机
在计算机网络系统中,交换机是针对共享工作模式的弱点而推出的。交换机拥有一条高带宽的背部总线和内部交换矩阵。交换机的所有的端口都挂接在这条背 部总线上,当控制电路收到数据包以后,处理端口会查找内存中的地址对照表以确定目的MAC(网卡的硬件地址)的NIC(网卡)挂接在哪个端口上,通过内部 交换矩阵迅速将数据包传送到目的端口。目的MAC若不存在,交换机才广播到所有的端口,接收端口回应后交换机会“学习”新的地址,并把它添加入内部地址表 中。
交换机工作于OSI参考模型的第二层,即数据链路层。交换机内部的CPU会在每个端口成功连接时,通过ARP协议学习它的MAC地址,保存成一张 ARP表。在今后的通讯中,发往该MAC地址的数据包将仅送往其对应的端口,而不是所有的端口。因此,交换机可用于划分数据链路层广播,即冲突域;但它不 能划分网络层广播,即广播域。
交换机被广泛应用于二层网络交换,俗称“二层交换机”。
交换机的种类有:二层交换机、三层交换机、四层交换机、七层交换机分别工作在OSI七层模型中的第二层、第三层、第四层盒第七层,并因此而得名。
2)路由器
路由器(Router)是一种计算机网络设备,提供了路由与转送两种重要机制,可以决定数据包从来源端到目的端所经过 的路由路径(host到host之间的传输路径),这个过程称为路由;将路由器输入端的数据包移送至适当的路由器输出端(在路由器内部进行),这称为转 送。路由工作在OSI模型的第三层——即网络层,例如网际协议。
路由器的一个作用是连通不同的网络,另一个作用是选择信息传送的线路。 路由器与交换器的差别,路由器是属于OSI第三层的产品,交换器是OSI第二层的产品(这里特指二层交换机)。
3)网关
网关(Gateway),网关顾名思义就是连接两个网络的设备,区别于路由器(由于历史的原因,许多有关TCP/IP 的文献曾经把网络层使用的路由器(Router)称为网关,在今天很多局域网采用都是路由来接入网络,因此现在通常指的网关就是路由器的IP),经常在家 庭中或者小型企业网络中使用,用于连接局域网和Internet。 网关也经常指把一种协议转成另一种协议的设备,比如语音网关。
在传统TCP/IP术语中,网络设备只分成两种,一种为网关(gateway),另一种为主机(host)。网关能在网络间转递数据包,但主机不能 转送数据包。在主机(又称终端系统,end system)中,数据包需经过TCP/IP四层协议处理,但是在网关(又称中介系 统,intermediate system)只需要到达网际层(Internet layer),决定路径之后就可以转送。在当时,网关 (gateway)与路由器(router)还没有区别。
在现代网络术语中,网关(gateway)与路由器(router)的定义不同。网关(gateway)能在不同协议间移动数据,而路由器(router)是在不同网络间移动数据,相当于传统所说的IP网关(IP gateway)。
网关是连接两个网络的设备,对于语音网关来说,他可以连接PSTN网络和以太网,这就相当于VOIP,把不同电话中的模拟信号通过网关而转换成数字信号,而且加入协议再去传输。在到了接收端的时候再通过网关还原成模拟的电话信号,最后才能在电话机上听到。

对于以太网中的网关只能转发三层以上数据包,这一点和路由是一样的。而不同的是网关中并没有路由表,他只能按照预先设定的不同网段来进行转发。网关最重要的一点就是端口映射,子网内用户在外网看来只是外网的IP地址对应着不同的端口,这样看来就会保护子网内的用户。

计算机基础

缓存相关(非常重要)

cache替换策略

FIFO算法 :先进先出算法

(好!)LRU算法 :最近最久未使用算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值