maintainable javascript
TRANSCRIPT
![Page 1: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/1.jpg)
Maintainable Javascript编写高效可维护的JS代码
@HectorGuo
![Page 2: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/2.jpg)
可维护性
![Page 3: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/3.jpg)
Programs are meant to be read by humans and only incidentally for computers to execute
程序主要是给人读的,其次才是让计算机拿来
运行的
- H. Abelson and G. Sussman,
The Structure and Interpretation of Computer Programs
![Page 4: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/4.jpg)
代码规范的作用
帮助团队相互间更好地通过代码来交流
![Page 5: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/5.jpg)
![Page 6: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/6.jpg)
![Page 7: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/7.jpg)
![Page 8: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/8.jpg)
4空格缩进
Tab缩进
![Page 9: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/9.jpg)
if (JSV.typeOf(items) === "array") {
for (x = 0, xl = properties.length; x < xl; ++x) {
itemSchema = items[x] || additionalProperties;
if (itemSchema !== false) {
itemSchema.validate(properties[x], report, instance, schema, x);
} else {
report.addError(instance, schema, "additionalProperties",
"Additional items are not allowed", itemSchema);
}
}
}
![Page 10: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/10.jpg)
if (JSV.typeOf(items) === "array") {
for (x = 0, xl = properties.length; x < xl; ++x) {
itemSchema = items[x] || additionalProperties;
if (itemSchema !== false) {
itemSchema.validate(properties[x], report, instance, schema,
x);
} else {
report.addError(instance, schema, "additionalProperties",
"Additional items are not allowed", itemSchema);
}
}
}
https://github.com/jdc0589/JsFormat
![Page 11: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/11.jpg)
/**
* A low-level selection function that works with Sizzle's compiled
* selector functions
* @param {String|Function} selector A selector or a pre-compiled
* selector function built with Sizzle.compile
* @param {Element} context
* @param {Array} [results]
* @param {Array} [seed] A set of elements to match against
*/
select = Sizzle.select = function( selector, context, results, seed ) {
var i, tokens, token, type, find,
compiled = typeof selector === "function" && selector,
match = !seed && tokenize( (selector = compiled.selector ||
selector) );
...
每个方法都应该有详细的注释
![Page 12: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/12.jpg)
switch(mode) {
case 1: // to B
changeTo('B');
break;
case 2: // mix A and B
mixWith('A', 'B');
break;
case 3: // to A
changeTo('A');
break;
case 4: // mix B and C
mixWith('B', 'C')
break;
}
较难理解的代码
![Page 13: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/13.jpg)
命名
● 用更易理解的名字给变量(Variables)/函数(Functions)命名
○ 不要在意长度
https://www.allacronyms.com/
![Page 14: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/14.jpg)
命名
● 用更易理解的名字给变量(Variables)/函数(Functions)命名
○ 不要在意长度
● 变量应该是名词
● 函数应该以动词开头(如 getName() )○ 返回布尔类型的函数应该以“is”或“has”开头(如 isVaild(), hasItem() )
● 避免使用无意义的名字,如 foo,bar,temp
![Page 15: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/15.jpg)
if (wl && wl.length) {
for (var i = 0; i < wl.length; i++) {
p = wl[i];
if (s.hasOwnProperty(p)) {
r[p] = s[p];
}
}
}
![Page 16: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/16.jpg)
那些年,我们踩过的坑
Do we really know JS ?
![Page 17: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/17.jpg)
var result = 1;
result == 1 // true
result == '1' // true
不要过于相信 == 的兼容性
[] == []
var a = [0];
if ([0]) {
console.log(a == true);
} else {
console.log("go here");
}
![Page 18: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/18.jpg)
0.2 - 0.1 === 0.1
0.8 - 0.6 === 0.2
注意浮点数的运算
// true
// false
![Page 19: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/19.jpg)
<button id="btn1">Click btn1</button>
<button id="btn2">Click btn2</button>
<button id="btn3">Click btn3</button>
for(var i = 1; i <= 3; i++){
$.on('#btn'+i, 'click', function(){
console.log('You are clicking:', 'btn' + i);
});
}
执行循环时,时刻注意作用域
// You are clicking: btn4
![Page 20: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/20.jpg)
<button id="btn1">Click btn1</button>
<button id="btn2">Click btn2</button>
<button id="btn3">Click btn3</button>
for(var i = 1; i <= 3; i++){
$.on('#btn'+i, 'click', function(){
console.log('You are clicking:', 'btn' + i);
});
}
执行循环时,时刻注意作用域
// You are clicking: btn4
http://latentflip.com/loupe
![Page 21: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/21.jpg)
<button id="btn1">Click btn1</button>
<button id="btn2">Click btn2</button>
<button id="btn3">Click btn3</button>
var handleClick = function(id) {
$.on('#'+id, 'click', function(){
console.log('You are clicking:', id);
});
}
for(var i = 1; i <= 3; i++){
handleClick('btn'+i);
}
执行循环时,时刻注意作用域
![Page 23: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/23.jpg)
http://javascript-puzzlers.herokuapp.com/
![Page 24: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/24.jpg)
高效性
![Page 25: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/25.jpg)
编写高效的Javascript
● JSON比XML更快
● 高效地使用数组
● 尽量减少内存的占用
● 使用模版
![Page 26: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/26.jpg)
JSON比XML更快
● 使用原生的JSON方法
var data = {a:'this is json data'};
var jsonStr = JSON.stringify(data);
var jsonData = JSON.parse(jsonStr);
![Page 27: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/27.jpg)
数组内部运作
var a = new Array();
a[0] = 1;
a[1] = 2.3;
a[2] = 'str';
Type: Int Array
![Page 28: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/28.jpg)
数组内部运作
var a = new Array();
a[0] = 1;
a[1] = 2.3;
a[2] = 'str';
Type: Int Array
Type: Int Array 1
![Page 29: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/29.jpg)
数组内部运作
var a = new Array();
a[0] = 1;
a[1] = 2.3;
a[2] = 'str';
Type: Int Array
Type: Int Array 1
Type: Float Array 1 2.3
![Page 30: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/30.jpg)
数组内部运作
var a = new Array();
a[0] = 1;
a[1] = 2.3;
a[2] = 'str';
Type: Int Array
Type: Int Array 1
Type: Float Array 1 2.3
Type: Var Array 1 2.3 ‘str’
![Page 31: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/31.jpg)
给数组预分配长度
var a = new Array();
for (var i = 0; i < 100; i++){
a.push(i + 2);
}
SLOW
var a = new Array(100);
for (var i = 0; i < 100; i++){
a[i] = i + 2;
}
FAST
![Page 32: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/32.jpg)
混合类型的数组,预定义类型
var a = new Array(100);
for (var i = 0; i < a.length; i++){
a[i] = i;
}
...
// 数组操作
...
a[99] = 'str';
SLOW
var a = new Array(100);
a[0] = 'hint';
for (var i = 0; i < a.length; i++){
a[i] = i;
}
...
// 数组操作
...
a[99] = 'str';
FAST
![Page 33: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/33.jpg)
Delete会迫使引擎进行类型转变(变慢)
var a = new Array(100);
...
for (var i = 0; i < 100; i++){
a[i] = [1,2,3];
}
...
delete a[23];
SLOW
var a = new Array(100);
...
for (var i = 0; i < 100; i++){
a[i] = [1,2,3];
}
...
a[23] = 0;
FAST
![Page 34: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/34.jpg)
缓存数组长度,避免重复性地访问属性
var a = new Array(100);
var total = 0;
for (var item in a){
total += item;
}
a.forEach(function(item){
total += item;
});
for (var i = 0; i < a.length; i++){
total += a[i];
}
SLOW
var a = new Array(100);
var total = 0;
var cachedLength = a.length;
for (var i = 0; i < cachedLength; i++){
total += a[i];
}
FAST
https://jsperf.com/for-vs-foreach/37
![Page 35: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/35.jpg)
缓存数组长度,避免重复性地访问属性
var a = new Array(100);
var total = 0;
for (var item in a){
total += item;
}
a.forEach(function(item){
total += item;
});
for (var i = 0; i < a.length; i++){
total += a[i];
}
SLOW
var a = new Array(100);
var total = 0;
var cachedLength = a.length;
for (var i = 0; i < cachedLength; i++){
total += a[i];
}
FAST
![Page 36: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/36.jpg)
高效地使用数组(Best Practices)
● 给数组预分配长度
● 混合类型的数组,预定义类型
● Delete会迫使引擎进行类型转变(变慢)
● 缓存数组长度,避免重复性地访问属性
![Page 37: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/37.jpg)
哪些条件下,会影响内存的分配?
● 直接或间接地使用 new ○ 给对象预留内存
● Runtime下强制执行GC(垃圾回收)
● 每次定义/引用对象的时候
![Page 38: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/38.jpg)
什么是垃圾回收(Garbage Collection)?
● 当内存池已满,已经无法再给新对象分配内存时,会把之前使用过的且再也
没有被引用的对象清空,腾出内存供新对象使用。
![Page 39: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/39.jpg)
V8引擎垃圾回收(GC)机制
![Page 40: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/40.jpg)
V8引擎垃圾回收(GC)机制
● Young Generation有更高的被回收率
![Page 41: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/41.jpg)
V8引擎垃圾回收(GC)机制
To Space
From Space GC时使用
![Page 42: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/42.jpg)
V8引擎垃圾回收(GC)机制
To Space
From Space GC时使用
![Page 43: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/43.jpg)
V8引擎垃圾回收(GC)机制
未被分配的内存
From Space GC时使用
A
分配给对象A
![Page 44: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/44.jpg)
V8引擎垃圾回收(GC)机制
未被分配的内存
From Space GC时使用
A
分配给对象B
B
![Page 45: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/45.jpg)
V8引擎垃圾回收(GC)机制
未被分配的内存
From Space GC时使用
A
分配给对象C
B C
![Page 46: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/46.jpg)
V8引擎垃圾回收(GC)机制
未被分配的内存
From Space GC时使用
A B C D
不够用了!
![Page 47: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/47.jpg)
V8引擎垃圾回收(GC)机制
未被分配的内存
From Space GC时使用
A B C
GC开始!
程序暂停!
![Page 48: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/48.jpg)
V8引擎垃圾回收(GC)机制
To Space
未被分配的内存A B C
空间被交换!
![Page 49: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/49.jpg)
V8引擎垃圾回收(GC)机制
To Space
未被分配的内存A B C
正在使用/被引用的对象
![Page 50: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/50.jpg)
V8引擎垃圾回收(GC)机制
To Space
未被分配的内存A B C
正在使用/被引用的对象
![Page 51: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/51.jpg)
V8引擎垃圾回收(GC)机制
To Space
未被分配的内存A B C
正在使用/被引用的对象
复制
![Page 52: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/52.jpg)
V8引擎垃圾回收(GC)机制
未被分配的内存A B C
正在使用/被引用的对象
未被分配的内存A C
![Page 53: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/53.jpg)
V8引擎垃圾回收(GC)机制
From Space
未被分配的内存A C
![Page 54: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/54.jpg)
V8引擎垃圾回收(GC)机制
From Space
未被分配的内存A C D
分配给对象D
![Page 55: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/55.jpg)
每次垃圾回收都会暂停程序执行(卡顿/掉帧)
![Page 56: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/56.jpg)
内存泄漏
![Page 57: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/57.jpg)
内存泄漏
16ms!JS / CSS > 计算样式 > 布局 > 绘制 > 渲染层合并
![Page 58: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/58.jpg)
内存泄漏
![Page 59: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/59.jpg)
Slow Object vs Fast Object
function SlowPurchase(price) {
this.price = price;
this.total = 0;
this.x = 1;
}
var slow = new SlowPurchase(25);
// x没用,我删掉它
delete slow.x;
SLOW
function FastPurchase(price) {
this.price = price;
this.total = 0;
this.x = 1;
}
var fast = new FastPurchase(25);
FAST
![Page 60: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/60.jpg)
Slow Object会占用更多的内存
![Page 61: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/61.jpg)
DOM泄漏 var treeRef = $('#tree');
var leafRef = $('#leaf');
$('body').remove(treeRef);
// 此时 #tree 并没有被回收,
// 因为还有 treeRef 对象在引用
// 好,那就清空它
treeRef = null;
// 此时 #tree 还是没有被回收,
// 因为还有 leafRef 对象在间接引用
//(leafRef.parentNode)
leafRef = null;
// 好了,这次 #tree 可以被回收了
![Page 62: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/62.jpg)
“Premature optimization is the root of all evil”
- Donald Knuth
该优化的时候再优化
![Page 63: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/63.jpg)
内存监测工具
● performance.memory● 任务管理器
● Chrome Dev Tools
https://speakerdeck.com/addyosmani/javascript-memory-management-masterclass
![Page 64: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/64.jpg)
Memory-diagnosis
![Page 65: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/65.jpg)
https://www.smashingmagazine.com/2012/11/writing-fast-memory-efficient-javascript/
![Page 66: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/66.jpg)
模版的发展var data = {
"result": [
{
"title": "Strawberry"
},{
"title": "Vanilla"
},{
"title": "Ice"
}
]
};
var template = '<ul>';
for (var i = 0; i < data.result; i++) {
template += '<li id="item' + i +
'"><strong>Title:</strong>' +
data.result[i].title +
'</li>';
}
template += '</ul>';
$('#container').html(template);
字符串拼接
var data = {
"result": [
{
"title": "Strawberry"
},{
"title": "Vanilla"
},{
"title": "Ice"
}
]
};
<!-- html -->
<script type="text/mustache-template" id="mustache">
<ul>
{{#result}}
<li><strong>Title:</strong> {{title}}</li>
{{/result}}
</ul>
</script>
// Javascript
var template = $('#mustache').html()
var html = Mustache.to_html(template, data);
$('#container').html(html);
模版引擎
![Page 67: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/67.jpg)
数据绑定
![Page 68: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/68.jpg)
数据绑定(Vue.js)
// javascript
var data = {
"result": [
{
"title": "Strawberry"
},{
"title": "Vanilla"
},{
"title": "Ice"
}
]
};
var app = new Vue({
el: '#container',
data: data.result
});
<!-- html -->
<div id="container">
<ul>
<li v-for="item in data">
<strong>Title:</strong>
{{item.title}}
</li>
</ul>
</div>
![Page 69: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/69.jpg)
资源链接
JS性能比较:
https://jsperf.com/
V8引擎工作原理呈现工具:
http://mrale.ph/irhydra/2/
Event Loop原理呈现工具:
http://latentflip.com/loupe
Practical Performance Tips to Make Your HTML JavaScript Faster(微软教程):
https://www.youtube.com/watch?v=dk75fqFXwCE&list=PLMywOXqBTbMVgzv_oGGmdRTAPl2URqopE&index=8
Maintainable Javascript:https://www.youtube.com/watch?v=3MejbqcMC08&list=PLMywOXqBTbMVgzv_oGGmdRTAPl2URqopE&index=7
![Page 70: Maintainable Javascript](https://reader034.vdocuments.mx/reader034/viewer/2022052318/589b0e6d1a28abb85d8b69cb/html5/thumbnails/70.jpg)
Thanks!