前端开发中不可忽视的知识点汇总


2019-10-4 拓展

css禁用鼠标事件

.disabled {
    pointer-events: none;
    cursor: default;
    opacity: 0.6;
}
1
2
3
4
5

get/post的理解和他们之间的区别

GET 请求可被缓存
GET 请求保留在浏览器历史记录中
GET 请求可被收藏为书签
GET 请求不应在处理敏感数据时使用
GET 请求有长度限制(2048字符),IE和Safari浏览器限制2k;Opera限制4k;Firefox,Chrome限制8k
GET 请求只应当用于取回数据

POST 请求不会被缓存
POST 请求不会保留在浏览器历史记录中
POST 不能被收藏为书签
POST 请求对数据长度没有要求

css禁止用户选择

body{
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
1
2
3
4
5
6
7
8

数组去重

// indexOf实现
var array = [1, 1, '1'];

function unique(array) {
    var res = [];
    for (var i = 0, len = array.length; i < len; i++) {
        var current = array[i];
        if (res.indexOf(current) === -1) {
            res.push(current)
        }
    }
    return res;
}

console.log(unique(array));

// 排序后去重
var array = [1, 1, '1'];

function unique(array) {
    var res = [];
    var sortedArray = array.concat().sort();
    var seen;
    for (var i = 0, len = sortedArray.length; i < len; i++) {
        // 如果是第一个元素或者相邻的元素不相同
        if (!i || seen !== sortedArray[i]) {
            res.push(sortedArray[i])
        }
        seen = sortedArray[i];
    }
    return res;
}

console.log(unique(array));

// filter实现
var array = [1, 2, 1, 1, '1'];
function unique(array) {
    var res = array.filter(function(item, index, array){
        return array.indexOf(item) === index;
    })
    return res;
}
console.log(unique(array));

// 排序去重
var array = [1, 2, 1, 1, '1'];
function unique(array) {
    return array.concat().sort().filter(function(item, index, array){
        return !index || item !== array[index - 1]
    })
}
console.log(unique(array));

// Object键值对
var array = [{value: 1}, {value: 1}, {value: 2}];

function unique(array) {
    var obj = {};
    return array.filter(function(item, index, array){
        console.log(typeof item + JSON.stringify(item))
        return obj.hasOwnProperty(typeof item + JSON.stringify(item)) ? false : (obj[typeof item + JSON.stringify(item)] = true)
    })
}

console.log(unique(array)); // [{value: 1}, {value: 2}]

// ES6 Set实现
var unique = (a) => [...new Set(a)]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

什么是CDN和CDN的好处

CDN:CDN是将源站内容分发至最接近用户的节点,使用户可就近取得所需内容,提高用户访问的响应速度和成功率。 解决因分布、带宽、服务器性能带来的访问延迟问题,适用于站点加速、点播、直播等场景。

好处:

1、多域名加载资源
一般情况下,浏览器都会对单个域名下的并发请求数(文件加载)进行限制,通常最多有4个,
那么第5个加载项将会被阻塞,直到前面的某一个文件加载完毕。因为CDN文件是存放在不同
区域(不同IP)的,所以对浏览器来说是可以同时加载页面所需的所有文件(远不止4个),
从而提高页面加载速度。

2、文件可能已经被加载过并保存有缓存
一些通用的js库或者是css样式库,如jQuery,在网络中的使用是非常普遍的。当一个用户在
浏览你的某一个网页的时候,很有可能他已经通过你网站使用的CDN访问过了其他的某一个网站,
恰巧这个网站同样也使用了jQuery,那么此时用户浏览器已经缓存有该jQuery文件(同IP的同
名文件如果有缓存,浏览器会直接使用缓存文件,不会再进行加载),所以就不会再加载一次了,
从而间接的提高了网站的访问速度

3、高效率
你的网站做的再NB也不会NB过百度NB过Google吧?一个好的CDNs会提供更高的效率,更低的
网络延时和更小的丢包率。

4、分布式的数据中心
假如你的站点布置在北京,当一个香港或者更远的用户访问你的站点的时候,他的数据请求势
必会很慢很慢。而CDNs则会让用户从离他最近的节点去加载所需的文件,所以加载速度提升
就是理所当然的了。

5、使用情况分析
一般情况下CDNs提供商(如百度云加速)都会提供数据统计功能,可以了解更多关于用户
访问自己网站的情况,可以根据统计数据对自己的站点适时适当的做出些许调整。

6、有效防止网站被攻击
一般情况下CDNs提供商也是会提供网站安全服务的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

如何提高首频加载速度

1.js外联文件放到body底部,css外联文件放到head内
2.http静态资源尽量用多个子域名
3.服务器端提供html和http静态资源时最好开启gzip
4.在js,css,img等资源响应的http headers里设置expires,last-modified
5.尽量减少http requests的数量
6.js/css/html/img资源压缩
7.使用css spirtes,可以减少img请求次数
8.大图使用lazyload懒加载
9.避免404,减少外联js
10.减少cookie大小可以提高获得响应的时间
11.减少dom elements的数量
12.使用异步脚本,动态创建脚本
1
2
3
4
5
6
7
8
9
10
11
12

浏览器内核(渲染引擎)

IE/360/搜狗浏览器: Trident

Chrome/Safari/Opera: WebKit(KHTML的一个开源的分支)

(虽然我们称WebKit为浏览器内核,但不太适合直接称渲染引擎,因为WebKit本身主要是由两个引擎构成的,一个正是渲染引擎“WebCore”,另一个则是javascript解释引擎“JSCore”,它们均是从KDE的渲染引擎KHTML及javascript解释引擎KJS衍生而来。)

(在13年发布的Chrome 28.0.1469.0版本开始,Chrome放弃Chromium引擎转而使用最新的Blink引擎(基于WebKit2——苹果公司于2010年推出的新的WebKit引擎),Blink对比上一代的引擎精简了代码、改善了DOM框架,也提升了安全性。)

(为了减少研发成本,Opera在20132月宣布放弃Presto,转而跟随Chrome使用WebKit分支的Chromium引擎作为自家浏览器核心引擎)

Firefox/SeaMonkey: Gecko
1
2
3
4
5
6
7
8
9
10
11

浏览器渲染过程及优化建议

1)解析:
一个是HTML/SVG/XHTML,事实上,Webkit有三个C++的类对应这三类文档。解析这三种文件会
产生一个DOM Tree。 CSS,解析CSS会产生CSS规则树。 Javascript,脚本,主要是通过DOM 
API和CSSOM API来操作DOM Tree和CSS Rule Tree.
2)渲染:浏览器引擎会通过DOM Tree 和 CSS Rule Tree 来构造 Rendering Tree。注意:
Rendering Tree 渲染树并不等同于DOM树,因为一些像Header或display:none的东西就没必
要放在渲染树中了。 CSS 的 Rule Tree主要是为了完成匹配并把CSS Rule附加上Rendering Tree
上的每个Element。也就是DOM结点。也就是所谓的Frame。 然后,计算每个Frame
(也就是每个Element)的位置,这又叫layout和reflow过程。
3)绘制:最后通过调用操作系统Native GUI的API绘制。
1
2
3
4
5
6
7
8
9
10

减少reflow和repaint 1)不要一条一条地修改DOM的样式。还不如预先定义好css的class,然后修改DOM的className。

把DOM离线后修改。如:
使用documentFragment 对象在内存里操作DOM 先把DOM给display:none(有一次reflow),
然后你想怎么改就怎么改。比如修改100次,然后再把他显示出来。 clone一个DOM结点到内存
里,然后想怎么改就怎么改,改完后,和在线的那个的交换一下。
3)不要把DOM结点的属性值放在一个循环里当成循环里的变量。不然这会导致大量地读写这
个结点的属性
4)为动画的HTML元件使用fixed或absoulte的position,尽量使用transfoem,那么修改
他们的CSS是不会reflow的
5)尽量少使用table布局。因为可能很小的一个小改动会造成整个table的重新布局
1
2
3
4
5
6
7
8
9

页面导入样式时,使用link和@import有什么区别?

1)link属于XHTML标签,除了加载CSS外,还能用于定义RSS, 定义rel连接属性等作用;
而@import是CSS提供的,只能用于加载CSS;
(2)页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
(3)import是CSS2.1 提出的,只在IE5以上才能被识别,而link是XHTML标签,无兼容问题;
(4)link支持使用js控制DOM去改变样式,而@import不支持;
1
2
3
4
5

简述一下你对HTML语义化的理解?

用正确的标签做正确的事情。
html语义化让页面的内容结构化,便于对浏览器、搜索引擎解析;
即使在没有样式CSS情况下也以一种文档格式显示,并且是容易阅读的;
搜索引擎的爬虫也依赖于HTML标记来确定上下文和各个关键字的权重,利于SEO;
使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。
1
2
3
4
5

请描述一下 cookies,sessionStorage 和 localStorage 的区别?

cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。
cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间来回传递。
sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
存储大小:
cookie数据大小不能超过4k。
sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
有期时间:
localStorage    存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
sessionStorage  数据在当前浏览器窗口关闭后自动删除。
cookie          设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
1
2
3
4
5
6
7
8
9
10

iframe有那些缺点?

*iframe会阻塞主页面的Onload事件;
*搜索引擎的检索程序无法解读这种页面,不利于SEO;
*iframe和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载。
使用iframe之前需要考虑这两个缺点。如果需要使用iframe,最好是通过javascript
动态给iframe添加src属性值,这样可以绕开以上两个问题。
1
2
3
4
5

网页验证码是干嘛的,是为了解决什么安全问题?

区分用户是计算机还是人的公共全自动程序。可以防止恶意破解密码、刷票、论坛灌水;
有效防止黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。
1
2

介绍一下标准的CSS的盒子模型?低版本IE的盒子模型有什么不同的?

1)有两种, IE 盒子模型、W3C 盒子模型; 
(2)盒模型: 内容(content)、填充(padding)、边界(margin)、 边框(border); 
(3)区 别: IE的content部分把 border 和 padding计算了进去;
1
2
3

position的值relative和absolute定位原点是?

absolute
生成绝对定位的元素,相对于值不为 static的第一个父元素进行定位。
fixed (老IE不支持)
生成绝对定位的元素,相对于浏览器窗口进行定位。
relative
生成相对定位的元素,相对于其正常位置进行定位。
static
默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right z-index 声明)。
inherit
规定从父元素继承 position 属性的值。
1
2
3
4
5
6
7
8
9
10

经常遇到的浏览器的兼容性有哪些?原因,解决方法是什么,常用hack的技巧 ?

png24位的图片在iE6浏览器上出现背景,解决方案是做成PNG8.

浏览器默认的margin和padding不同。解决方案是加一个全局的*{margin:0;padding:0;}来统一。

IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。

浮动ie产生的双倍距离 #box{ float:left; width:10px; margin:0 0 0 100px;}
这种情况之下IE会产生20px的距离,解决方案是在float的标签样式控制中加入 
——_display:inline;将其转化为行内属性。(_这个符号只有ie6会识别)

渐进识别的方式,从总体中逐渐排除局部。
首先,巧妙的使用“\9”这一标记,将IE游览器从所有情况中分离出来。
接着,再次使用“+”将IE8和IE7、IE6分离开来,这样IE8已经独立识别。
css
.bb{
background-color:red;/所有识别/
background-color:#00deff\9; /IE678识别/
+background-color:#a200ff;/IE67识别/
_background-color:#1e0bd1;/IE6识别/
}

IE下,可以使用获取常规属性的方法来获取自定义属性,
也可以使用getAttribute()获取自定义属性;
Firefox下,只能使用getAttribute()获取自定义属性。
解决方法:统一通过getAttribute()获取自定义属性。

IE下,even对象有x,y属性,但是没有pageX,pageY属性;
Firefox下,event对象有pageX,pageY属性,但是没有x,y属性。

解决方法:(条件注释)缺点是在IE浏览器下可能会增加额外的HTTP请求数。

Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示,
可通过加入 CSS 属性 -webkit-text-size-adjust: none; 解决。

超链接访问过后hover样式就不出现了 被点击访问过的超链接样式不在具有
hover和active了解决方法是改变CSS属性的排列顺序:
 L-V-H-A : a:link {} a:visited {} a:hover {} a:active {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

CSS优化、提高性能的方法有哪些?

关键选择器(key selector)。选择器的最后面的部分为关键选择器(即用来匹配目标元素的部分);
如果规则拥有 ID 选择器作为其关键选择器,则不要为规则增加标签。过滤掉无关的规则(这样样式系统就不会浪费时间去匹配它们了);
提取项目的通用公有样式,增强可复用性,按模块编写组件;增强项目的协同开发性、可维护性和可扩展性;
使用预处理工具或构建工具(gulp对css进行语法检查、自动补前缀、打包压缩、自动优雅降级)。
1
2
3
4

如何修改chrome记住密码后自动填充表单的黄色背景 ?

input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill {
    background-color: rgb(250, 255, 189); /* #FAFFBD; */
    background-image: none;
    color: rgb(0, 0, 0);
  }
1
2
3
4
5

让页面里的字体变清晰,变细用CSS怎么做?

-webkit-font-smoothing: antialiased;
1

让overflow:scroll平滑滚动?

-webkit-overflow-scrolling: touch;
1

如何将浮点数点左边的数每三位添加一个逗号,如12000000.11转化为『12,000,000.11』?

function commafy(num){
  	return num && num
  		.toString()
  		.replace(/(\d)(?=(\d{3})+\.)/g, function($1, $2){
  			return $2 + ',';
  		});
  }
1
2
3
4
5
6
7

Javascript作用链域?

全局函数无法查看局部函数的内部细节,但局部函数可以查看其上层的函数细节,
直至全局细节。 当需要从局部函数查找某一属性或方法时,如果当前作用域没有
找到,就会上溯到上层作用域查找, 直至全局函数,这种组织形式就是作用域链。
1
2
3

谈谈This对象的理解。

this总是指向函数的直接调用者(而非间接调用者); 
如果有new关键字,this指向new出来的那个对象; 
在事件中,this指向触发这个事件的对象,
特殊的是,IE中的attachEvent中的this总是指向全局对象Window;
1
2
3
4

eval是做什么的?

它的功能是把对应的字符串解析成JS代码并运行; 应该避免使用eval,
不安全,非常耗性能(2次,一次解析成js语句,一次执行)。 由JSON字
符串转换为JSON对象的时候可以用eval,var obj =eval('('+ str +')');
1
2
3

javascript 代码中的"use strict";是什么意思 ? 使用它区别是什么?

使JS编码更加规范化的模式,消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为。
默认支持的糟糕特性都会被禁用,比如不能用with,也不能在意外的情况下给全局变量赋值;
全局变量的显示声明,函数必须声明在顶层,不允许在非函数代码块内声明函数,arguments.callee也不允许使用;
保证代码运行的安全,限制函数中的arguments修改;
提高编译器效率,增加运行速度;
1
2
3
4
5

如何判断一个对象是否属于某个类?

if(a instanceof Person){
   alert('yes');
}
// 判断对象类型最好的方式
// 对于 Object 对象,直接调用 toString()  就能返回 [object Object] 。
//而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。
Object.prototype.toString.call('') ;   // [object String]
Object.prototype.toString.call(1) ;    // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window 是全局对象 global 的引用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

new一个对象的过程

1、创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。
2、属性和方法被加入到 this 引用的对象中。
3、新创建的对象由 this 所引用,并且最后隐式的返回 this 。
1
2
3

Ajax 解决浏览器缓存问题

1、在ajax发送请求前加上 anyAjaxObj.setRequestHeader("If-Modified-Since","0")。
2、在ajax发送请求前加上 anyAjaxObj.setRequestHeader("Cache-Control","no-cache")。
3、在URL后面加上一个随机数: "fresh=" + Math.random();。
4、在URL后面加上时间戳:"nowtime=" + new Date().getTime();。
5、如果是使用jQuery,直接这样就可以了 $.ajaxSetup({cache:false})。这样页面的所有ajax都会执行这条语句就是不需要保存缓存记录。
1
2
3
4
5

如何解决跨域问题?

jsonp、 iframe、window.name、window.postMessage、服务器上设置代理页面

列举几条 JavaScript 的基本代码规范

1)不要在同一行声明多个变量;
(2)如果你不知道数组的长度,使用 push;
(3)请使用 ===/!== 来比较 true/false 或者数值;
(4)对字符串使用单引号 ''(因为大多时候我们的字符串。特别html会出现");
(5)使用对象字面量替代 new Array 这种形式;
(6)绝对不要在一个非函数块里声明一个函数,把那个函数赋给一个变量。浏览器允许你这么做,但是它们解析不同;
(7)不要使用全局函数;
(8)总是使用 var 来声明变量,如果不这么做将导致产生全局变量,我们要避免污染全局命名空间;
(9)Switch 语句必须带有 default 分支;
(10)使用 /**...*/ 进行多行注释,包括描述,指定类型以及参数值和返回值;
(11)函数不应该有时候有返回值,有时候没有返回值;
(12)语句结束一定要加分号;
(13)for 循环必须使用大括号;
(14)if 语句必须使用大括号;
(15)for-in 循环中的变量应该使用 var 关键字明确限定作用域,从而避免作用域污染;
(16)避免单个字符名,让你的变量名有描述意义;
(17)当命名对象、函数和实例时使用驼峰命名规则;
(18)给对象原型分配方法,而不是用一个新的对象覆盖原型,覆盖原型会使继承出现问题;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

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

1)创建新节点
createDocumentFragment()    //创建一个DOM片段
createElement()   //创建一个具体的元素
createTextNode()   //创建一个文本节点2)添加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子节点前插入一个新的子节点3)查找
getElementsByTagName()    //通过标签名称
getElementsByName()    //通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)
getElementById()    //通过元素Id,唯一性
1
2
3
4
5
6
7
8
9
10
11
12
13

如何判断当前脚本运行在浏览器还是node环境中?

this === window ? 'browser' : 'node';

消除transtration闪屏

.css {
    -webkit-transform-style: preserve-3d;
    -webkit-backface-visibility: hidden;
    -webkit-perspective: 1000;
}
1
2
3
4
5

改变输入框内提示文字颜色

::-webkit-input-placeholder { /* WebKit browsers */
    color: #999; }
:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
    color: #999; }
::-moz-placeholder { /* Mozilla Firefox 19+ */
    color: #999; }
:-ms-input-placeholder { /* Internet Explorer 10+ */
    color: #999; }
input:focus::-webkit-input-placeholder{ color:#999; }
1
2
3
4
5
6
7
8
9

长时间按住页面闪退

.element {
    -webkit-touch-callout: none;
}
1
2
3

手机上的多行省略

.overflow-hidden{
    display: box !important;
    display: -webkit-box !important;
    overflow: hidden;
    text-overflow: ellipsis;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 4;/*第几行出现省略号*/
    /*text-align:justify;不能和溢出隐藏的代码一起写,会有bug*/
}
1
2
3
4
5
6
7
8
9

移动端html标签几个体验优化

html,body{

overflow: hidden;
/*手机上写overflow-x:hidden;会有兼容性问题,如果子级如果是绝对
定位有运动到屏幕外的话ios7系统会出现留白*/

-webkit-overflow-scrolling:touch;
/*流畅滚动,ios7下会有滑一下滑不动的情况,所以需要写上*/

position:realtive;
/*直接子级如果是绝对定位有运动到屏幕外的话,会出现留白*/
}
1
2
3
4
5
6
7
8
9
10
11
12

开启硬件加速

//目前,像Chrome/Filefox/Safari/IE9+以及最新版本Opera都支持硬件加速,
//当检测到某个DOM元素应用了某些CSS规则时就会自动开启,从而解决页面闪白,保证动画流畅。
.css {
    -webkit-transform: translate3d(0,0,0);
    -moz-transform: translate3d(0,0,0);
    -ms-transform: translate3d(0,0,0);
    transform: translate3d(0,0,0);
}
1
2
3
4
5
6
7
8

canvas和svg区别

1.从图像类别区分,Canvas是基于像素的位图,而SVG却是基于矢量图形。
  可以简单的把两者的区别看成photoshop与illustrator的区别。
2.从结构上说,Canvas没有图层的概念,所有的修改整个画布都要重新渲染,
  而SVG则可以对单独的标签进行修改。
3.从操作对象上说,Canvas是基于HTML canvas标签,通过宿主提供的
  Javascript API对整个画布进行操作的,而SVG则是基于XML元素的。
4.从功能上讲,SVG发布日期较早,所以功能相对Canvas比较完善。
5.关于动画,Canvas更适合做基于位图的动画,而SVG则适合图表的展示。
6.从搜索引擎角度分析,由于svg是有大量标签组成,所以可以通过给
  标签添加属性,便于爬虫搜索
1
2
3
4
5
6
7
8
9
10

什么是闭包(closure),闭包使用的优缺点

闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见
的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数
的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。

优点:
  1.保护函数内部变量的安全,加强了封装性 
  2.在内存中维持一个变量 
  3.设计私有方法和变量 
  4.可以读取函数内部的变量 
缺点:
  1.导致内存泄漏,使用不当会造成额外的内存占用 
  2.可以改变父函数的变量,所以使用时要谨慎
1
2
3
4
5
6
7
8
9
10
11
12

你有用过哪些前端性能优化的方法?

1) 减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;
      网页Gzip,CDN托管,data缓存 ,图片服务器。
(2) 前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,
      前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数
(3) 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。
(4) 当需要设置的样式很多时设置className而不是直接操作style。
(5) 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。
(6) 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。
(7) 图片预加载,将样式表放在顶部,将脚本放在底部  加上时间戳。
(8) 避免在页面的主体布局中使用table,table要等其中的内容完全下载之后
      才会显示出来,显示比div+css布局慢。对普通的网站有一个统一的思路,
      就是尽量向前端优化、减少数据库操作、减少磁盘IO。向前端优化指的是,
      在不影响功能和体验的情况下,能在浏览器执行的不要在服务端执行,能在缓存
      服务器上直接返回的不要到应用服务器,程序能直接取得的结果不要到外部取得,
      本机内能取得的数据不要到远程取,内存能取到的不要到磁盘取,缓存中有的不要
      去数据库查询。减少数据库操作指减少更新次数、缓存结果减少查询次数、将数据
      库执行的操作尽可能的让你的程序完成(例如join查询),减少磁盘IO指尽量不使
      用文件系统作为缓存、减少读写文件次数等。程序优化永远要优化慢的部分,换语言
      是无法“优化”的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

页面重构怎么操作?

网站重构:在不改变外部行为的前提下,简化结构、添加可读性,而在网站前端保持一致的行为。
也就是说是在不改变UI的情况下,对网站进行优化,在扩展的同时保持一致的UI。

对于传统的网站来说重构通常是:
  表格(table)布局改为DIV+CSS
  使网站前端兼容于现代浏览器(针对于不合规范的CSS、如对IE6有效的)
  对于移动平台的优化
  针对于SEO进行优化
  深层次的网站重构应该考虑的方面
  减少代码间的耦合
  让代码保持弹性
  严格按规范编写代码
  设计可扩展的API
  代替旧有的框架、语言(如VB)
  增强用户体验
  通常来说对于速度的优化也包含在重构中
  压缩JS、CSS、image等前端资源(通常是由服务器来解决)
  程序的性能优化(如数据读写)
  采用CDN来加速资源加载
  对于JS DOM的优化
  HTTP服务器的文件缓存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Promise优缺点

优点: 
  解决回调地狱, 对异步任务写法更标准化与简洁化
缺点: 
  首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消; 
  其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部; 
  第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成).
1
2
3
4
5
6

极简版promise封装:

  function promise () {
    this.msg = '' // 存放value和error
    this.status = 'pending'
    var that = this
    var process = arguments[0]

    process (function () {
      that.status = 'fulfilled'
      that.msg = arguments[0]
    }, function () {
      that.status = 'rejected'
      that.msg = arguments[0]
    })
    return this
  }

  promise.prototype.then = function () {
    if (this.status === 'fulfilled') {
      arguments[0](this.msg)
    } else if (this.status === 'rejected' && arguments[1]) {
      arguments[1](this.msg)
    }
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

双向数据绑定v-model的实现

通过v-model VUE实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。

// 依赖收集
// 简化版
var obj = { }
var name 
//第一个参数:定义属性的对象。
//第二个参数:要定义或修改的属性的名称。
//第三个参数:将被定义或修改的属性描述符。
Object.defineProperty(obj, "data", {
  //获取值
  get: function () {
    return name
  },
  //设置值
  set: function (val) {
    name = val
    console.log(val)
  }
})
//赋值调用set
obj.data = 'aaa'
//取值调用get
console.log(obj.data)

// 详细版
 myVue.prototype._obverse = function (obj) { // obj = {number: 0}
    var value;
    for (key in obj) {  //遍历obj对象
      if (obj.hasOwnProperty(key)) {
        value = obj[key]; 
        if (typeof value === 'object') {  //如果值是对象,则递归处理
          this._obverse(value);
        }
        Object.defineProperty(this.$data, key, {  //关键
          enumerable: true,
          configurable: true,
          get: function () {
            console.log(`获取${value}`);
            return value;
          },
          set: function (newVal) {
            console.log(`更新${newVal}`);
            if (value !== newVal) {
              value = newVal;
            }
          }
        })
      }
    }
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Thomas: 11/5/2019, 6:20:25 PM