JavaScript
JavaScript第一步
https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/First_steps
1.脚本调用——async和defer
<script async src="jquery.js"></script>
<script asynnc src="index.js"></script>
async 异步,可以解决调用顺序问题,告知浏览器在遇到<script>
元素时不要中断后续HTML内容的加载,而是直接下载然后运行。
注意点:
1.只能用于外部脚本;
2.直接下载然后运行,导致脚本的运行次序无法控制;
3.使用情况,当脚本无需等待页面解析,且无依赖独立运行时;
<script defer src="jquery.js"></script>
<script defer src="index.js"></script>
defer 脚本将按照在页面中出现的顺序加载和运行
使用情况
当脚本需要等待页面解析,且依赖于其他脚本,调用这些脚本时应使用defer
,将关联的脚本按所需顺序置于HTML中。
2.字符串 String
-
查找字符串 indexOf()
str = 'my piana'; str.indexOf('piana'); //返回3 str.indexOf('your'); //返回-1
-
提取字符串
slice(start[,end]) 注: 可为负索引,不修改原String和Array
substring(start[,end])
substr(start[,length]) 注: 可为负索引str.slice(0,3); str.slice(2);
-
转换大小写
toUpperCase()
toLowerCase() -
替换
replace() 注: 只替换首个匹配;可使用正则表达式匹配字符
3.字符串与数组之间的转换
字符串 -> 数组 split()
数组 -> 字符串 join() toString()
let myData = 'a,b,c,d,e,f';
let myArray = myData.split(','); //["a","b", "c", "d", "e", "f"]
let myyNewString = myArray.join('*'); //"a\*b\*c\*d\*e\*f"
let str = ['dog','cat'];
str.toString(); //"dog,cat"
实例:
- number-guessing-game-start.html
- index.html
style.css
raw-text.txt
main.js
0527
创建JavaScript代码块
https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Building_blocks
- if-else switch
- 循环:for while
- 基本函数
- 事件
- 事件冒泡与事件捕获
1. 条件——switch
实例:theme.html
2. break和continue
break 立即退出循环
continue 结束当前循环,转而执行下一个循环
3. 事件
-
事件处理器属性
例如:
btn.oncilick = function(){};
onfocus、onblur、onchange、onmouseover、onmouseoutconst btn = document.querySelector('button'); btn.onclick = function() { const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; }
-
行内事件处理器 (勿用)
-
addEventListener()和removeEventListener()
参数1:事件
参数2:执行的操作
随机背景颜色转换代码:const btn = document.querySelector('button'); function bgChange() { const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; document.body.style.backgroundColor = rndCol; } btn.addEventListener('click', bgChange);
其他事件
在处理函数内部,会有一个固定指定名称的参数。例如event
, evt
, e
。被称为事件对象
function bgChange(e) {
const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')';
e.target.style.backgroundColor = rndCol;
console.log(e);
}
btn.addEventListener('click', bgChange);
4. 事件冒泡及事件捕获
捕获阶段:
- 浏览器检查元素的最外层祖先<html>,是否在捕获阶段中注册了一个onclick事件处理程序,如果是,则运行它。
- 然后,它移动到<html>中单击元素的下一个祖先元素,并执行相同的操作,然后是单击元素再下一个祖先元素,依此类推,直到到达实际点击的元素。
冒泡阶段: (默认情况下)
- 浏览器检查实际点击的元素是否在冒泡阶段中注册了一个onclick事件处理程序,如果是,则运行它
- 然后它移动到下一个直接的祖先元素,并做同样的事情,然后是下一个,等等,直到它到达<html>元素。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dquUFXWC-1646193593383)(img/bubble.png)]
Array详解
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array
1. 遍历数组 forEach()
var fruits = ['Apple', 'Banana'];
fruits.forEach((item, index, Array) => {
console.log(index, item);
})
2. 数组添加、删除项 push() pop() unshift() shift()
push() pop()
数组末尾添加,返回数组长度
unshift() shift()
数组起始处添加,返回变动的元素
let myArr = ['cat','dog'];
myArr.push('dollar'); //['cat','dog','dollar']
let nowLength = myArr.push('blue'); //4
let removeItem = myArr.shift(); //'cat'
3. 删除、替换现有元素或原地添加新的元素 splice()
语法:array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
start
起始位置
deleteCount
删除的元素个数
item
添加的元素
返回值:删除——输出删除的元素组成的数组;否则返回空数组
const months = ['Jan', 'March', 'April', 'June'];
// 添加
months.splice(1, 0, 'Feb'); // inserts at index 1
console.log(months); // expected output: Array ["Jan", "Feb", "March", "April", "June"]
// 删除
months.splice(4, 1); // replaces 1 element at index 4
console.log(months); // expected output: Array ["Jan", "Feb", "March", "April"]
// 替换
months.splice(1,1,'2');
console.log(months); // expected output: Array ["Jan", "2", "March", "April"]
4. 分割、深拷贝数组 slice()
语法:arr.slice([begin[, end]])
返回值:一个含有被提取元素的新数组
let newFruits = fruits.slice();
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
animals.slice(2);// expected output: Array ["camel", "duck", "elephant"]
animals.slice(2, 4);// expected output: Array ["camel", "duck"]
animals.slice(1, 5);// expected output: Array ["bison", "camel", "duck", "elephant"]
5. 查找第一个满足测试函数的元素 find()
返回元素的值 find()
返回元素的索引 findIndex()
const array1 = [12, 7, 99, 34];
let found = array1.find(element => element>10);
console.log(found); // 12
let foundIndex = array1.findIndex(element => element<10);
console.log(foundIndex); // 1
6. 创建新数组 map()
返回值为一个原数组每个元素执行回调函数的结果组成的新数组
const array2 = [1, 3, 4, 6, 9];
let doubleArray = array2.map(element => element*2);
console.log(doubleArray); // [1, 9, 36, 81]
7. 过滤数组成员 filter()
返回值:满足条件的新数组
let array1 = [1, 3, 5, 6];
array1.filter((elem) => {
return (elem > 3)
}); // [5,6]
回顾答疑
1. 问: String的slice方法和Array中的slice方法有设区别?
- String.slice(start,end) 返回起止下标之间的字符;
Array.slice(start,end) 是对数组深拷贝的过程,常用的除了分割数组,就是数组的深拷贝;
2. 问:深拷贝与浅拷贝的差别
-
浅拷贝
-
基本数据类型(number, string, boolean, null, undefined):
名值存储在栈内存中,值引用,实际上内存引用,指向了某一处内存的值let a = 1; let b = a;
栈内存 name val a 1 复制 b=a ,栈内会新开辟一块内存
此时修改a的值,此时不会改变b的值栈内存 name val a 1 b 1 -
引用数据类型(Object, Array, Date):
名存在栈内存中,值存在堆内存中,栈内存会提供一个引用的地址指向堆内存中的值。数组指向了同一处内存的值,如果 该处内存值发生了变化,浅拷贝的赋值变量值也会改变。let myArr = [0, 1, 2, 3, 4]; let newArr = myArr; a[0] = 1;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UUaoZv7Y-1646193593387)(img/shallow_copy1.png)]
当newArr = myArr进行拷贝时,复制myArr的引用地址
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2RleTq8e-1646193593390)(img/shallow_copy2.png)]
修改数组myArr的值,newArr也会改变
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YBq8OMOV-1646193593395)(img/shallow_copy3.png)]
-
-
深拷贝
则是指从原数组内存处取出值,重新赋值到一块新的内存中,原数组值的修改不会影响到新的数组。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KnjOKaG9-1646193593398)(img/deep_copy.png)]
slice concat深拷贝过程let a=[1,2,3,4], b=a.slice(); a[0]=2; console.log(a,b);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bjfI7ebo-1646193593400)(img/Array_slice1.png)]
let a=[0,1,[2,3],4], b=a.slice(); a[0]=2; a[2][0] = 100; console.log(a,b);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nIgR2oCM-1646193593402)(img/Array_slice2.png)]
b对象的一级属性确实是深拷贝的过程,拥有独立的内存。但是二级属性还是公用了地址,所以还是浅拷贝的过程。
综上:slice concat是不完全的深拷贝
3. 问:全部替换应该怎么做
-
使用正则表达式 /g 全局搜索匹配
let str = 'my test replaceAll my test.' let newStr = str.replace(/my/g,'your'); console.log(str); console.log(newStr);
4. const arr3 = arr1.concat(arr2)修改 arr1之后arr3会有影响吗?修改arr2呢?
- cancat返回一个新数组,修改原数组,arr3不变;深拷贝过程
5. 在对数组遍历过程中 在forEach遍历中,break/return会有什么影响吗?
- 在foreach中是不能通过break continue return来终止循环,会报错
6. 性能调优:怎么在ES5范畴内终止数组遍历?ES6上有没有其他的方法呢?
Object详解
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object
1. 箭头函数
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions
-
基础语法
// 传递多个参数 (param1, param2, …, paramN) => { statements } (param1, param2, …, paramN) => expression; //相当于:(param1, param2, …, paramN) =>{ return expression; } // 当只有一个参数时,圆括号是可选的: (singleParam) => { statements } singleParam => { statements } // 没有参数的函数应该写成一对圆括号。 () => { statements } // 声明函数 用const更命名,方便调用 const setTheme = ()=>{} setTheme(); // 函数调用和执行
-
箭头函数有几个使用注意点。
- (1)箭头函数没有自己的this对象。function/this.js
- (2)不可以当作构造函数,也就是说,不可以对箭头函数使用new命令,否则会抛出一个错误。
- (3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
- (4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
- (5)由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向。
ES6
1. let 和 const
let
-
暂时性死区(temporal dead zone,简称 TDZ):在代码块内,使用let命令声明变量之前,该变量都是不可用的。
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
注: typeof会因为TDZ出现错误typeof x; // ReferenceError let x; typeof y; //undefined
- 不存在变量提升。`var`声明变量可以在声明之前使用,值为**undefined**;`let`声明变量可以在声明之前使用会**报错**
- 不允许在系统作用域内,重复声明同一个变量
**`const`**
- 声明一个只读变量,一旦声明,常量值不能改变,且一旦声明,必须立即初始化。只声明不赋值会报错
- *其他性质同 let*
### 2. 变量的解构赋值
___
**解构:** ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
- Array
解构不成功,变量的值=undefined
```js
let [a, b, c] = [1, 2, 3]; // 可以从数组中提取值,按照对应位置,对变量赋值。
-
解构赋值允许指定默认值。默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
let [x, y = 'b'] = ['a']; // x='a', y='b' let [x, y = 'b'] = ['a', undefined]; // x='a', y='b' let [x = 1, y = x] = []; // x=1; y=1 let [x = 1, y = x] = [2]; // x=2; y=2 let [x = 1, y = x] = [1, 2]; // x=1; y=2
-
Object
属性基本相同
Object与Array解构的区别:
数组的元素是按次序排列的,变量的取值由它的位置决定;
而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。let { bar, foo } = { foo: 'aaa', bar: 'bbb' }; foo // "aaa" bar // "bbb" let { baz } = { foo: 'aaa', bar: 'bbb' }; baz // undefined // 变量名与属性名不一致时: let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; baz // "aaa"
注意点:
-
如果要将一个已经声明的变量用于解构赋值,必须非常写法。
let x; ({x} = {x: 1});
-
解构赋值允许等号左边的模式之中,不放置任何变量名。因此,可以写出非常古怪的赋值表达式。
-
由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
let arr = [1, 2, 3]; let {0 : first, [arr.length - 1] : last} = arr; first // 1 last // 3
-
-
String
字符串解构赋值时,字符串被转换成了一个类似数组的对象。const [a, b] = 'hi'; a // "h" b // "i" // length属性解构赋值 let {length : len} = 'hello'; len // 5
-
Number boolean
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。
由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。let {toString: s} = 123; s === Number.prototype.toString // true
-
function 函数
写法不同,结果也会不同function move({x, y} = { x: 0, y: 0 }) { return [x, y]; } move({x: 3, y: 8}); // [3, 8] move({x: 3}); // [3, undefined] move({}); // [undefined, undefined] move(); // [0, 0]
用途:
- 交换变量值
- 从函数返回多个值
- 函数参数的定义
- 提取JSON数据
- 遍历
Map
解构 - 函数参数的默认值
- 输入模块的指定方法
4. 字符串的扩展
-
字符的Unicode表示法
-
采用\uxxxx形式表示一个字符,其中xxxx表示字符的 Unicode 码点。
-
字符范围:
\u0000
~\uFFFF
-
超出范围的字符,使用两个双字节表示,故此码点需要放入大括号内
"\uD842\uDFB7" // "𠮷" "\u20BB7" // " 7" 等价于 \u20BB+7 "\u{20BB7}" // "𠮷" 正确结果
注意点:
字符的六种表示方法'\z' === 'z' // true '\172' === 'z' // true '\x7A' === 'z' // true '\u007A' === 'z' // true '\u{7A}' === 'z' // true
-
-
字符串的遍历器接口
- 使用for…of遍历字符串。
- 可识别大于0xFFFF的码点
-
模板字符串
插入变量时,变量名、变量表达式、调用函数需写在${}
中$('#result').append(` There are <b>${basket.count}</b> items in your basket, <em>${basket.onSale}</em> are on sale! `);
5. 字符串的新增方法
- 实例方法 includes() startsWith() endsWith()
includes()
:返回布尔值,表示是否找到了参数字符串。
startsWith()
:返回布尔值,表示参数字符串是否在原字符串的头部。
endsWith()
:返回布尔值,表示参数字符串是否在原字符串的尾部。 - repeat()
返回一个新字符串,表示将原字符串重复n次,小数则取整 - padStart() padEnd()
padStart(maxLength, addStr)
:头部补全,二参默认空格
padEnd(maxLength, addStr)
:尾部补全,同上 - trim() trimStart() trimEnd()
消除空格,返回新字符串
7.数值的扩展
- 进制
二进制:0b
、oB
十六进制:0o
、0O
转十进制:Number(0b1111)
- Number.isFinite() Number.isNaN()
Number.isFinite()
:检查数值有限,即非Infinity - Number.parseInt(), Number.parseFloat()
- Number.isInteger()
- Math对象扩展
- Math.trunc方法用于去除一个数的小数部分,返回整数部分。
- Math.sign方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。
- Math.expm1(x) 返回 ex - 1,即Math.exp(x) - 1。
- Math.log1p(x) 方法返回1 + x的自然对数,即Math.log(1 + x)。如果x小于-1,返回NaN
- Math.log10(x) 返回以 10 为底的x的对数。如果x小于 0,则返回 NaN。
- (**) 指数运算符,例如 2**3
8.函数扩展
- 函数参数
- 参数变量是默认声明的,所以不能用let或const再次声明。
- 参数默认值可以与解构赋值的默认值,结合起来使用
- rest参数
(形式为…变量名),用于获取函数的多余参数,rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。 - 严格模式
- 规定只要函数参数使用了默认值、解构赋值、或者扩展运算符,那么函数内部就不能显式设定为严格模式,否则会报错。
- 函数内部的严格模式,同时适用于函数体和函数参数。
- 尾调用,尾递归
指某个函数的最后一步是调用另一个函数(或自身)。
9.函数的扩展
- 扩展运算符
- 扩展运算符(spread)是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
- 主要用于函数调用。
- 替代函数的apply方法。
- 应用:
- 复制数组同
cancat
——深拷贝 - 合并数组
- 与解构赋值结合
- 将字符串转为真正的数组
- 任何定义了遍历器(Iterator)接口的对象(参阅 Iterator 一章),都可以用扩展运算符转为真正的数组。
- Map 和 Set 结构,Generator 函数
- 复制数组同
10. 对象的扩展
- 属性的可枚举性
描述对象的enumerable属性,称为“可枚举性”,如果该属性为false,就表示某些操作会忽略当前属性。Object.getOwnPropertyDescriptor
方法可以获取该属性的描述对象- 有四个操作会忽略enumerable为false的属性。
- for…in循环:只遍历对象自身的和继承的可枚举的属性。
- Object.keys():返回对象自身的所有可枚举的属性的键名。
- JSON.stringify():只串行化对象自身的可枚举的属性。
- Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。
- 遍历
- (1)for…in
for…in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。 - (2)Object.keys(obj)
Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。 - (3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。 - (4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。 - (5)Reflect.ownKeys(obj)
Reflect.ownKeys返回一个数组,包含对象自身的(不含继承的)所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
- (1)for…in
- super属性,指向当前对象的原型对象。
11. 对象的新增方法
-
Object.is() 同值相等
-
Object.assign() 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
- 语法:
Object.assign(target, source1, source2);
- 注意点
- 浅拷贝
- 同名属性替换
- 可处理数组
- 应用
- 为对象增加属性
- 为对象增加方法
- 克隆对象
- 合并多个对象
- 为属性指定默认值
- 语法:
-
Object.getOwnPropertyDescriptors() 方法,返回指定对象所有自身属性(非继承属性)的描述对象。
-
__proto__ 属性(前后各两个下划线),用来读取或设置当前对象的原型对象(prototype)。
-
Object.setPrototypeOf 方法的作用与__proto__相同,用来设置一个对象的原型对象(prototype),返回参数对象本身。
-
Object.setPrototypeOf 方法与Object.setPrototypeOf 方法配套,用于读取一个对象的原型对象
16. Promise 对象
-
含义
Promise 是异步编程的一种解决方案。所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。- 特点
- (1)对象的状态不受外界影响
- (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果
- 特点
-
基本用法
const promise = new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); } else { reject(error); } });
-
Promise.prototype.then()
- then方法是定义在原型对象Promise.prototype上的。它的作用是为 Promise 实例添加状态改变时的回调函数。
- 返回值:一个新的Promise实例
-
Promise.prototype.catch() 方法是
.then(null, rejection)
或.then(undefined, rejection)
的别名,用于指定发生错误时的回调函数。 -
Promise.prototype.finally() 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。
-
Promise.all(),Promise.race() 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
-
Promise.allSettled(),Promise.any() 方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例
21. Class的基本语法
类的方法内部如果含有this,它默认指向类的实例。
22.Class的继承
Flex布局:实例篇
https://www.ruanyifeng.com/blog/2015/07/flex-examples.html
基准线:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WeAyfv1Y-1646193593407)(img/flex1.png)]
1. 骰子布局
实例:touzi.html + touzi.css
2. 网格布局
- 基本网格布局——平均分布
- 百分比布局,其余网格平均分配剩余空间
- 圣杯布局 shengbei.html
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hvaPH1vG-1646193593410)(img/flex2_shengbei.png)] - 输入框布局
- 悬挂式布局
- 固定的底栏
- 流式布局
知识点回顾
https://juejin.cn/post/6844903922084085773
1. 在浏览器输入URL回车之后发生了什么( HTTP(端口80)
请求)?
-
URL解析
- 地址解析:判断输入的URL是否合法
- HSTS 会强制可会断使用HTTPS(端口403)访问页面
- 检查缓存
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZZZtNFKi-1646193593416)(img/check_storage.png)]
-
DNS查询
- 基本步骤
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JLQnbyhw-1646193593418)(img/main_step.png)]- 检查浏览器缓存,无则调用系统库函数进行查询
- OS的DNS缓存:检查域名是否在本地的Hosts文件里,无则向DNS服务器发送查询请求
- 路由器缓存
- ISP DNS缓存
- 根域名服务器查询
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ruVhwQVX-1646193593423)(img/URL_check.png)]
- 基本步骤
-
TCP连接
TCP/IP四层结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S7ZsWH3j-1646193593427)(img/TCP_IP.png)]- 应用层:发送 HTTP 请求
根据得到服务器的 IP 地址,浏览器开始构造一个 HTTP 报文,其中包括:- 请求报头(Request Header):请求方法、目标地址、遵循的协议等等
- 请求主体(其他参数)
注意点:
浏览器只能发送GET
、POST
方法,打开网页使用的是GET
方法
- 传输层:TCP 传输报文
传输层会发起一条到达服务器的 TCP 连接,为了方便传输,会对数据进行分割(以报文段
为单位),并标记编号, 方便服务器接受时能够准确地还原报文信息。
在建立连接前,会先进行 TCP 三次握手,结束时四次挥手。 - 网络层:IP协议查询Mac地址
将数据段打包,并加入源及目标的IP地址,并且负责寻找传 输路线。
判断目标地址是否与当前地址处于同一网络中,是的话直接 根据 Mac 地址发送,否则使用路由表查找下一跳地址,以 及使用 ARP 协议查询它的 Mac 地址。 - 链路层:以太网协议
以太网协议
根据以太网协议将数据分为以“帧
”为单位的数据包,每一帧分为两个部分:
标头
:数据包的发送者、接受者、数据类型
数据
:数据包具体内容
Mac 地址
以太网规定了连入网络的所有设备都必须具备“网卡”接口,数据包都是从一块网卡传递到另一块网卡,网卡的地址就 是 Mac 地址。每一个 Mac 地址都是独一无二的,具备了 一对一的能力。
广播
发送数据的方法很原始,直接把数据通过 ARP 协议,向本网络的所有机器发送,接收方根据标头信息与自身 Mac 地址比较,一致就接受,否则丢弃。
注意:接收方回应是单播。 - 服务器接受请求
接受过程就是把以上步骤逆转过来,参见上图。
- 应用层:发送 HTTP 请求
-
服务器处理请求
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bZaBcw39-1646193593431)(img/server.png)] -
接受响应
- 查看 Response header,根据不同状态码做不同的事(比如上面提到的重定向)。
- 如果响应资源进行了压缩(比如 gzip),还需要进行解压。
- 对响应资源做缓存。
- 根据响应资源里的 MIME 类型去解析响应内容(比如 HTML、Image各有不同的解析方式)。
-
熏染页面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NBBidHrk-1646193593433)(img/ll.png)] -
JavaScript编译执行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6ykWpN1c-1646193593437)(img/JS.png)]
DOM
https://www.w3school.com.cn/htmldom/index.asp
1. DOM方法
-
获取元素
- getElementById(id) - 获取带有指定 id 的节点(元素)
- getElementsByTagName() - 返回包含带有指定标签名称的所有元素的节点列表(集合/节点数组)。
- getElementsByClassName() - 返回包含带有指定类名的所有元素的节点列表。
-
节点的增删改查
- appendChild(node) - 插入新的子节点(元素)作为父元素的最后一个元素
- insertBefore() - 作为父元素的第一个元素进行添加
- removeChild(node) - 删除子节点(元素)
- replaceChild() - 替换子节点。
- createAttribute()- 创建属性节点。
- createElement()- 创建元素节点。
- createTextNode()- 创建文本节点。
- getAttribute() - 返回指定的属性值。
2. DOM属性
- innerHTML - 节点(元素)的文本值
- nodeName - 规定节点的名称(只读)
- nodeValue - 规定节点的值
- nodeType - 返回节点的类型(只读)
- parentNode - 节点(元素)的父节点
- childNodes - 节点(元素)的子节点
- attributes - 节点(元素)的属性节点
3. DOM修改
- 改变 HTML 内容
- 改变 CSS 样式
- 改变 HTML 属性
- 创建新的 HTML 元素
- 删除已有的 HTML 元素
- 改变事件(处理程序)
4. DOM事件
- 当用户点击鼠标时
onclick
onmousedown
onmousesetup
- 当网页已加载时
onload
onunload
- 当图片已加载时 ``
- 当鼠标移动到元素上时
onmouseover
onmouseout
- 当输入字段被改变时
onchange
- 当 HTML 表单被提交时
- 当用户触发按键时