SlideShare a Scribd company logo
Maintainable Javascript
编写高效可维护的JS代码
@HectorGuo
可维护性
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
代码规范的作用
帮助团队相互间更好地通过代码来交流
Maintainable Javascript
Maintainable Javascript
Maintainable Javascript
4空格缩进
Tab缩进
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);
}
}
}
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
/**
* 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) );
...
每个方法都应该有详细的注释
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;
}
较难理解的代码
命名
● 用更易理解的名字给变量(Variables)/函数(Functions)命名
○ 不要在意长度
https://www.allacronyms.com/
命名
● 用更易理解的名字给变量(Variables)/函数(Functions)命名
○ 不要在意长度
● 变量应该是名词
● 函数应该以动词开头(如 getName() )
○ 返回布尔类型的函数应该以“is”或“has”开头(如 isVaild(), hasItem() )
● 避免使用无意义的名字,如 foo,bar,temp
if (wl && wl.length) {
for (var i = 0; i < wl.length; i++) {
p = wl[i];
if (s.hasOwnProperty(p)) {
r[p] = s[p];
}
}
}
那些年,我们踩过的坑
Do we really know JS ?
var result = 1;
result == 1 // true
result == '1' // true
不要过于相信 == 的兼容性
[] == []
var a = [0];
if ([0]) {
console.log(a == true);
} else {
console.log("go here");
}
0.2 - 0.1 === 0.1
0.8 - 0.6 === 0.2
注意浮点数的运算
// true
// false
<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
<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
<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);
}
执行循环时,时刻注意作用域
http://ejohn.org/apps/learn/
http://javascript-puzzlers.herokuapp.com/
高效性
编写高效的Javascript
● JSON比XML更快
● 高效地使用数组
● 尽量减少内存的占用
● 使用模版
JSON比XML更快
● 使用原生的JSON方法
var data = {a:'this is json data'};
var jsonStr = JSON.stringify(data);
var jsonData = JSON.parse(jsonStr);
数组内部运作
var a = new Array();
a[0] = 1;
a[1] = 2.3;
a[2] = 'str';
Type: Int Array
数组内部运作
var a = new Array();
a[0] = 1;
a[1] = 2.3;
a[2] = 'str';
Type: Int Array
Type: Int Array 1
数组内部运作
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
数组内部运作
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’
给数组预分配长度
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
混合类型的数组,预定义类型
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
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
缓存数组长度,避免重复性地访问属性
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
缓存数组长度,避免重复性地访问属性
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
高效地使用数组(Best Practices)
● 给数组预分配长度
● 混合类型的数组,预定义类型
● Delete会迫使引擎进行类型转变(变慢)
● 缓存数组长度,避免重复性地访问属性
哪些条件下,会影响内存的分配?
● 直接或间接地使用 new
○ 给对象预留内存
● Runtime下强制执行GC(垃圾回收)
● 每次定义/引用对象的时候
什么是垃圾回收(Garbage Collection)?
● 当内存池已满,已经无法再给新对象分配内存时,会把之前使用过的且再也
没有被引用的对象清空,腾出内存供新对象使用。
V8引擎垃圾回收(GC)机制
V8引擎垃圾回收(GC)机制
● Young Generation有更高的被回收率
V8引擎垃圾回收(GC)机制
To Space
From Space GC时使用
V8引擎垃圾回收(GC)机制
To Space
From Space GC时使用
V8引擎垃圾回收(GC)机制
未被分配的内存
From Space GC时使用
A
分配给对象A
V8引擎垃圾回收(GC)机制
未被分配的内存
From Space GC时使用
A
分配给对象B
B
V8引擎垃圾回收(GC)机制
未被分配的内存
From Space GC时使用
A
分配给对象C
B C
V8引擎垃圾回收(GC)机制
未被分配的内存
From Space GC时使用
A B C D
不够用
了!
V8引擎垃圾回收(GC)机制
未被分配的内存
From Space GC时使用
A B C
GC开始!
程序暂停!
V8引擎垃圾回收(GC)机制
To Space
未被分配的内存A B C
空间被交换!
V8引擎垃圾回收(GC)机制
To Space
未被分配的内存A B C
正在使用/被引用的 对象
V8引擎垃圾回收(GC)机制
To Space
未被分配的内存A B C
正在使用/被引用的 对象
V8引擎垃圾回收(GC)机制
To Space
未被分配的内存A B C
正在使用/被引用的 对象
复制
V8引擎垃圾回收(GC)机制
未被分配的内存A B C
正在使用/被引用的 对象
未被分配的内存A C
V8引擎垃圾回收(GC)机制
From Space
未被分配的内存A C
V8引擎垃圾回收(GC)机制
From Space
未被分配的内存A C D
分配给对象D
每次垃圾回收都会
暂停程序执行
(卡顿/掉帧)
内存泄漏
内存泄漏
16ms!
JS / CSS > 计算样式 > 布局 > 绘制 > 渲染层合并
内存泄漏
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
Slow Object会占用更多的内存
DOM泄漏 var treeRef = $('#tree');
var leafRef = $('#leaf');
$('body').remove(treeRef);
// 此时 #tree 并没有被回收,
// 因为还有 treeRef 对象在引用
// 好,那就清空它
treeRef = null;
// 此时 #tree 还是没有被回收,
// 因为还有 leafRef 对象在间接引用
//(leafRef.parentNode)
leafRef = null;
// 好了,这次 #tree 可以被回收了
“Premature optimization is
the root of all evil”
- Donald Knuth
该优化的时候再优化
内存监测工具
● performance.memory
● 任务管理器
● Chrome Dev Tools
https://speakerdeck.com/addyosmani/javascript-memory-management-mast
erclass
Memory-diagnosis
https://www.smashingmagazine.com/2012/11/writing
-fast-memory-efficient-javascript/
模版的发展
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);
模版引擎
数据绑定
数据绑定(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>
资源链接
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
Thanks!

More Related Content

What's hot (20)

PPTX
SQL Server 2008 新增的 T-SQL 與資料型態
Chui-Wen Chiu
 
PDF
淘宝前台系统优化实践“吞吐量优化”-Qcon2011
Yiwei Ma
 
PDF
Mongo db introduction
Dai Qifeng
 
PPT
Mysql权限体系结构 by junsansi
Beenyoung Lee
 
DOCX
Memcached分享
princehaku
 
PPT
Mongo db技术分享
晓锋 陈
 
PPT
设计模式分享
michaelsh
 
PPT
手机腾讯网Js资源版本增量更新方案w3ctech
luyongfugx
 
PPTX
我对后端优化的一点想法.pptx
james tong
 
PDF
程式人雜誌 -- 2014 年11月號
鍾誠 陳鍾誠
 
PPTX
Glider
windyrobin
 
PPTX
Groovy Introduction for Java Programmer
Li Ding
 
PDF
【Maclean liu技术分享】深入理解oracle中mutex的内部原理
maclean liu
 
PDF
Ch7
Alisha Smile
 
PDF
JavaScript 快速複習 2017Q1
Sheng-Han Su
 
PDF
Recurrent Neural Network 遞迴式神經網路
Yen-lung Tsai
 
PDF
Sklearn basic - v01
ssuser5e7722
 
PPTX
R intro 20140716-basic
Kevin Chun-Hsien Hsu
 
PDF
Unity遊戲程式設計 - 2D運動與碰撞處理I
吳錫修 (ShyiShiou Wu)
 
PDF
Jscex:案例、经验、阻碍、展望
jeffz
 
SQL Server 2008 新增的 T-SQL 與資料型態
Chui-Wen Chiu
 
淘宝前台系统优化实践“吞吐量优化”-Qcon2011
Yiwei Ma
 
Mongo db introduction
Dai Qifeng
 
Mysql权限体系结构 by junsansi
Beenyoung Lee
 
Memcached分享
princehaku
 
Mongo db技术分享
晓锋 陈
 
设计模式分享
michaelsh
 
手机腾讯网Js资源版本增量更新方案w3ctech
luyongfugx
 
我对后端优化的一点想法.pptx
james tong
 
程式人雜誌 -- 2014 年11月號
鍾誠 陳鍾誠
 
Glider
windyrobin
 
Groovy Introduction for Java Programmer
Li Ding
 
【Maclean liu技术分享】深入理解oracle中mutex的内部原理
maclean liu
 
JavaScript 快速複習 2017Q1
Sheng-Han Su
 
Recurrent Neural Network 遞迴式神經網路
Yen-lung Tsai
 
Sklearn basic - v01
ssuser5e7722
 
R intro 20140716-basic
Kevin Chun-Hsien Hsu
 
Unity遊戲程式設計 - 2D運動與碰撞處理I
吳錫修 (ShyiShiou Wu)
 
Jscex:案例、经验、阻碍、展望
jeffz
 

Similar to Maintainable Javascript (20)

PPTX
从问题开始,谈前端架构
裕波 周
 
PPT
training and sharing about clean code
Chonpin HSU
 
PPT
人机对弈编程概述
勇浩 赖
 
PDF
Ch10 習題
hungchiayang1
 
PPTX
Yui3入门
cly84920
 
PDF
Arduino程式快速入門
吳錫修 (ShyiShiou Wu)
 
PPTX
20161209-Julia Taiwan first meetup-julia語言入門
岳華 杜
 
PDF
Python learn guide
robin yang
 
PPTX
Java script测试之js unit ut
fangdeng
 
PDF
JavaScript 教程
Bobby Zhou
 
PPTX
Chapter 5 array and struct
hhliu
 
PPTX
异步编程与浏览器执行模型
keelii
 
PPT
Sun java
softwaredesigner
 
KEY
Scala
popeast
 
PDF
Node.js开发体验
QLeelulu
 
PPTX
180518 ntut js and node
Peter Yi
 
PDF
Jni攻略之十一――启动虚拟机调用Java类
yiditushe
 
PDF
C语言学习100例实例程序
yiditushe
 
PDF
Java SE 7 技術手冊第五章草稿 - 何謂封裝?
Justin Lin
 
PPT
关于Js的跨域操作
王 承石
 
从问题开始,谈前端架构
裕波 周
 
training and sharing about clean code
Chonpin HSU
 
人机对弈编程概述
勇浩 赖
 
Ch10 習題
hungchiayang1
 
Yui3入门
cly84920
 
Arduino程式快速入門
吳錫修 (ShyiShiou Wu)
 
20161209-Julia Taiwan first meetup-julia語言入門
岳華 杜
 
Python learn guide
robin yang
 
Java script测试之js unit ut
fangdeng
 
JavaScript 教程
Bobby Zhou
 
Chapter 5 array and struct
hhliu
 
异步编程与浏览器执行模型
keelii
 
Scala
popeast
 
Node.js开发体验
QLeelulu
 
180518 ntut js and node
Peter Yi
 
Jni攻略之十一――启动虚拟机调用Java类
yiditushe
 
C语言学习100例实例程序
yiditushe
 
Java SE 7 技術手冊第五章草稿 - 何謂封裝?
Justin Lin
 
关于Js的跨域操作
王 承石
 
Ad

Maintainable Javascript