1.关于基础css html js部分
1.1基本算法
1)快速排序
时间复杂度 nlogn
function quickSort(arr){if (arr.length<=1){return arr;}var pivotIndex = 0,pivort = arr.splice(pivortIndex, 1)[0];var left = [],right = [];for (var i = 1, length = arr.length; i < length; i++) {if (arr[i] < pivort) {left.push(arr[i]);}else if (arr[i] > = pivort) {right.push(arr[i]);}}return quickSort(left).concat([pivort], quickSort(right));
}
2) 二分查找算法
时间复杂度:logn(以2为底n的对数)
二分查找的基本思想是将n个元素分成大致相等的两部分,去a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果x<a[n/2],则只要在数组a的左半部分继续搜索x,如果x>a[n/2],则只要在数组a的右半部搜索x.时间复杂度无非就是while循环的次数!总共有n个元素,渐渐跟下去就是n,n/2,n/4,....n/2^k,其中k就是循环的次数由于你n/2^k取整后>=1即令n/2^k=1可得k=log2n,(是以2为底,n的对数)所以时间复杂度可以表示O()=O(logn)
function binarySearch (arr, value) {var low = 0,high = arr.length - 1,mid;while (low <= high) {mid = Math.floor((low + high)/2);if (arr[mid] == value) {return mid;}else if (arr[mid] < value) {low = mid +1;}else if (arr[mid] > value) {high = mid -1;}else {return -1;}}
}
3)单向链表反转
依次将第2---N个节点逐次插入到第一个节点后,最后将第一个节点挪到新表的结尾
例子为单向链表,头结点为空
时间复杂度:N
function reverse (list) {//空链表if (list.head.next == null) {return list;}
//非空链表var p = list.head.next,q;while (p.next !== null) {q = p.next;p.next = q.next;q.next = list.head.next;list.head.next = q;}return list;
}
4)查找单向链表的倒数第K个节点
function searchK (list, k) {var head = list.head;if (head == null || k == 0) {return null;}//第一个节点先向前走K-1步var firstNode = head;for (var i = 0; i < k-1; i++) {firstNode = firstNode.next;}//判断链表长度是否有K长if (i!== k-1) { return null;}//两个节点同时走var secondNode = head;while (firstNode.next !== null) {secondNode = secondNode.next;firstNode = firstNode.next;}return secondNode;
}
5)深度克隆
function clone (test) {if (Array.isArray(test)) {var arr = [];for (var i = 0, length = test.length; i < length; i++) {arr.push(clone(arr[i]));}}else if (typeOf test === "object") {var obj = {};for (var j in test) {obj[j] = clone(test[j]);}return obj;}else {return test;}
}
6)数组去重
例如去重['1',1,2,2,NaN,NaN,null,undefined]
尤其注意1,'1'
NaN
function _isNaN (value) {return typeof value === 'number' && isNaN(value);
}
function unique (arr) {var type = '',key = '',res = [],hash = {};for(var i= 0,len=arr.length;i<len;i++){if(_isNaN(arr[i])){if(!hash[arr[i]]){hash['NaN'] = true;res.push(arr[i]); }}else{type = typeof arr[i];key = type + arr[I];if(!hash[key]){hash[key] = true;res.push(arr[i]);}}}return res;
}
7)两个栈实现一个队列
https://segmentfault.com/a/11...
1.2 replace,match,search正则匹配是string的方法
str.replace(/ /g,'20%');
g表示全局匹配,不会匹配完第一个就不匹配了i忽略大小写m多行匹配
1.3 Rexg正则匹配test,exec
test,返回一个 Boolean 值,它指出在被查找的字符串中是否存在模式。
如果存在则返回 true,否则就返回 false。exec,用正则表达式模式在字符串中运行查找
var str=" 12 er 45 ;; ";var rexg=/ /;rexg.exec(str);Array[1]
0: " "
index: 0
input: " 12 er 45 ;; "
length: 1
__proto__: Array[0]
var str=" 12 er 45 ;; ";var rexg=/ /;rexg.exec(str);
[" "]0: " "index: 0input: " 12 er 45 ;; "length: 1__proto__: Array[0]var str=" 12 er 45 ;; ";str.match(/ /g,'20%');
[" ", " ", " ", " ", " "]var str=" 12 er 45 ;; ";str.replace(/ /,'20%');
"20%12 er 45 ;; "var str=" 12 er 45 ;; ";str.match(/ /,'20%');
[" "]var str=" 12 er 45 ;; ";str.search(/ /,'20%');
0var str=" 12 er 45 ;; ";str.search(/ /g,'20%');
0var str=" 12 er 45 ;; ";var rexg=/ /;rexg.test(str);
true
1.4 闭包
定义:
- 可以访问外部函数作用于中变量的函数
- 被内部函数引用的外部函数的变量保存在外部作用域中而不被回收
优缺点:
优点:
变量私有化
减少全局变量污染
可以让一个变量常驻内存
缺点:
内存泄漏
闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存
1.5 js数组
数组可以当栈用:
arr.unshift(val)进栈,依次向前插入arr.pop()出栈 取得数组最后一项,原数组改变减少最后一项实现了先进后出
数组当队列或者正常数组用:
arr.push(val),顺序添加
arr.shift(),抛出第一个值即arr[0],原数组改变减少第一项
2.关于JS延迟加载
JS延迟加载的方式:1.位置,js放在</body>结束标签前 2.监听,window.onload后再添加script标签3.属性,为script标签添加属性defer或async 4.ajax下载js脚本后eval()执行
3.defer和async的比较
3.1 defer="defer",defer默认false:
该属性用来通知浏览器,这段脚本代码将不会产生任何文档内容。
例如 JavaScript代码中的document.write()方法将不会骑作用,浏览器遇到这样的代码将会忽略,并继续执行后面的代码。
属性只能是 defer,与属性名相同。
在HTML语法格式下,也允许不定义属性值,仅仅使用属性名。3.2 async="true/false",只写async省略属性值的情况下为true:
该属性为html5中新增的属性,它的作用是能够异步地下载和执行脚本,不因为加载脚本而阻塞页面的加载。
一旦下载完毕就会立刻执行。加上defer 等于在页面完全载入后再执行,相当于文档载入后即执行,不用等包括图片在内的资源下载完毕。
async和defer一样,都不会阻塞其他资源下载,所以不会影响页面的加载,
但在async的情况下,js文档一旦下载完毕就会立刻执行,所以很有可能不是按照原本的顺序来执行,如果js有依赖性,就要注意了。3.3 相同点:
加载文件时不阻塞页面渲染;
使用这两个属性的脚本中不能调用document.write方法;
允许不定义属性值,仅仅使用属性名;3.4 不同点:
html的版本html4.0中定义了defer;html5.0中定义了async;这将造成由于浏览器版本的不同而对其支持的程度不同;执行时刻:每一个async属性的脚本都在它下载结束之后立刻执行,同时会在window的load事件之前执行。
所以就有可能出现脚本执行顺序被打乱的情况;
每一个defer属性的脚本都是在页面解析完毕之后,按照原本的顺序执行,同时会在document的DOMContentLoaded之前执行。3.5 混合用
如果async为true,那么脚本在下载完成后异步执行。
如果async为false,defer为true,那么脚本会在页面解析完毕之后执行。
如果async和defer都为false,那么脚本会在页面解析中,停止页面解析,立刻下载并且执行。
4.关于ajax
var xhr = new XMLHttpRequest(); IE new ActiveXObject("Microsoft.XMLHTTP");
1.xhr.open()
三个参数:1)请求方式,post/get2)请求的URL3)是否发送异步请求 true/false
注意: 只是启动,并未发送请求,要调用send
2.xhr.send()
一个参数:必须有参数为http请求的主体post请求一般传入get请求必须传入null
发送后得到服务器的响应,响应的数据会自动填充xhr的属性
responseText,响应主体responseXMLstatus,http状态码statusText,状态说明
3.xhr.readyState
如何判断服务器响应已到位,如何判断响应所处阶段
xhr.readyState:0,1,2,3,4
4表示完成,收到全部响应
4.xhr.status
((status >= 200 && status <300) || status = = = 304 )表示请求成功
5.xhr.onreadystatechange事件
readyState改变一次,onreadystatechange事件触发一次
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){if(xhr.readyState == 4){try {if((xhr.status >= 200 && xhr.status <300) || xhr.status == 304){console.log(xhr.responseText);}else{console.log("erro:" + xhr.status);}}catch(ex){//ontimeout处理}}
};
xhr.open("get","example.js",true);//异步
xhr.send(null);
6.对GET,POST请求参数的处理
GET
1) encodeURIComponent()对参数键和值进行编码,保证格式正确2) 键=值对之间以 & 分隔
function addURLParam(url,name,value){url + = (url.indexOf("?") = = -1 ? "?" : "&");url + = encodeURIComponent(name) + "=" + encodeURIComponent(value);return url;
}
POST
XMLHttpRequest 1级的实现:1)Content-Type的设置:xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");2)serialize()序列化数据var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){if(xhr.readyState == 4){try {if((xhr.status >= 200 && xhr.status <300) || xhr.status == 304){console.log(xhr.responseText);}else{console.log("erro:" + xhr.status);}}catch(ex){//ontimeout处理}}
};
xhr.open("post",url,true);//异步
xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
var form = document.getElementById("exampleID");
xhr.send(serialize(form));
XMLHttpRequest 2级
增加了FormData:不必明确头部类型var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){if(xhr.readyState == 4){try {if((xhr.status >= 200 && xhr.status <300) || xhr.status == 304){console.log(xhr.responseText);}else{console.log("erro:" + xhr.status);}}catch(ex){//ontimeout处理}}
};
xhr.open("post",url,true);//异步var form = document.getElementById("exampleID");
xhr.send(new FormData(form));
7.XMLHttpRequest 2 级
xhr.timeout = 属性值xhr.ontimemout = function(){console.log("超时未收到响应");
};在规定时间内浏览器未收到响应就触发 ontimeout 事件
5.关于web存储
5.1 cookie,sessionStorage,localStorage区别?
sessionStorage,loalStorage统称webStorage;Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在,而Web Storage仅仅是为了在本地“存储”数据而生
(1)存储大小:
cookie,4k; sessionStorage,localStorage,5M或更大;
(2)过期时间:
cookie,过期时间前一直有效,默认cookie(没有设置expires的cookie)失效时间直到关闭浏览器,设置方式保留COOKIES一个小时------Response.Cookies("MyCookie").Expires = DateAdd("h", 1, Now());sessionStorage关闭即删除,只要同源的同窗口(或tab)中,刷新页面或进入同源的不同页面,数据始终存在loalStorage永不丢失
(3)服务器交互带宽使用情况:
cookie放在请求头发送给服务端,浪费带宽sessionStorage,loalStorage无于服务端交互
(4)存储位置:
cookie以键值对形式存储在http请求的header中发送给服务端,同时从服务端获得的cookie是 键=值分号隔开的形式存储 sessionStorage,localStorage存储在本地
(5)共享:
cookie受同源策略限制sessionStorage同一窗口共享localStorage受同源限制
(6)用法:
cookie需要自己封装方法* escape()函数是JS内置函数,编码将字符串编码为16进制,unescape()解码
1.添加一个cookie
<script language="JavaScript" type="text/JavaScript">
<!--
function addcookie(name,value,expireHours){var cookieString=name+"="+escape(value);//判断是否设置过期时间if(expireHours>0){var date=new Date();date.setTime(date.getTime()+expireHours*3600*1000);cookieString=cookieString+"; expire="+date.toGMTString();// 或者cookieString+=";max-age="+60*5; /* 设置cookie的有效期为5分钟 */}document.cookie=cookieString;
}
//-->
</script>
2.获取指定名称的cookie值:getcookie(name)
该函数返回名称为name的cookie值,如果不存在则返回空,其实现如下:
<script language="JavaScript" type="text/JavaScript">
<!--
function getcookie(name){var strcookie=document.cookie;var arrcookie=strcookie.split(";");for(var i=0,len=arrcookie.length;i<len;i++){var arr=arrcookie[i].split("=");if(arr[0]==name)return unescape(arr[1]);}return "";
}
//-->
</script>
3.删除指定名称的cookie:deletecookie(name)
该函数可以删除指定名称的cookie,其实现如下:
<script language="JavaScript" type="text/JavaScript">
<!--
function deletecookie(name){var cookieValue = getCookie(name);var cookieString = null;if(cookieValue!== "" || cookieValue!==null){cookieString = name + "=" + escape(cookieValue) + ";max-age=" + 0;}document.cookie = cookieString;
}
//-->
</script>
cookie 的属性:Domain(设置子域该域下才可访问cookie)HttpOnly(设置后将不能用JS脚本操作cookie),Secure(设置后将只能通过HTTPS协议访问),Expiress(过期时间,不设置默认关闭浏览器cookie失效),目前已被max-age属性所取代 max-age用秒来设置cookie的生命周期Path(设置路径的页面才可访问cookie)
sessionStorage,localStorage有接口:
setItem,getItem,removeItem,clear
例如清除所有的key/value
sessionStorage.clear(); localStorage.clear();
sessionStorage.setItem("key", "value");
var value = sessionStorage.getItem("key");
sessionStorage.removeItem("key");
5.关于http
5.1 状态码
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)204 NO CONTENT - [DELETE]:用户删除数据成功。301,302,303 redirect:重定向;301永久性重定向 增加SEO排名,说说302临时重定向,303:对于POST请求,它表示请求已经被处理,客户端可以接着使用GET方法去请求Location里的URI。307:对于POST请求,表示请求还没有被处理,客户端应该向Location里的URI重新发起POST请求。304not modified:未修改返回缓存的内容不再请求新的;request If-None-Match400:客户端的URL输入有问题,浏览器解析不出来 401:需要身份验证403:已经验证身份通过,但是服务器不予执行404:对客户端请求服务端找不到资源406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误503:服务器暂时无法提供服务,过一会就好了
5.2 GET和POST的区别?
GET - 从指定的资源请求数据
POST - 向指定的资源提交要被处理的数据
大小限制
get 1024字节post 无限制,但可以自行设定
安全性
post较get安全
数据存放
get传输的参数附在URL后面post传输的数据放在HTTP请求体中
幂等
get是幂等的,post不是
缓存,收藏,历史
get都可以,post没有
6.关于网络安全
xss(cross site script)跨站脚本攻击:Reflected XSS(基于反射的XSS攻击):搜索框内键入恶意代码Stored XSS(基于存储的XSS攻击):发布的帖子/文章键入恶意代码DOM-based or local XSS(基于DOM或本地的XSS攻击):免费WIFI中间网关对网页修改嵌入恶意代码防范:前端对要显示的内容和服务端返回的内容进行转码htmlencode服务端对请求的内容进行验证防范攻击xss攻击主要是拿到cookie,所以可以禁止操作cookie,设置HttpOnly属性详细见 https://segmentfault.com/a/1190000008423064
CSRF跨站请求伪造 cross site request forgery
详情:https://segmentfault.com/a/1190000008424201冒充用户发起请求(在用户不知情的情况下),完成一些违背用户意愿的请求
(比如散布的小广告点进去就完成转正操作了假如你刚刚登录过网上银行session依旧未过期)防御方法:验证HTTP请求头部的referer即可知道是否是bank.com发起的请求;请求地址中添加token并验证;HTTP头部添加自定义属性并验证;验证码
- XSS:
攻击者发现XSS漏洞——构造代码——发送给受害人——受害人打开——攻击者获取受害人的cookie——完成攻击
- CSRF:
攻击者发现CSRF漏洞——构造代码——发送给受害人——受害人打开——受害人执行代码——完成攻击
SQL注入攻击构造巧妙的SQL语句,从而成功获取想要的数据;黑客的填空游戏
-
某个网站的登录验证的SQL查询代码为:
strSQL = "SELECT * FROM users WHERE (name = '" + userName + "') and (pw = '"+ passWord +"');"
- 恶意填入
userName = "1' OR '1'='1";
- 与
passWord = "1' OR '1'='1";
- 时,将导致原本的SQL字符串被填为
strSQL = "SELECT * FROM users WHERE (name = '1' OR '1'='1') and (pw = '1' OR '1'='1');"
- 也就是实际上运行的SQL命令会变成下面这样的
strSQL = "SELECT * FROM users;"
防御方法 : 对输入进行验证 整形参数判断 unicode转换等
7.关于跨域
同源策略
1 协议相同
2 域名相同
3 端口相同
跨域的方法
1.window.postMessage(message,targetOrigin) (双向跨域)
2.document.domain = 共同的主域名 跨子域 (双向跨域)
http://www.a.com/a.jshttp://script.a.com/b.js统一为主域名a.com
----------------------------------------------------------
3.jsonp(单向跨域)
只支持get请求
<script src=".../callback()"></script>
4.CORS跨域资源共享 (单向跨域)
比JSONP强大,支持各种类型的HTTP请求允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制A跨域访问B,需要在B的响应头加入 Access-Control-Allow-Origin:http://A
5.服务器代理 (单向跨域)
跨域的HTTP请求是在服务器端
6.window.name (单向跨域)
8.关于构建工具gulp git grunt fis3
gulpjs是一个前端构建工具,与gruntjs相比:
gulpjs无需写一大堆繁杂的配置参数,
而且gulpjs使用的是nodejs中stream来读取和操作数据,其速度更快
npm install -g gulp 全局安装到本机c盘data中npm install gulp
安装到本项目的node moudule模块中npm install --save-dev gulp
将gulp依赖添加到本项目的packge.json的依赖内
就可以运行gulp命令执行gulpfile.js文件内定义的default任务了
gulpfile.js内
常用的四个API:gulp.task(), gulp.src(), gulp.dest(),gulp.watch()
gulp.src
gulp.src(globs) 获取文件流对象,是虚拟文件对象流,进而调用stream.pipe()继续操作流通过指定gulp.src()方法配置参数中的base属性,我们可以更灵活的来改变gulp.dest()生成的文件路径。当我们没有在gulp.src()方法中配置base属性时,base的默认值为通配符开始出现之前那部分路径。例子:
gulp.src(script/lib/*.js, {base:'script'}) //配置了base参数,此时base路径为script
//假设匹配到的文件为script/lib/jquery.js.pipe(gulp.dest('build')) //此时生成的文件路径为 build/lib/jquery.js
gulp.dest
gulp.dest(path) 用来写文件,path替换掉基本路径就是生成的文件的路径
gulp.task
gulp.task(name,[deps],fn) 任务的名字,依赖的任务,执行的方法deps只有一个也要用数组括起来如果任务A依赖B,B有异步编码,A不会等B的异步代码执行完而是直接执行,解决办法:1,执行一个回调函数通知gulp异步完成
2,返回一个流对象
3,require Q;返回promise对象
gulp.watch
gulp.watch(glob,tasks) 匹配文件路径 文件改变后执行tasks(之前定义好的task,gulp.task(name,[deps],fn))详情见 https://segmentfault.com/a/1190000008427866
对于GIT的提问
git rebase
git merge
等等 详情见 https://segmentfault.com/a/11...
9.关于框架vue angularjs
v-for ng-repeatnew vue({el:data:methods:}) angular.module(name,[]) 继而controller
angular controller之间通信方式:
上下级之间通信:作用域继承、事件触发($on、$emit 和 $boardcast)
同级之间通信:注入服务 service、借助父级controller实现子级controller之间的通信、借助$rootScope实现同级之间的通信
10.关于nodejs
创建简单的服务器
var http = require("http"); http.createServer(function(request, response) { response.writeHead(200, {"Content-Type": "text/plain"}); response.write("Hello World"); response.end(); }).listen(8888);
11.关于restfulAPI
1.协议
HTTPS协议
2.域名
可以添加次级域名https://api.example.com如果不需要扩展,可以放在主域名下https://example.com/api
3.版本
为API添加版本https://api.example.com/v1/
4.不允许动词
路径名词一般与数据库表格一直https://api.example.com/v1/animals
5.参数设计
参数键值形式 & 符号分开https://api.example.com/v1/animals?name='cat'&sex='1'
6.错误处理
请求结果是错误的4xx一般返回的JSON数据中设置erro键{error: "Invalid API key"
}
7.HTTP动词
常用的:GET,POSTGET(SELECT):从服务器取出资源(一项或多项)POST(CREATE):在服务器新建一个资源另有:PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)DELETE(DELETE):从服务器删除资源HEAD:获取资源的元数据OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的
8.状态码
上翻有
12.关于异步编程
ES 6以前:
-
回调函数(ajax实现异步的原理就是采用了回调函数)
function f1(callback){setTimeout(function () {// f1的任务代码callback();}, 1000);}f1(f2);
问题:多层嵌套很混乱,异常难以捕获
-
事件驱动/事件监听 发布/订阅模式(观察者模式)
原理同 回调
-
promise对象
promise模式在任何时刻都处于以下三种状态之一: 未完成(unfulfilled)、已完成(resolved)和拒绝(rejected)promise对象上的then方法负责添加针对已完成和拒绝状态下的处理函数。 then(resolvedHandler, rejectedHandler); then方法会返回另一个promise对象,以便于形成promise管道, 这种返回promise对象的方式能够支持开发人员把异步操作串联起来
ES 6:
* Generator函数(协程coroutine)
ES 7:
* async和await
13.关于模块化编程 requirejs seajs commonjs
AMD(Require遵循的规范)define, require
CMD(SeaJS遵循的规范)经常使用的 API 只有 define, require, require.async, exports, module.exports 这五个
-
promise(commonJS提出的规范)
1.对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。 不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)2.CMD 推崇依赖就近,AMD 推崇依赖前置。
14.关于面向对象
14.1封装性
JS没有类,怎么谈封装呢。有对象,对象有属性
有构造函数,构造函数有基本属性值和引用属性值
函数有prototype原型,可以实现属性方法共享
14.2多态性
14.3继承性
某一对象的实例 赋值给 另一个对象的原型 实现继承
构造函数、实例、原型的关系:
var a = function(){...};var b = new a();//b 是由 a 构造出来的var c = function(){...};c.prototype = b;//c 继承了 a
15.关于跨设备响应式
1.百分比
2.移动端禁viewport缩放功能
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" />
width:viewport 的宽度,可以指定一个固定值,如650;或者可以是device-width,表示设备的宽度height:和 width 相对应,可指定高度initial-scale:页面初始缩放比例(0-1)maximum-scale:允许用户缩放到的最大比例(0-1)minimum-scale:允许用户缩放到的最小比例(0-1)user-scalable:用户是否可以手动缩放(yes/no)
禁用chrome 自调节字体大小body {-webkit-text-size-adjust: 100%;
}
3.CSS3 media queries
@media only screen and (max/min-width/height: 960px) {/* 样式定义 */
}@media only screen and (max-width:500px){.outDiv {margin: 0 auto;}
}
16.关于浏览器兼容
简单总结
css 样式加前缀 -webkit这样子的js 冒泡事件和阻止冒泡
很多见:http://blog.csdn.net/xingxing...
http://blog.csdn.net/comeonj/...
17.关于linux
暂且放两个链接 之前写过的:
https://segmentfault.com/a/11...
https://segmentfault.com/n/13...
18. 前端性能优化
- HTTP:减少HTTP请求;解决办法:合并图片,合并css,js文件,lazzyload懒加载图片
- CSS:合理用reflow,repaint:style变一次就reflow一次,因此尽可能设一个新的class,改变className,reflow一次
- DOM:减少DOM操作,多用innerHTML一次添加
- JSON格式交换数据,轻量级数据
- css放在头部,js放在尾部,外部引用
6.CDN内容分发网络,实时性不太好