GET和POST的区别
- GET请求能够缓存,POST不能
- POST请求比GET请求安全一点点,因为GET请求参数都包含在URL里面,会被浏览器保存在历史记录中
- URL有长度限制,会影响GET请求,这个长度限制是浏览器规定的
- POST支持更多的编码类型且不对数据类型限制
前端性能优化
加载优化
- 编写样式代替图片,使用iconfont代替图片
- 使用CDN加载图片
- 小图使用base64编码代替图片链接
- 使用雪碧图
- 图片懒加载
DNS预解析
<link rel="dns-prefetch" href="http://example.com">
预加载
<link rel="preload" href="http://example.com">
预渲染
<link rel="prerender" href="http://example.com">
单页应用
- 文件压缩、合并
- 按需加载
- 样式抽离,公共代码抽离
脚本
- 减少重绘与回流
- 尽量使用事件代理代替事件绑定
css优化
- css写在头部,js写在尾部
- 标准化各种浏览器前缀
- 选择器嵌套层级避免太深
缓存
缓存方式
- Service Worker
- Memory Cache
- Disk Cache
- Push Cache
- 网络请求
缓存策略
- 强制缓存(Cache-control、Expires)
- 协商缓存(ETag、Last-Modified)
存储
| 特性 | cookie | localStorage | sessionStorage | indexDB |
|---|---|---|---|---|
| 数据生命周期 | 一般由服务器生成,可以设置过期时间 | 除非被清理,否则一直存在 | 页面关闭就清理 | 除非被清理,否则一直存在 |
| 数据存储大小 | 4K | 5M | 5M | 无限 |
| 与服务端通信 | 每次都会携带在header中,对于请求性能影响 | 不参与 | 不参与 | 不参与 |
继承
原型链继承
function Parent(name) {
this.name = name;
}
Parent.prototype.say = function() {
console.log(this.name);
}
function Child(name) {
this.name = name;
}
Child.prototype = new Parent('father');
Child.prototype.eat = function() {
console.log('eat!!!');
}
Child.prototype.constructor = Child;
var child = new Child('Son');
child.say(); // Son
child.eat(); // eat!!!
类式继承
function Parent(name) {
this.name = name;
}
Parent.prototype.say = function() {
console.log(this.name);
}
function Child(name, parentName) {
Parent.call(this, parentName);
this.name = name;
}
Child.prototype.eat = function() {
console.log('eat!!!');
}
var child = new Child('Son');
child.say(); // Uncaught TypeError: child.say is not a function
child.eat(); // eat!!!
组合式继承
function Parent(name) {
this.name = name;
}
Parent.prototype.say = function() {
console.log(this.name);
}
function Child(name, parentName) {
Parent.call(this, parentName);
this.name = name;
}
Child.prototype = new Parent('father');
Child.prototype.eat = function() {
console.log('eat!!!');
}
Child.prototype.constructor = Child;
var child = new Child('Son');
child.say(); // Son
child.eat(); // eat!!!
寄生组合式继承
function Parent(name) {
this.name = name;
}
Parent.prototype.say = function() {
console.log(this.name);
}
function Child(name, parentName) {
Parent.call(this, parentName);
this.name = name;
}
function factory(proto) {
function F() {}
F.prototype = proto;
return new F();
}
Child.prototype = factory(Parent.prototype);
Child.prototype.eat = function() {
console.log('eat!!!');
}
Child.prototype.constructor = Child;
var child = new Child('Son');
child.say(); // Son
child.eat(); // eat!!!
函数实现
- 函数组合运行
- 说明:实现一个方法,可将多个函数方法按从左到右的方式组合运行。
- 如
composeFunctions(fn1,fn2,fn3,fn4)等价于fn4(fn3(fn2(fn1))。 - 示例:
- const add = x => x + 1;
- const multiply = (x, y) => x * y;
- const multiplyAdd = composeFunctions(multiply, add);
- multiplyAdd(3, 4) // 返回 13
function composeFunctions() {
var args = Array.prototype.slice.apply(arguments);
return function() {
if (args.length == 1) {
return args[0].apply(this, Array.prototype.slice.apply(arguments));
}
return composeFunctions(...args.slice(1))(args[0].apply(this, Array.prototype.slice.apply(arguments)));
}
}
节流和防抖
// 防抖,只执行最后一次
function debounce (fn, wait) {
var timer = null;
return () => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, Array.prototype.slice.call(arguments, 0)), wait);
}
},
// 节流,每隔一段时间执行一次
function throttle(fn, wait) {
var timer = null;
return () => {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, Array.prototype.slice.call(arguments, 0));
timer = null;
}, wait);
}
}
}