编写可维护的javascript读后笔记(二)
2017-02-04 11:43
260 查看
编写可维护的javascript读后笔记(二)
本篇主要写第二部分 编程的实践,包括八章内容。第五章 UI层的松耦合
在web开发中,用户界面(User interface,UI)是有三个彼此隔离又相互作用的层定义的。(1) HTML用来定义页面的数据和语义
(2)CSS用来给页面添加样式 创建视觉特征
(3)javascript用来给页面添加行为的。
三个层面达到松耦合会给后续代码的维护带来很大的方便,可以做到更改其中一个不会影响到其他。而且对找问题也会分清界限。
1. 将javascript从CSS中抽离;
避免CSS表达式的使用。浏览器会以高频率重复计算CSS表达式,这严重影响了性能。而且对查找问题造成了一定的困扰,因为遇到javascript报错一般都会到js文件中查找问题。很少会想到去CSS文件中查找。
2.将CSS从Javascript中抽离
很多地方可能会需要在js代码中控制样式。用element.style=”“这种方式控制样式,这样就违背了松耦合的理念,可以使用控制类名的方式 将CSS从javascript中抽离开。
例如:
// 把需要控制的样式写在一个类名里 .red { color : white; } // 在js文件里 找到要添加该样式的相应元素,赋予.red类名 element.className+="red"; //原生写法 element.classList.add("red"); //HTML5的写法 $(element).addClass("red"); // Jquery中的写法
3.将javascript从HTML中抽离
(1)不好的写法
<button onclick="doSomething()" id="btn">Click Me</button>
这是DOM0级的事件写法 把javascript代码写在了HTML。不方便调试和维护。js代码应该都是在一个外部文件中,获取DOM节点 绑定事件。
(2)好的写法
// 定义一个专门的js文件 内容如下 然后用script标签 引入到HTML文件中 function doSomething() { } var btn=document.getElementById("btn"); btn.addEventListener("click",doSomething,false);
4.将HTML从javascript中抽离
有些地方会涉及到动态创建DOM节点插入到页面中,这有可能会涉及到在javascript中写HTML代码。
一般的解决方法是采用模板的方法 引入一个外部模板 动态填充内容。
第六章 避免使用全局变量
当脚本中的全局变量和全局函数越来越多时,发生命名冲突的概率也会越来越高。尤其是当多人团队中。全局变量有可能会重复 相互影响。1.对于函数来说,确保你的函数不会对全局变量有依赖,将增强你的代码的可测试性。
2.意外的全局变量
不小心省略var语句可能意味着在不知情的情况下修改某个已存在的全局变量,如name变量。因为name实际上是window的一个默认属性,window.name属性常用语框架(frame)和Iframe场景中。不小心改变name会影响到站点的链接导航。
function doSomething() { var a=10; name=a + 1; //不好的写法 意外的创建了全局变量 }
3.单全局变量方式
但全局变量方式已经在各种流行的javascript类库中广泛使用,如YUI、jQuery、Dojo等。所有的方法和属性都附着在定义的一个全局对象上。
4.模块
模块是一种基于单全局变量的扩充方法。
两种流行的类型是“YUI模块”和 “异步模块定义(简称:AMD Asynchronous Module Definition)”;
// AMD 模块语法 define("module-name",["dependency1","dependency2"], function(dependency1,dependency2) { //模块正文 var Books = {}; Book.info = { author : "nike", price : 10 } return Books; }); /* * 想要使用AMD模块 需要使用一个与之兼容的模块加载器,如requireJs。 * * requireJs模块加载器添加了一个全局函数require(),专门用来加载指定 * 的依赖和执行回调函数。 * * 调用require时会首先立即加载依赖,这些依赖都加载完成后会即可执行 * 回调函数。 * / require(["module-name"],function(books) { console.log(books.author); });
5.零全局变量
使用零全局变量的场景比较少,当你的脚步非常短且不需要和其他代码产生交互,可以考虑使用零全局变量的方式实现代码。其实现是依靠一个立即执行函数并传入window对象实现的。
(function(win) { "user strict"; //用严格模式来避免意外创建全局变量 var doc = win.document; // 定义其他的变量 // 其他的相关代码 }(window));
第七章 事件处理
事件处理是javascript的一个核心功能。怎么样使你的事件处理程序独立又可测试是一个需要注意地方。1.好的事件处理程序应该将应用逻辑从事件处理程序中抽离出来。
// 不好的写法 function handleClick(event) { var popup=document.getElementById("popup"); popup.style.left = event.clientX + "px"; popup.style.top = event.clientY + "px"; popup.className = "reveal"; } addEventListener(element, "click",handleClick); // 好的写法 var myHandleClick = { handleCLick : function(event) { this.showPopup(event); }, showPopup : function(event) { var popup = document.getElementById("popup"); popup.style.left = event.clientX + "px"; popup.style.top = event.clientY + "px"; popup.className = "reveal"; } }; addEventListener(element, "click", function(event) { myHandleClick.handleClick(event); });
2.好的事件处理程序不应该分发event对象。
上述案例event对象被分发了几次,从匿名事件处理函数传入了myHandleCLick.handleClick(),然后又传入了myHandleClick.showPopup()函数中,改进办法如下:
var myHandleClick = { handleCLick : function(event) { /** * 最好让事件处理程序成为接触event对象的唯一函数 * 所以关于阻止事件默认行为和阻止冒泡也在这里写 * / event.preventDefault(); event.stopPropagation(); // 应用逻辑函数的调用. this.showPopup(event.clientX,event.clientY); }, // showPopup函数只需要两个event对象的信息clientX和clientY. showPopup : function(x,y) { var popup = document.getElementById("popup"); popup.style.left = x + "px"; popup.style.top = y + "px"; popup.className = "reveal"; } }; addEventListener(element, "click",function(event) { myHandleClick.handleClick(event); });
第八章 避免“空”比较
变量和空(null)比较 并起不到什么作用。如:
// 下面这段代码显然是想判断一下a是否是数组,但是通过a与null的相比,并不能判断a是不是数组。因为字符串 数值等也不等于null.到了a.sort()时就会报错。 if(a !==null) { a.sort(); a.foreach(item) { //一些操作 } }
有一种例外就是需要用到跟null值比较:获取元素节点时:
// 如果dom不存在,通过document.getElementById()获得的值是null var ele = document.getElementById("id"); if(ele !== null) { // 一些操作 }
javascript提供了很多方法来检测变量的真实值。
1.对于字符串、数值、布尔值和undefined 这种简单类型的数据可以使用typeof运算符来检测
语法:typeof variable
(1)对于字符串,typeof 返回 “string”。
(2)对于数字,typeof 返回 “number”。
(3)对于布尔值,typeof 返回 “boolean”。
(4)对于undefined, typeof 返回 “undefined”。
2.检测引用值时,如Object,Array,Date,Error,RegExp等 typeof检测出来都是“object”,typeof 检测null时也是得出“object”。检测引用值类型最好的方法是用instanceof。
语法: value instanceof constructor
3.由于使用instanceof检测函数和数组 在遇到跨帧时(跨frame)会有些问题。所以函数和数组有其更好的检测方式
(1)function函数的检测方法 用typeof;
typeof 变量 === "function"; 然而在IE8及以下版本中,typeof检测DOM节点的方法(document.getElementById()等)会返回“object”,所以检测DOM节点方法可以用in 检测 如 “querySelectAll” in document;判断是否存在document.querySelectAll的方法。除了这种检测function最好用typeof.
(2)检测数组
Object.prototype.toString.call(value) === "[object Array]";
Array.isArray(value); IE9+ Firefox4+ Safari5+ Opera10.5+和Chrome都实现了这个检测数组的方法。其内部实现原理也是用了上面的toString方法。
4.检测属性
判断属性是否存在最好的方法是使用in运算符。In运算符仅仅会简单的判断属性是否存在,而不会去读属性的值。(包括原型链上的属性)
如果只想检测实例对象的某个属性是否存在,不查找原型链。则使用hasOwnProperty()方法
// 对于所有非DOM对象来说 object.hasOwnProperty(key); // 如果不确定是否为DOM对象 "hasOwnProperty" in object && object.hasOwnProperty(key);
第九章 将配置数据从代码中分离出来
数据是不应该影响指令的运行的。精心设计的应用会将关键数据从主要的源码中抽离出来的。1.抽离出配置数据的好处:
(1)以后需要更改数据时 不用再更改javascript代码了,安全性
(2)以后更改出现多次的值时,只需要更改一处即可 方便。
2.那么什么数据需要抽离出来呢?
(1) URL
(2)需要展现给用户的字符串
(3)重复的值
(4)设置(比如每页的配置项)
(5)任何可能发生变更的值
3.案例
抽离数据前的代码:
// 配置数据抽离前 数据跟代码混在一块 function validate(arg) { if(!arg) { alert("Invalid Value"); location.href = "/errors/invalid.php"; } } function toggleSelected(element) { if(hasClass(element,"selected")) { removeClass(element,"selected"); }else{ addClass(element,"selected"); } }
抽离数据后的代码
// 抽离数据后的代码 改变数据只需改变config对象值即可 var config = { MSG_INVALID : "Invalid Value", URL_INVALID : "/errors/invalid.php", CSS_SELECTED : "selected" } function validate(arg) { if(!arg) { alert(config.MSG_INVALID); location.href = config.URL_INVALID; } } function toggleSelected(element) { if(hasClass(element,config.CSS.SELECTED)) { removeClass(element,config.CSS.SELECTED); }else{ addClass(element,config.CSS.SELECTED); } }
相关文章推荐
- 编写可维护的JavaScript----笔记(二)
- 编写可维护的JavaScript学习笔记(一)
- 编写可维护的JavaScript----笔记(一)
- 编写可维护的JavaScript----笔记(三)
- 编写可维护的 JavaScript 笔记 (6 - 7 章)
- 编写可维护的 JavaScript 笔记 (1-3章)
- ↗☻【编写可维护的JavaScript #BOOK#】第3章 语句和表达式
- 深入理解javascript学习笔记(一) 编写高质量代码
- 如何编写可维护的面向对象JavaScript代码
- 如何编写可维护的面向对象JavaScript代码
- ↗☻【编写可维护的JavaScript #BOOK#】第1章 基本的格式化
- 编写高度可维护javascript代码的几点关键性原则
- 编写高度可维护javascript代码的几点关键性原则
- 《高效的JavaScript代码编写技巧》阅读笔记
- ↗☻【编写可维护的JavaScript #BOOK#】命名空间
- 如何编写可维护的JavaScript代码
- 深入理解javascript学习笔记(一) 编写高质量代码
- [转]如何编写可维护的面向对象JavaScript代码
- JavaScript探秘:编写可维护的代码的重要性
- JavaScript 学习笔记之二:编写自己的jQuery扩展分页插件(分享yQuery)