您的位置:首页 > Web前端 > JavaScript

编写可维护的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