最佳实践

  • 前言
  • 1 可维护性
  • 2 降低耦合
    • 2.1 将css从js中抽离
    • 2.2 模板文本写注释
    • 2.3 应用逻辑 / 事件处理程序分离
      • 2.3.1 概念
      • 2.3.2 Demo
    • 2.4 松散耦合原则
  • 3 编程实践
    • 3.1 不轻易修改对象
    • 3.2 避免全局量
    • 3.3 避免与null比较
    • 3.4 使用常量
  • 4 性能
    • 4.1 注意作用域
    • 4.2 避免不必要的属性查找
    • 4.3 优化循环
    • 4.4 最小化语句数
    • 4.5 优化DOM交互
    • 4.6 其他方法

前言

《Javascript高级程序设计》最佳实践

1 可维护性

  • 可理解性
  • 直观性
  • 可适应性
  • 可扩展性
  • 可调试性

总结

要做到可维护性、可读性强的代码,至少完成以下几点

  1. 函数注释(功能、参数、返回值)

    /*** 功能描述** @param {参数类型}参数名 参数说明 * @return {返回值类型} 返回值说明*/
    function fn(p1, p2) {// 参数类型:fn、Number、String、Boolean、Array、Object
    }
    
  2. 完成独立功能的大段代码,写功能注释

  3. 有意义的变量名、函数名,驼峰命名

2 降低耦合

耦合:两个模块之间的输入与输出的联系紧密,相互影响过多

代码耦合过紧会导致模块难以维护,修改一处的同时另一处也需要修改,降低了我们的开发效率。

2.1 将css从js中抽离

// bad
element.style.color = '#FFF';
element.style.width = '30px';
element.sytle.display = 'block';// good
.show { // csscolor: #FFF;width: 30px;display: block;
}
element.className += 'show';

2.2 模板文本写注释

需要JS动态生成的HTML内容,在父元素下写上模板的注释,易于后期维护

<ul id="mylist"><!-- <li><a href="1">First item</a></li> -->
</ul>

2.3 应用逻辑 / 事件处理程序分离

2.3.1 概念

什么是事件处理程序

事件就是用户或浏览器自身执行的某种动作。比如说 click,mouseover,都是事件的名字。而相应某个事件的函数就叫事件处理程序

什么是应用逻辑

被事件处理函数触发的一些动作,比如对元素的颜色、宽度等属性进行操作

为什么要分离

  • 方便更改触发事件的方式,比如从鼠标点击事件切换成按键事件
  • 可以直接测试应用逻辑代码,无需通过特定事件

2.3.2 Demo

按下Enter键,div移动

document.onkeydown = function handle1(event) {if (event.keyCode === 13) {div.style.left = 100 + 'px';div.style.top = 100 + 'px';}
}

一般这样写并没有什么问题

加功能:点击document对象,div移动到鼠标位置

document.onclick = function handle2(event) {div.style.left = event.clientX + 'px';div.style.top = event.clientY + 'px';
}

这样里面的代码就重复了

分析一下代码

// handle1是事件处理函数,判断是否是Enter键按下
document.onkeydown = function handle1(event) {if (event.keyCode === 13) {// 下面是应用逻辑的代码,控制div移动div.style.left = 100 + 'px';div.style.top = 100 + 'px';}
}

把应用逻辑的代码单独封装成一个函数

// 两个事件处理函数
document.onkeydown = function(event) {if (event.keyCode === 13) {moveFn(100, 100);}
};
document.onclick = function(event) {moveFn(event.clientX, event.clientY);
}
// 应用逻辑
function moveFn(x, y) {div.style.left = x + 'px';div.style.top = y + 'px';
}

注意:事件处理函数在传值给应用函数时,应该event中所需要的数据,不要传整个event对象。这样做的好处是表明了应用逻辑所需要的具体参数,也便于测试人员理解函数的功能。

2.4 松散耦合原则

  • 函数自身的event对象,不能传递给其他函数
  • 应用逻辑中的动作,应该可以在不执行任何事件处理的情况下进行
  • 任何事件处理程序都应该处理事件,任何将处理交给应用逻辑

3 编程实践

3.1 不轻易修改对象

除了你自己创建 / 维护的对象,原生对象、别人创建的对象一律不能修改

  1. 不能修改是指
  • 不为实例 / 原型添加属性
  • 不为实例 / 原型添加方法
  • 不重复定义已存在的方法
  1. 为什么不能修改别人的对象
  • 例如对原生的Array对象添加一个aaa方法,当将来某一天Array原生支持了aaa方法,这样你以前测试完善的代码就会出错
  1. 如果需要修改别人的对象
  • 继承该对象,对继承了的对象进行修改
  • 重新创建一个

3.2 避免全局量

let name = "yh";
function sayName() {console.log(name);
}

两个全局量,name & sayName()方法,name还覆盖了window.name的原生属性

let mySpace = {name: 'yh',sayname: function() {console.log(this.name);}
}

一个全局量,而且属性和方法有单独命名空间,不用担心和别人冲突

3.3 避免与null比较

如果看到与null比较的代码,用以下方法替换:

  • 如果值为引用类型,instanceof检查其构造函数
  • 如果值为基本类型,typeof检查类型
  • 如果想确定对象是否有某个方法,typeof 对象.方法名

3.4 使用常量

4 性能

4.1 注意作用域

  1. 避免全局查找
function updateUI() {let imgs = document.getElementsByTagName('img');for (let i = 0, len = imgs.length; i < len; i++) {imgs[i].title = document.title + 'image' + i;}let msg = document.getElementById('msg');msg.innerHTML = 'Update complete.';
}

这段代码里至少有三个document的查询,用一个变量将document对象存起来,就可以减少全局查找的次数,提高性能

function updateUI() {let doc = document;let imgs = doc.getElementsByTagName('img');for (let i = 0, len = imgs.length; i < len; i++) {imgs[i].title = doc.title + 'image' + i;}let msg = doc.getElementById('msg');msg.innerHTML = 'Update complete.';
}

一个函数中多次用到的全局变量存为局部变量总是没错的

  1. 避免with语句

4.2 避免不必要的属性查找

算法复杂度

标记 名称 操作
O(1) 常数 访问变量、访问数组的元素
O(log n) 对数 二分查找
O(n) 线性 遍历数组所有元素、访问对象上的属性
O(n2) 平方

对象的多重属性查找

let total = ele.style.width + ele.style.height;

查找了 2 + 2 次,效率低

let eleStyle = ele.style;
let total = eleStyle.width + eleStyle.height;

查找了 1 + 1 + 1 次,节省25%

在大的程序中进行这种改进,优化比较明显

数字化的数组位置 vs 命名属性(NodeList对象等),优先选择数组位置

4.3 优化循环

1. 减值迭代

大多数循环从0开始,增加到特定值结束。如果从特定值开始,减小到0结束,效率会更高

2. 简化终止条件

每次循环都会计算终止条件,终止条件越简单越好

// 增值迭代
for (let i = 0; i < arr.length; i++) {process(arr[i]);
}
// 减值迭代
for (let i = arr.length - 1; i >= 0; i--) {process(arr[i]);
}
// 每次循环时,少进行了一次 arr.length 的查找,提高了性能

3. 简化循环体

循环体执行次数是最多的,确保性能最优

4. 展开循环

Duff装置

5. 避免双重解释

eval()、function构造函数、setTimeout的第一个参数是字符串时会发生双重解释

eval("alert('Hello world!')");
let sayHi = new Function("alert(''Hello world!')");
setTimeout("alert('Hello world!')", 500);

一般都不会这么写

4.4 最小化语句数

1. 多个变量同时声明

// 不好
let num = 0;
let arr = [1, 2, 3];
let str = 'haha';
let obj = new Date();// 好
let num = 0,arr = [1, 2, 3],str = 'haha',obj = new Date();

2. 插入迭代值

例如:从arr中获取第i个值以后,让 i+1

// 不好
let name = arr[i];
i++;// 好
let name = arr[i++];

3. 使用数组和对象字面量

// 不好
let values = new Array();
values[0] = 123;
values[1] = 456;
values[2] = 789;let person = new Object();
person.name = 'yh';
person.age = 18;
person.sayName = function() {console.log(this.name);
};// 好
let values = [123, 456, 789];let person = {name: 'yh',age: 18,sayName: function() {console.log(this.name);}
}

4.5 优化DOM交互

1. 最小化DOM更新(createDocumentFragment 或 innerHTML)

let list = document.getElementById('myList'),item,i;for (i = 9; i >= 0; i--) {item = document.createElement('li');list.appendChild(item);item.appendChild(document.createTextNode('Item' + i));
}

上面这段代码添加了十个 li ,每次添加都有两个DOM更新(appendChild, createTextNode)

一共触发了20次DOM更新,非常消耗性能

// 优化
let list = document.getElementById('myList'),fragment = document.createDocumentFragment(),item,i;for (i = 9; i >= 0; i--) {item = document.createElement('li');fragment.appendChild(item);item.appendChild(document.createTextNode('Item' + i));
}

createDocumentFragment是DOM节点,但并不在DOM树中,向它添加元素不会引起页面重绘

2. 使用事件代理

尽可能将时间委托给祖先节点,减少页面上的事件处理程序

3. 减少HTMLCollection

什么情况下会得到HTMLCollection:

  • getElementsByTagName()
  • 获取元素的childNodes
  • 获取元素的attributes
  • 获取特定的元素集合时,如document.forms, document.images

如果要多次访问,可以用变量保存,减少访问次数

4.6 其他方法

1. 原生方法

原生方法是C/C++编写,比js快的多

多看看JS的原生方法,例如Math对象中的复杂数学运算

2. Switch语句

switch语句比if-else更快,

按照 最可能执行到的 → 最不可能执行到的 顺序进行排列

3. 位运算符较快

尽可能用位运算符替代,例如 取模、与、或 等运算

每次循环都会

JS最佳实践——红皮书相关推荐

  1. Vue.js最佳实践

    Vue.js最佳实践 第一招:化繁为简的Watchers 场景还原: created(){this.fetchPostList() },watch: {searchInputValue(){this. ...

  2. hook koa web 码云_Doodoo.js 发布 1.1.0,Koa.js+ Nuxt.js 最佳实践

    doodoo.js发布1.1.0 -- 中文最佳实践Node.js Web快速开发框架,支持Koa.js, Express.js中间件.包含多项功能改进,及Bug修复. 更新内容: 1.[新增]新增支 ...

  3. Vue.js 最佳实践清单,照亮你的开发之路

    作者简介: 李中凯老师,8年前端开发,前端负责人,擅长JavaScript/Vue. 公众号:1024译站 掘金文章专栏:https://juejin.im/user/57c7cb8a0a2b5800 ...

  4. 前端干货之JS最佳实践

    持续更新地址 https://wdd.js.org/js-best-pr... 1. 风格 一千个读者有一千个哈姆雷特,每个人都有自己的code style.我也曾为了要不要加分号给同事闹个脸红脖子粗 ...

  5. React.js 2016 最佳实践 徬梓阅读 1584收藏 71

    为什么80%的码农都做不了架构师?>>>    译者按:近几个月React相关话题依旧火热,相信越来越多的开发者在尝试这样一项技术,我们团队也在PC和移动端不断总结经验.2016来了 ...

  6. Node.js在携程的落地和最佳实践

    在携程 Node.js 应用根据用户群,主要分两个方向: DA(数据聚合服务)和 SSR(服务端渲染)是服务于外部用户的,目标是提升用户体验.当然,DA 和 SSR 同时也提升了开发效率,例如前端开发 ...

  7. docker 根据标签删除镜像_10 个 Docker 镜像安全最佳实践

    <Docker 镜像安全最佳实践速查表[1]>列举了 10 个诀窍和指南,确保更安全和更高质量的 Docker 镜像处理.此外,还可以检视有关 Docker 安全的新报告<Docke ...

  8. GitHub 一周热点速览:前后端最佳实践

    作者 | HelloGitHub-小鱼干 责编 | 王晓曼 来源 | HelloGitHub 最佳实践,又名 best-practices,是 GitHub 常见的项目名,也是本周 Trending ...

  9. dropzonejs vue 使用_dropzone.js使用实践

    官网地址:http://www.dropzonejs.com/ 一,它是什么: DropzoneJS is an open source library that provides drag'n'dr ...

最新文章

  1. JavaScript中整型数据使用
  2. php请求路由,PHP 新手入门指南 - 表单请求与路由
  3. Delphi中methodaddress的代码解析
  4. C#执行cmd [转载]
  5. 开源 java CMS - FreeCMS2.2 系统配置
  6. PYTHON 爬虫笔记十一:Scrapy框架的基本使用
  7. java对象引用传递和值传递的一些总结
  8. c语言考试常考大题,C语言题库经典题 考试常考题.doc
  9. 计算机思维和数学的那些事
  10. 一维非稳态常系数热传导方程(第一类边界条件)
  11. 3步上架iOS APP【2022最新教程】
  12. 动漫制作都用html5吗,怎么制作h5动画?
  13. dellr420部署os_dell r420 H310/H810阵列配置教程及常见问题
  14. 【解决方案】摄像机户外直播能在哪些地方运用?团建/项目启动会/户外婚礼等户外直播方案介绍
  15. ADS1220的几种应用介绍(含源码)
  16. Ubuntu安装搜狗输入法无论如何就是找不到的解决方法///Ubuntu怎么安装搜狗输入法///Ubuntu怎么输入中文///Ubuntu搜狗输入法怎么修改皮肤
  17. java基于springboot+Vue+nodejs的高校网上二手闲置跳蚤市场 element
  18. 情感驿站 | 为人处世的行为准则总结
  19. 咋连接到文件共享服务器,连接服务器文件共享
  20. java dto 实例_Spring Boot DTO示例:实体到DTO的转换

热门文章

  1. 学习安装unik环境——过程一
  2. 京东热-key-探测框架新版发布,单机-QPS-可达-35-万
  3. 吴恩达《深度学习》课程介绍
  4. 英语论文写作技巧-2
  5. ad19原理图标注_AD19如何让原理图的栅格显示更加清晰醒目
  6. 跑步装备品牌排行榜,跑步爱好者必备好物推荐
  7. 图片和字符串相互转换
  8. 如何打开电脑c语言窗口,C语言控制台窗口图形界面编程(五). -电脑资料
  9. 微信开发:解决IOS端下面的点击延迟问题
  10. 【重要通知】红帽RHCE7.0版本考试即将下线