Internet是在一个通信网络中连接的计算机的大规模集合,通过装置连接起来,相互之间可以通信。
根据端到端的设计原则,IP只为主机提供一种无连接、不可靠的、尽力而为的数据包传输服务。
阶段 | 描述 |
---|---|
HTTP1.0 | 非持续连接,2个RTT时间,使用TCP链接 |
HTTP1.1 | 支持持久连接,在相同TCP上通讯;支持流水线,可以不等反馈发送很多信息 |
HTTP2.0 | 支持HTTP1.1,在数据如何封装成帧上有区别,降低了request传输次数,对其多路传输 |
HTTP3.0 | 和HTTP2完全不同,使用UDP协议,通过重传保证效率 |
// PPT
c s s → c s s 2 → c s s 2.1 → c s s 3 css \rightarrow css2 \rightarrow css2.1 \rightarrow css3 css→css2→css2.1→css3
用于指定外部样式表。width:20%/auto
、px/em
tag & @import
style
标签提供的可以写在body中、head中或外部文件中
<body>
<script>
document.write("This is a heading
");
document.write("This is a paragraph.
");
script>
body>
<head>
<script>
function myFunction(){
document.getElementById("demo").innerHTML="My First JavaScript Function";
}
script>
head>
<script src="url" type="text/javascript">
! script commands and comments
script>
use strict;
的目的是指代码在严格条件下执行。.callee
和.caller
this
指向全局对象.caller
和.arguments
获取函数调用的堆栈protected
、static
和interface
<head>
<script>
function changetext(id){
id.innerHTML="谢谢!";
}
script>
head>
<body>
<h1 onclick="changetext(this)">请点击该文本h1>
body>
<div onmouseover="mOver(this)" onmouseout="mOut(this)">把鼠标移到上面div>
<script>
function mOver(obj){
obj.innerHTML="谢谢"
}
function mOut(obj){
obj.innerHTML="把鼠标移到上面"
}
script>
$().trigger("advanced_search_load_complete");
$().bind("advanced_search_load_complete", function(){ ... });
function myClass() { //此处相当于构造函数 }
,这里 myClass就是一个类。其实可以把它看成类的构造函数。至于非构造函数的部分,以后会详细描述。var obj1 = new myClass();
,JavaScript提供了一个方法可以获得对象实例。即new操作符。其实JavaScript中,类和函数是同一个概念,当用new操作一个函数时就返回一个对象。对象名.属性名; 对象名.方法名;
对象名["属性名"]; 对象名["方法名"];
for item in obj
prototype
属性,指向另一个对象,这个对象的所有属性和方法会被构造函数继承。// 每个实例对象的type和eat都是一样的,每次生成一些示例其实是重复的内容,多占用内存
functlon Cat(name,color){
this.name = nane;
this.color = color;
this.type = "猫科动物";
this.eat = function(){alert("吃老鼠");
};
// 使用prototype属性
function Cat(name ,color){
this.name = name;
this.color = color ;
)
Cat.prototype.type = "猫科动物";
Cat.prototype.eat = function(){alert("吃老鼠");
// 例子1:声明方式1
$("div").each(function(index){alert(this)})
// 例子1:声明方式2:f1就是匿名函数
var f1 = function(index){alert(this)};
$("div").each(f1);
// 例子2:声明方式1
var double = function(x){return 2 * x;}
// 例子2:声明方式2
(function(x, y){
alert(x + y);
})(2, 3);
js匿名函数更多参考
// 代码块内声明
function getValue(condition) {
if (condition) {
let value = "blue";
return value;
} else {
// value 在此处不可用
return null;
}
// value 在此处不可用
}
// 禁止重复声明
var count = 30;
let count = 40; // Uncaught SyntaxError: Identifier 'count' has already been declared
// 不会抛出错误
var count = 30;
var condition = 1;
if (condition) {
let count = 40;
// 其他代码
}
// 循环中的绑定块作用域的妙用,如果使用var声明i的话,就会导致i成为全局边浪
for (let i = 0; i < btns.length; i++) {
btns[i].onclick = function () {
console.log('第' + (i + 1) + '个')
}
}
// 对比例1
var x = 10
function fn() {
console.log(x)
}
function show(f) {
var x = 20
(function() {
f() //10,而不是20
})()
}
show(fn)
// 对比例2
var a = 10
function fn() {
var b = 20
function bar() {
console.log(a + b) //30
}
return bar
}
var x = fn(),
b = 200
x() //bar()
function f1(){
var n=999;
// 匿名函数,本质也是闭包
nAdd=function(){n+=1;}
// f2闭包函数
function f2(){
alert(n);
}
return f2;
}
// f1被赋值被全局变量,于是也就不会在调用结束后被垃圾回收机制回收。
var result=f1();
result(); // 999
nAdd();
result(); // 1000
// 例子1
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
// 函数声明时,向外查找function没有找到,则再往外直接到全局
return this.name;
};
}
};
alert(object.getNameFunc()());// "The Window"
// 例子2
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
// 向上查找找到this指本object
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()());
// 例子3
var name="XL";
var person={
name:"xl",
showName:function(){
console.log(this.name);
}
}
person.showName();// xl
//这里是person对象调用showName方法,很显然this关键字是指向person对象的,所以会输出name
var showNameA=person.showName;
showNameA(); //输出 XL
//这里将person.showName方法赋给showNameA变量,此时showNameA变量相当于window对象的一个属性,因此showNameA()执行的时候相当于window.showNameA(),即window对象调用showNameA这个方法,所以this关键字指向window
// this和调用时有关,而不是创建时
var btn = document.getElementById("btn");
btn.onclick = function(){
alert(this.id);
}
// 取消绑定
btn.onclick = null;
var btn = document.getElementById("btn");
var hander = function(){
}
// 参数:事件处理属性名称、处理函数、是否再捕获时执行事件处理函数
addEventListener("click",handler,false/true);
removeEventListener("click",handler,false/true);
addEventListener
添加的事件处理程序,只能通过removeEventListener
来删除。
)在捕获阶段不会接收到事件,这意味着在捕获阶段,事件的传递从document到
再到
最后到后就停止了;然后就是处于目标阶段,而在事件处理中目标阶段被看做冒泡阶段的一部分。
- 当一个 DOM 事件触发时,它不是在触发的对象上只触发一次的,而是经历上述的三个阶段,即开始从文档的根节点流向目标对象, 然后在目标对向上被触发,之后再回溯到文档的根节点。
2.4.3. 观察者模式
- 察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。它主要用于实现分布式事件处理系统。
/*通知所有注册的观察者对象*/
public void nodifyObservers(String newState){
for(Observer observer:list){
observer.update(newState);
}
}
2.5. Ajax
2.5.1. RIA Rich Internet Applications 丰富互联网应用程序
- 是一种具有近似于传统桌面应用软件系统功能和特性的网络应用系统。
- RIA系统最大的特点是将大部分处理任务都从用户界面端移植到客户端,仅保留一些必要数据与服务器端进行信息交互。
- RIA系统的特性:
- 运行于浏览器中,不需要额外安装支持软件
- 在本地运行时,受安全沙箱全程保护。
- 优点
- 无需安装
- 容易升级
- 可以通过Internet/intranet轻易获得
- 更加丰富的用户界面
- 响应速度更快的用户界面
- 客户端/服务端 负载平衡
- 异步通讯
- 网络效率
- 缺点
- 搜索引擎不可见
- 专有(与开放标准相反)
- 完整性丧失(RIA通常无法与HTML很好地融合在一起)
- 软件开发的复杂性(什么东西要被缓存或不缓存再客户端计算机中?)
- RIA体系结构打破了网页范例
- 受限于安全沙箱
- 依赖于脚本支持
- 客户端运行速度受限
2.5.2. 同步、异步通信
2.5.2.1. 同步
- 同步请求/响应通信模型中,总是浏览器(与Web服务器、应用服务器或Web应用程序相对)发起请求(通过Web用户)。接着,Web服务器、应用服务器或Web应用程序响应进入的请求。在处理同步请求/响应对期间,用户不能继续使用浏览器。
- 基本上所有新数据都需要刷新页面
2.5.2.2. 异步
- Web用户在当前异步请求被处理时还可以继续使用浏览器。一旦异步请求处理完成,异步响应就被通信(从Web服务器、应用服务器或Web应用程序)回客户机页面。典型情况下,在这个过程中,调用对Web用户没有影响;他们不需要等候响应。
- 交换数据但是不需要刷新页面
2.5.3. Ajax请求
- 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
- 传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
2.5.4. Ajax优缺点
- 优点
- 更好的交互性和响应能力,使用起来更让人愉快。
- 由于部分渲染,减少了与Web服务器的连接。
- 因为只加载需要更新页面的数据,而不是刷新整个页面,所以可以节省带宽,减少网络流量。
- 缺点
- 返回和刷新按钮变得无用。
- 为此页面添加书签将变得无用。
- 需要在Web浏览器上启用JavaScript。
- 网络延迟可能会破坏可用性。
- 通过AJAX加载的数据不会被任何主要的搜索引擎索引。因此,使SEO不友好。违背URL和资源定位的初衷
2.5.5. 安全相关,SOP,跨域
2.5.5.1. 安全相关
XSS威胁
- 跨站脚本(Cross site scripting,通常简称为XSS)是一种网站应用程序的安 全漏洞攻击,是代码注入的一种。 它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。指攻击者在网页中嵌入客户端脚本(例如JavaScript),当用户浏览此网页时,脚本就会在用户的浏览器上执行,从而达到攻击者的目的.这类攻击通常包含了HTML以及用户端脚本语言。
- AJAX无法从本地存储的网页上运行,只能在存储在Web服务器上的网页上运行
2.5.5.2. SOP
- 同源政策:限制浏览器可以获取的资源,只能从同源网站获取内容(除了资源文件) 同源政策规定,AJAX请求只能发给同源的网址,否则就报错。"同源政策"越来越严格。目前,如果非同源,共有三种行为受到限制。
- Cookie、LocalStorage 和 IndexDB 无法读取。
- DOM无法获得。
- AJAX请求不能发送。
2.5.5.3. 跨域问题
- 当协议、子域名、主域名、端口号中任意一个不同时,都算作不同域
- 实现跨域的方法
- CORS:服务器设置HTTP响应头中Access-Control-Allow-Origin值,解除跨域限制。
- nginx:反向代理
- Docker
2.5.6. 数据格式
2.5.6.1. JSON
- 由Douglas Crockford形式化和推广,它是一种轻量级的、易于简化的数据格式,使用JavaScript对象和数组文本语法编写。
2.5.6.2. JSON-P JSON with Padding
- 带填充的JSON
- 当使用动态脚本标记插入时,JSON数据被视为另一个JavaScript文件,并作为本机代码执行。为了实现这一点,数据必须包装在回调函数中。
- 由于JavaScript被当作本机数据来处理,因此它以本机JavaScript的速度被解析。
- 避免使用与性能无关的JSON-P有一个原因:由于JSON-P必须是可执行的JavaScript,因此任何人都可以调用它,并使用动态脚本标记插入将其包含在任何网站中。
- 不要在JSON-P中对任何敏感数据进行编码,因为您无法确保它保持私有,即使使用随机url或cookie。
3. 服务器端
3.1. Node.js 重要
- Node.js是基于Chrome的JavaScript运行时构建的平台,可轻松构建快速,可扩展的网络应用程序。
- Node.js使用事件驱动的非阻塞I/O模型,使其轻巧高效,非常适合跨分布式设备运行的数据密集型实时应用程序。
3.1.1. 特点,应用场景
3.1.1.1. 特点
- MVC分离
- 现代语法和闭包使得更强大的扩展库成为可能。
- 很多语言可以交叉编译在JS中
- Node.js通过优化可以通过Web服务传递数据,并且仅传递数据,保证交付行为良好。
- 支持JSON
- 回调机制出色,避免使用线程:单线程上异步处理,而不是传统多线程
- 适用于请求大量请求但是每个请求不需要大量计算能力的应用程序,并发问题很少。
3.1.1.2. 应用场景
- 网站
- IM即时聊天
- API
- HTTP代理
- 前端构建工具(脚手架)
- 操作系统(NodeOS)
- 跨平台打包工具
- 小程序
- 命令行工具
- 反向代理
3.1.2. 基本原理
- 异步I/O
- 事件循环驱动
- 不惜一切代价避免同步代码,因为阻塞了时间循环,意味着很多的回调。
- 网上解释
- Node.js:单线程,异步I/O,事件驱动
- 应用程序的请求过程可以分为俩个部分:CPU运算和I/O读写
- CPU计算速度通常远高于磁盘读写速度,这就导致CPU运算已经完成,但是不得不等待磁盘I/O任务完成之后再继续接下来的业务。
- 所以I/O才是应用程序的瓶颈所在,在I/O密集型业务中,假设请求需要100ms来完成,其中99ms花在I/O上。
- 如果需要优化应用程序,让他能同时处理更多的请求,我们会采用多线程,同时开启100个、1000个线程来提高我们请求处理,当然这也是一种可观的方案。但是由于一个CPU核心在一个时刻只能做一件事情,操作系统只能通过将CPU切分为时间片的方法,让线程可以较为均匀的使用CPU资源。
- 操作系统在内核切换线程的同时也要切换线程的上下文,当线程数量过多时,时间将会被消耗在上下文切换中。所以在大并发时,多线程结构还是无法做到强大的伸缩性。那么是否可以另辟蹊径呢?!
- 我们先来看看单线程,《深入浅出Node》一书提到"单线程的最大好处,是不用像多线程编程那样处处在意状态的同步问题,这里没有死锁的存在,也没有线程上下文切换所带来的性能上的开销",那么一个线程一次只能处理一个请求岂不是无稽之谈,先让我们看张图:
- Node.js的单线程并不是真正的单线程,只是开启了单个线程进行业务处理(cpu的运算),同时开启了其他线程专门处理I/O。当一个指令到达主线程,主线程发现有I/O之后,直接把这个事件传给I/O线程,不会等待I/O结束后,再去处理下面的业务,而是拿到一个状态后立即往下走,这就是"单线程"、“异步I/O”。
- I/O操作完之后呢?Node.js的I/O 处理完之后会有一个回调事件,这个事件会放在一个事件处理队列里头,在进程启动时node会创建一个类似于While(true)的循环,它的每一次轮询都会去查看是否有事件需要处理,是否有事件关联的回调函数需要处理,如果有就处理,然后加入下一个轮询,如果没有就退进程,这就是所谓的"事件驱动"。这也从Node的角度解释了什么是"事件驱动"。在node.js中,事件主要来源于网络请求,文件I/O等,根据事件的不同对观察者进行了分类,有文件I/O观察者,网络I/O观察者。事件驱动是一个典型的生产者/消费者模型,请求到达观察者那里,事件循环从观察者进行消费,主线程就可以马不停蹄的只关注业务不用再去进行I/O等待。
4. 优化 重要
4.1. 基准测试/性能分析
- 通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量和可对比的测试
- 延迟(传播、传输、处理、排队)和带宽
- Web性能要点
- 延迟和带宽对Web性能的影响
- 传输协议(TCP)对HTTP的限制
- HTTP协议自身的功能和缺陷
- Web应用的发展趋势及性能需求
- 浏览器局限性和优化思路
- 性能监控指标
- FP:首次绘制,页面第一次绘制的时间点:只要出现视觉变化,无论什么。
- FCP:首次内容绘制,完成对DOM中的一部分内容渲染的时间点:首次绘制来自DOM的内容。
- FMP:首次有意义绘制,页面关键元素的渲染时间,由开发者自行定义。
- 首屏时间:应用渲染完整个屏幕的时间。
- 用户可交互时间:DOMReady时间
- 总下载时间:页面所有资源加载完成的时间,一般统计window.onload时间,也可以是异步渲染全部完成的时间。
- 页面所有元素夹杂时间
- 第一个字节加载时间
- 页面渲染时间:瀑布流中两个指标Start Render和msFirstPaint
- Start Render:通过捕获页面加载的视频,实验室测量。
- msFirstPaint:是浏览器本身报告的测量。
- DOM元素数量
- 自定义指标
- 相关工具
4.2. 基本原理
- 浏览器核心优化策略
- 基于文档的优化(做法是优先获取资源,提前解析)
- 推测性优化(学习用户的导航模式,尝试预测用户的下一次操作,预先解析DNS、预先连接可能的目标)
- web性能优化两个准则
- 消除或减少不必要的网络延迟
- 将需要传输的数据压缩至最少
4.3. 优化思路,技术,方法
4.3.1. 优化思路
- 减少域名查找
- 重用TCP连接
- 最少次数的Http重定向
- 使用内容分发网络
- 避免不必要的资源请求
- 在客户端贮藏部分资源
- 资源传输前先压缩
- 避免不必要的请求字节
- 使请求和响应过程并行
4.3.2. 具体的优化方法
- CSS:CSS放置在HTML顶部,减少CSS文件,避免绝对CSS。
- Image:合适的图片大小,而不是浏览器调整
- js:将js放在html的底部,尽量用外部js
- 服务器优化:减少域名查找,数据压缩
- html:标准兼容、去除空白符、结构尽量简单、做到浏览器和移动端的兼容
- 针对HTTP1.x的优化
- 利用http管道
- 域名分片
- 打包资源以减少HTTP请求
- 父文档中嵌入小资源
- HTTP2优化
- 少发数据,减少请求,减少传输数据量和不必要网络延迟,调整资源供给
- 每个来源一个链接(多个链接会抵消新协议中首部压缩和请求优先级的作用),去掉不必要资源打包(不利于缓存,单个文件比较大),利用服务器推送(充分使用缓存的机制)
7. 正则表达式
正则表达式