前端基础知识

前端基础知识整理

1.typeof 返回的数据类型

typeof 返回的数据类型包括 undefined、 string、number、boolean、symbol、object、function、bigInt 类型

2.检查数组的方式

  1. isArray()方法
  2. Object.prototype.toString.call()
  3. instanceof Array
  4. constructor
  5. typeof()

3.js 中的 call、apply、bind 方法的区别

js 中的 call apply bind 都是用来改变方法上下文(context),就是可以使函数可以被其他对象调用。

let hxy = {
  name: 'hxy',
  age: 22,
  say(x, y) {
    console.log(this.name + ':' + this.age + x + y);
  },
};
let yyw = {
  name: 'yyw',
  age: 18,
};
hxy.say(1, 2); // 实际上是调用的this.say() this指的是hxy
hxy.say.apply(yyw, [1, 2]); // 调用apply后this改变指向,this指向yyw,相当于yyw.say()
hxy.say.call(yyw, 1, 2);
hxy.say.bind(yyw, 1, 2)();

运行结果:

hxy: 2212;
yyw: 1812;
yyw: 1812;
yyw: 1812;

4.闭包

简单来说,闭包就是指能读取其他函数内部变量的函数
闭包的简单应用:

function f1() {
  var n = 99;
  function f2() {
    return n;
  }
  return f2;
}
var result = f1();
console.log(result());
//返回n = 99;

运行结果返回了 f1 中的变量 n

闭包有三个特性:

1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会被垃圾回收机制回收

使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。

5.js 事件机制

DOM 事件流分为三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段
事件捕获(event capturing):通俗的理解就是,当鼠标点击或者触发 dom 事件时,浏览器会从根节点开始由外到内进行事件传播,即点击了子元素,如果父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件。
事件冒泡(dubbed bubbling):与事件捕获恰恰相反,事件冒泡顺序是由内到外进行事件传播,直到根节点。
dom 标准事件流的处理顺序为先捕获、再冒泡

6.常用的处理字符串方法

.charAt(index):获取字符串索引对应的具体字符,参数 index 介于 0~length-1 之间。

.indexOf(value,index):返回字符串第一次出现指定值的索引,没有找到指定值就返回-1。
字符串、数组都适用。
value:必需,规定需检索的字符串值。可选的整数参数。
index:规定在字符串中开始检索的位置。它的合法取值是 0 到 stringObject.length - 1。如省略该参数,则将从字符串的首字符开始检索。

.substr(start,length):返回从指定位置开始到指定字符数的字符。

img

.substring(indexStart,indexEnd):返回一个字符串从开始索引到结束索引之间的新字符串。

img

.split() 字符串:使用指定的分隔符字符串将一个String对象分割成子字符串数组,以一个指定的分割字串来决定每个拆分的位置。

.replace() 字符串:方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串

toLowerCase():会将调用该方法的字符串值转为小写形式,并返回。

toUpperCase():方法将调用该方法的字符串转为大写形式并返回(如果调用该方法的值不是字符串类型会被强制转换)。

7.window 对象 和 document 对象

window 对象:代表浏览器中一个打开的窗口
document 对象:代表整个 HTML 文档,可以用来访问页面中的所有元素,且每个载入浏览器的 HTML 文档都是 document 对象

document 对象是 window 对象的一部分,可以有 window. document 来访问

html 部分

1.说说你对语义化的理解?

1,去掉或者丢失样式的时候能够让页面呈现出清晰的结构
2,有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重;
3,方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意译的方式来渲染网页;
4,便于团队开发和维护,语义化更具可读性,是网页的重要动向,遵循W3C标准的团队都遵循这个标准,可以减少差异化。

2.Doctype 作用? 严格模式与混杂模式如何区分?它们有何意义?

(1)<!DOCTYPE> 声明位于文档中的最前面,处于 <html> 标签之前。告知浏览器以何种模式来渲染文档。

(2)、严格模式的排版和 JS 运作模式是  以该浏览器支持的最高标准运行。

(3)、在混杂模式中,页面以宽松的向后兼容的方式显示。模拟老式浏览器的行为以防止站点无法工作。

(4)、DOCTYPE不存在或格式不正确会导致文档以混杂模式呈现。

3.你知道多少种 Doctype 文档类型?

 该标签可声明三种 DTD 类型,分别表示严格版本、过渡版本以及基于框架的 HTML 文档。
 HTML 4.01 规定了三种文档类型:Strict、Transitional 以及 Frameset。
 XHTML 1.0 规定了三种 XML 文档类型:Strict、Transitional 以及 Frameset。
Standards (标准)模式(也就是严格呈现模式)用于呈现遵循最新标准的网页,而 Quirks
 (包容)模式(也就是松散呈现模式或者兼容模式)用于呈现为传统浏览器而设计的网页。

4.DOM 操作——怎样添加、移除、移动、复制、创建和查找节点。

(1)创建新节点

      createDocumentFragment()    //创建一个DOM片段

      createElement()   //创建一个具体的元素

      createTextNode()   //创建一个文本节点

(2)添加、移除、替换、插入

      appendChild()

      removeChild()

      replaceChild()

      insertBefore() //在已有的子节点前插入一个新的子节点

(3)查找

      getElementsByTagName()    //通过标签名称

      getElementsByName()    //通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)

      getElementById()    //通过元素Id,唯一性

5.html5 有哪些新特性、移除了那些元素?如何处理 HTML5 新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?

* HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。

* 拖拽释放(Drag and drop) API
  语义化更好的内容标签(header,nav,footer,aside,article,section)
  音频、视频API(audio,video)
  画布(Canvas) API
  地理(Geolocation) API
  本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
  sessionStorage 的数据在浏览器关闭后自动删除

  表单控件,calendar、date、time、email、url、search
  新的技术webworker, websocket, Geolocation

* 移除的元素

纯表现的元素:basefont,big,center,font, s,strike,tt,u;

对可用性产生负面影响的元素:frame,frameset,noframes;

支持HTML5新标签:

* IE8/IE7/IE6支持通过document.createElement方法产生的标签,
  可以利用这一特性让这些浏览器支持HTML5新标签,

  浏览器支持新标签后,还需要添加标签默认的样式:

* 当然最好的方式是直接使用成熟的框架、使用最多的是html5shim框架
   <!--[if lt IE 9]>
   <script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script>
   <![endif]-->
如何区分:DOCTYPE声明新增的结构元素功能元素

6.documen.write 和 innerHTML 的区别

document.write只能重绘整个页面

innerHTML可以重绘页面的一部分

7.什么是 HTML5 以及和 HTML 的区别是什么

概念

HTML5 是 HTML 的新标准,其主要目标是无需任何额外的插件如 Flash、Sliverlight 等,就可以传输所有内容。他囊括了动画、视频、丰富的图形用户界面等。

区别

从语义结构上看:

  • HTML4.0:没有体现结构语义化的标签,通常都是是这样来命名的<div id="header"></div>,这样表示网站的头部。
  • HTML5:在语义上却有很大的优势。提供了一些新的标签,比如

8.行内元素有哪些?块级元素有哪些? 空(void)元素有那些?

  • 行内元素: a, span, img, input, select, strong;
  • 块级元素: div, ul, li, dl, dt, dd, h1-5, p等;
  • 空元素: <br>, <hr>, <img>, <link>, <meta>;

9.WebSocket 的实现和应用

什么是 webSocket?

WebSocket 是 HTML5 中的协议,支持持久连续,http 协议不支持持久性连接。

WebSocket 是什么样的协议,具体有什么优点。

WebSocket 是基于 Http 协议的,或者说借用了 Http 协议来完成一部分握手,在握手阶段与 Http 是相同的。

10.HTML 元素如何体现其嵌套关系

  • 块级元素可以包含行内元素
  • 块级元素不一定能包含块级元素
  • 行内元素一般不能包含块级元素(a 元素例外)

11.对 HTML5 有什么了解?

  • 良好的移动性,以移动设备为主;
  • 响应式设计,以适应自动变化的屏幕尺寸
  • 支持离线缓存技术,webStorage 本地缓存
  • 新增的地理位置等
  • 新增 webSocket/webwork 技术

CSS 部分

1.标准的 CSS 盒子模型及其和低版本的 IE 盒子模型的区别?

标准(W3C)盒子模型:width = 内容宽度(content) + border + padding + margin

低版本 IE 盒子模型: width = 内容宽度(content + border + padding)+ margin

2.display 有哪些值?他们的作用是什么?

  • none:使用后元素将不会显示
  • grid:定义一个容器属性为网格布局
  • flex:定义一个弹性布局
  • block:使用后元素将变为块级元素显示,元素前后带有换行符
  • inline:display 默认值。使用后原色变为行内元素显示,前后无换行符
  • list-item:使用后元素作为列表显示
  • table:使用后将作为块级表格显示(类似),前后带有换行符

    3.用 CSS 创建一个三角形

    <style>
      .content {
        width: 0;
        height: 0;
        border-top: 40px solid transparent;
        border-left: 40px solid transparent;
        border-right: 40px solid transparent;
        border-bottom: 40px solid #ff0000;
      }
    </style>
    
    <div class="content"></div>

    4.什么是响应式设计?响应式设计的基本原理是什么?

    响应式网站设计是一个网站能够兼容多个终端,而不是为每一个终端做一个特定的版本。

    关于原理:基本原理是通过媒体查询(@media)查询检测不同的设备屏幕尺寸做处理。

    关于兼容:页面头部必须有 meta 生命的 viewport

    5.浮动原理以及为什么会出现浮动和什么时候需要清除浮动?清除浮动的方式?

    非 IE 浏览器下,容器不设定高度且子元素浮动时,容器高度不能被内容撑开。此时,内容会溢出到容器外面而影响布局。此类现象被称为浮动(溢出)

    原理:

    • 浮动元素脱离文档流,不占据空间
    • 浮动元素碰到包含它的边框或其他浮动元素的边框停留。

    浮动会带来的问题:

    • 父级元素的高度将会无法被,会影响与父级元素同级的元素
    • 与浮动元素同级的非浮动元素(内联元素)会跟随其后
    • 若浮动的元素不是第一个元素,则该元素之前的元素也要浮动,否则会影响页面的显示结构。

    清除方式:

    • 父级盒子定义高度(height)
    • 最后一个浮动元素后面加一个 div 空标签,并且添加样式 clear:both
    • 包含浮动元素的父级标签添加样式 overflow 为 hidden/both

    6.::before 和:after 中双冒号和单冒号有什么区别?解释一下这 2 个伪元素的作用

    • 冒号用于 css3 伪类,双冒号用于 css3 伪元素
    • ::before 就是以一个子元素的存在,定义在元素主体内容之前的一个伪元素,并不存在于 dom 之中,只存在在页面之中。

    7.display,float,position 有什么关系?

    • 如果 displaynone,那么positionfloat都不起作用,元素不显示;
    • 如果position值为absolute或者fixed,元素绝对定位,float的计算值为nonedisplay根据下面的表格进行调整;
    • 如果float不是none,框是浮动的,display根据下表进行调整;
    • 其他情况下display的值为指定值 总结起来:绝对定位、浮动、根元素都需要调整 display

    8.什么是回流(重排)和重绘以及其区别?

    • 回流(重排)reflow:当 render tree 中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变时而需要重新构建;
    • 重绘(repaint):当 redner tree 中的一些元素需要更新属性,而这些属性只影响元素的外观,网格,而不会影响布局时,称其为重绘,例如颜色改变等。
    • 每个页面至少需要引发一次重排+重绘,而且重排(回流)一定会引发重绘。

    计算机网络知识

    1.浏览器内核

    浏览器主要分为两个部分:渲染引擎和 JS 引擎

    渲染引擎:主要负责获取页面内容和排班渲染页面

    JS 引擎:解析和执行 JS 来实现页面的动态效果,以及交互内容。

    2.TCP 三次握手和四次挥手

    为什么要进行三次握手:为了确认对方的发送和接受能力。

    三次握手

    三次握手主要流程:

    • 一开始双方处于 CLOSED 状态,然后服务端开始监听某个端口进入 LISTEN 状态
    • 然后客户端主动发起连接,发送 SYN,然后自己变为 SYN-SENT,seq=x
    • 服务端收到之后,返回 SYN seq=y 和 ACk ack=x+1(对于客户端发来的 SYN),自己变成 SYN-REVD
    • 之后客户端发送 ACK seq= x+ 1,ack= y + 1 给服务端,自己变成 EASTBLISHED 状态,服务端收到 ACK,也进入 ESTABLISHED

    为什么不是两次

    无法确认客户端的接收能力。

    四次挥手

    • 一开始都处于 ESTABLISH 状态,然后客户端发送 FIN 报文,带上 seq = p,状态变为 FIN-WAIT-1
    • 服务端收到之后,发送 ACK 确认,ack = p + 1,然后进入 CLOSE-WAIT 状态
    • 客户端收到之后进入 FIN-WAIT-2 状态
    • 过了一会等数据处理完,再次发送 FIN、ACK、seq = q ,ack = p +1,进入 LAST-ACK 阶段
    • 客户端收到 FIN 之后,客户端进入 TIME_WAIT(等待 2MSL),然后发送 ACK 给服务端 ack= 1+1
    • 服务端收到之后进入 CLOSED 状态

    3.浏览器输入 url 之后发生了什么

    1. 浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
    2. 建立 TCP 连接(三次握手);
    3. 浏览器发出读取文件(URL 中域名后面部分对应的文件)的 HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;
    4. 服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
    5. 释放 TCP 连接(四次挥手)
    6. 浏览器将该 html 文本导出并显示内容

    4.Cookie、sessionStorage、localStorage 区别

    共同点:都是保存在浏览器端,且同源的。

    区别:

    1. cookie 数据始终在同源的 http 请求中携带,即 cookie 在浏览器中和服务器间来回传递。sessionStorage 和 localStorage 不会自动把数据发给服务器,仅在本地保存。
    2. cookie 数据不能超过 4k(适合保存小数据)。sessionStorage 和 localStorage 容量较大。
    3. 数据有效期不同
      • sessionStorage:仅在当前浏览器窗口关闭前有效。
      • localStorage:始终有效,窗口或浏览器关闭也一直保存,需手动清除。
      • cookie 只在设置的 cookie 过期时间之前一直有效,即使窗口或浏览器关闭。
    4. 作用域不同。
      • sessionStorage 不在不同的浏览器窗口中共享。
      • localStorage 在所有同源窗口中都是共享的。
      • cookie 也是在所有同源窗口中都是共享的。
    5. 应用场景
      • localStorage:常用于长期登录(+判断用户是否已登录),适合长期保存在本地的数据。
      • sessionStorage:敏感账号一次性登录。
      • cookie 与服务器交互。

    5.原型和原型链

    创建了一个函数就会为其创建一个 prototype 属性,指向这个函数的原型对象,原型对象会自动获得 constructor 属性,指向 prototype 属性所在函数。

    当一个对象调用某个方法或者属性的时候,先在自身查找,如果找到就调用,如果没有就顺着proto到原型对象中查找,如果还没有就继续去原型的原型中查找,一直到 null,这样形成一条链叫做原型链。

    6.作用域和闭包

    作用域可理解为该上下文中声明的变量和声明的作用范围

    闭包属于一种特殊的作用域,称为静态作用域。它的定义可以理解为:父函数被销毁的情况下,返回出的子函数仍然可以继续访问到父级的变量对象,这样的函数称为闭包。

    • 闭包会产生一个很经典的问题:
      • 多个子函数的都是同时指向父级,是完全共享的。因此当父级的变量对象被修改时,所有子函数都受到影响。

    7.this 的指向问题

    口诀:箭头函数、new、bind、apply 和 call、欧比届点(obj.)、直接调用、不在函数里。

    1.箭头函数

    箭头函数 this 不会被改变

    1. 创建箭头函数时,就已经确定了它的 this 指向。
    2. 箭头韩式内的 this 指向外层的 this。

    2.new

    当使用 new 关键字调用函数时,函数中的 this 一定是 JS 创建的新对象

    3.bind

    bind 指 Function.prototype.bind()

    多次 bind 时只认第一次 bind 的值

    function func() {
      console.log(this);
    }
    func.bind(1).bind(2)(); //1

    箭头函数中 this 不会被修改

    func = () => {
      console.log(this);
    };
    func.bind(1)(); //window 口诀1优先

    4.apply 和 call

    apply()call()的第一个参数都是 this,区别在于通过 apply 调用时实参是放到数组中的,而通过 call 调用时实参是逗号分隔的。

    bind 函数中 this 不会被修改

    func = () => {
      //这里this指向取决于外层this,参考口诀7不在函数里
      console.log(this);
    };
    func.apply(1);

    5.欧比届点(obj.)

    function func() {
      console.log(this.x);
    }
    obj = { x: 1 };
    obj.func = func;
    obj.func(); //1

    6.直接调用

    在函数不满足前面的场景,被直接调用时,this 将指向全局对象。在浏览器环境中全局对象是 Window

    function func() {
      console.log(this);
    }
    func(); //window

    7.不在函数里

    不在函数中的场景,可分为浏览器的 <script /> 标签里,或 Node.js 的模块文件里。

    1. <script /> 标签里,this 指向 Window。
    2. 在 Node.js 的模块文件里,this 指向 Module 的默认导出对象,也就是 module.exports。

    9.数组去重

    1. 定义一个新数组,并存放原数组的第一个元素,然后将元素组一一和新数组的元素对比,若不同则存放在新数组中。
    2. 先将原数组排序,再与相邻的进行比较,如果不同则存入新数组。
    3. 利用对象属性存在的特性,如果没有该属性则存入新数组。
    Array.prototype.unique = function () {
      let arr = this,
        obj = {},
        result = [];
      for (let i = 0; i < arr.length; i++) {
        if (!obj[arr[i]]) {
          //如果能查找到,证明数组元素重复了
          obj[arr[i]] = 1;
          result.push(arr[i]);
        }
      }
      return result;
    };
    let a = [1, 2, 3, 1, 2, 3];
    let b = a.unique();
    console.log(b); //打印结果:(3)[1,2,3]
    1. 使用 es6 set,Set 数据结构,它类似于数组,其成员的值都是唯一的

      let arr = [1, 2, 3, 4, 3, 4, 5, 2, 6];
      console.log([...new Set(arr)]);
    2. 使用 filter 过滤函数去重

      let arr = [1, 2, 6, 4, 3, 4, 5, 2, 6];
      console.log(arr.filter((v, i, arr) => arr.indexOf(v) === i));

      10.防抖、节流

    防抖:触发高频函数事件后,n 秒内函数只能执行一次,如果在 n 秒内这个事件再次被触发的话,那么会重新计算时间。

    ​ 通常使用场景:用户输入,只需再输入完成后做一次输入校验即可。

    节流:指连续触发事件但是在 n 秒内只执行一次函数。节流会稀释函数的执行频率。

    ​ 通常使用场景:滚动条事件或者 resize 事件,通常每隔 100~500ms 执行一次即可。

    //防抖
    function debounce(func,wait){
    	let timeout;
    	return function(){
    	if(itmeout){
    	clearTimeout(timeout)
    	}
    	timeout = setTimeout(()=>{
    	func.apply(this,arguments)
    	},wait}
    	}
    }
    //节流
    function throttle(func,wait){
    	let timeout;
    	return function(){
    	if(!timeout){
    		timeout = setTimeout(()=>{
    		timeout = null;
    		func.apply(this, arguments)
    		},wait)
    	}
    	}
    }

    11.ES6 的新特性

    1. 声明 let / const
    2. 解构赋值
    3. class/extend:类声明与继承
    4. Set / Map:新的数据结构
    5. 箭头函数
    6. promise
    7. async/await
    8. 数组/对象的扩展

    12.跨域

    1.为什么会出现跨域问题

    同源策略限制 不同源会造成跨域。以下任意一种情况不同,都是不同源。

    2.什么情况才算做跨域

    非同源请求,均为跨域。名词解释:同源——如果两个页面拥有相同的协议(protocol),端口(port)和主机(host),那么这两个页面属于同一个源(origin)。

    3.为什么有跨域需求?

    场景——工程服务化后,不同职责的服务分散在不同的工程中,往往这些工程的域名是不同的,但一个需求可能需要对应多个服务

    4.如何实现跨域

    三种跨域方法

    • JSONP
    • CORS
    • postMessage

    1.JSONP 只能解决 get 跨域

    单纯地为了实现跨域请求而创造的一个 trick。

    原理:动态创建一个 script 标签。利用 script 标签的 src 属性不受同源策略限制。因为所有的 src 属性和 href 属性都不受同源策略限制。可以请求第三方服务器数据内容。

    步骤
    1. 去创建一个 script 标签

    2. script 的 src 属性设置接口地址

    3. 接口参数,必须要带一个自定义函数名,要不然后台无法返回数据

    4. 通过定义函数名器接受后台返回数据

      //去创建一个script标签
      var script = document.createElement('script');
      //script的src属性设置接口地址 并带一个callback回调函数名称
      script.src = 'http://127.0.0.1:8888/index.php?callback=jsonpCallback';
      //插入到页面
      document.head.appendChild(script);
      //通过定义函数名去接收后台返回数据
      function jsonpCallback(data) {
        //注意  jsonp返回的数据是json对象可以直接使用
        //ajax  取得数据是json字符串需要转换成json对象才可以使用。
      }

      2.CORS:跨域资源共享

    • 原理:服务器设置 Access-Control-Allow-OriginHTTP 响应头之后,浏览器将会允许跨域请求
    • 限制:浏览器需要支持 HTML5,可以支持 POST,PUT 等方法兼容 ie9 以上
    需要后台设置 Access-Control-Allow-Origin: * //允许所有域名访问,或者
    Access-Control-Allow-Origin: http://a.com //只允许所有域名访问

    3.设置 document.domain

    • 原理:相同主域名不同子域名下的页面,可以设置 document.domain 让他们同域
    • 限制:同域 document 提供的是页面间的互操作,需要载入 iframe 页面
    // URL http://a.com/foo
    var ifr = document.createElement('iframe');
    ifr.src = 'http://b.a.com/bar';
    ifr.onload = function(){
        var ifrdoc = ifr.contentDocument || ifr.contentWindow.document;
        ifrdoc.getElementsById("foo").innerHTML);
    };
    
    ifr.style.display = 'none';
    document.body.appendChild(ifr);
    

    4.用 Apache 做转发(逆向代理),让跨域变同域

    13.TCP/IP 分为几层?各层的作用是什么?

    1. 应用层 2.传输层 3.网络层 4.网络接口层
    • 1、应用层
      • TCP/IP 协议族在这一层面有着很多协议来支持不同的应用,许多大家所熟悉的基于 Internet 的应用的实现就离不开这些协议。如我们进行万维网(WWW)访问用到了 HTTP 协议、文件传输用 FTP 协议、电子邮件发送用 SMTP、域名的解析用 DNS 协议、远程登录用 Telnet 协议等等,都是属于 TCP/IP 应用层的;就用户而言,看到的是由一个个软件所构筑的大多为图形化的操作界面,而实际后台运行的便是上述协议。(FTP、SMTP、telnet、DNS、tftp)
    • 2、传输层
      • 这一层的的功能主要是提供应用程序间的通信,TCP/IP 协议族在这一层的协议有 TCP 和 UDP。(UDP)
    • 3、 网络层
      • 是 TCP/IP 协议族中非常关键的一层,主要定义了 IP 地址格式,从而能够使得不同应用类型的数据在 Internet 上通畅地传输,IP 协议就是一个网络层协议。(IP 数据包)
    • 4、网络接口层
      • 这是 TCP/IP 软件的最低层,负责接收 IP 数据包并通过网络发送之,或者从网络上接收物理帧,抽出 IP 数据报,交给 IP 层。(帧,网络接口协议)