非侵入式JavaScript
非侵入式JavaScript[1]是一种将JavaScript从HTML结构抽离的设计概念,避免在HTML标签中夹杂一堆onchange、onclick等属性去挂载JavaScript事件,让HTML与JavaScript分离,依模型-视图-控制器的原则将功能权责清楚区分,使HTML也变得结构化容易阅读。这个名称并不是正式定义,它的基本原则包括:
- 将网页的行为层和表现层分离开[2];
- 是解决传统JavaScript编程问题(浏览器呈现不一致,缺乏扩展性)的最佳实践;
- 为可能不支持JavaScript高级特性的用户代理(通常是浏览器)提供渐进增强的支持[3]。
新范型
行为与文件标签的分离
传统上,JavaScript脚本通常与HTML文件的标签放在一起。例如,以下是在HTML中注册JavaScript事件进程的典型方法:
<input type="text" name="date" onchange="validateDate()"/>
HTML标签的目的通常是描述文件的排版结构,而不是网页操作的程序行为。两者的结合或许会对网站的可维护性产生负面影响,例如将呈现和内容相结合。在HTML中建立和引用的JavaScript脚本行为,例如在单一元素上设置多个不同事件的进程,或在多个元素上设置相同的事件进程,或者在使用事件委派时,结果可能难以使用和维护。
非侵入式方案是以编程方式注册需要的事件进程,而不是和网页元素内嵌在一起。不同于前述那样添加一个onchange
属性,相关的元素改用简单的标识,例如以class
,id
属性和它们值当成脚本参考的标识,或标记中一些其它的方式:
<input type="text" name="date" id="date"/>
当页面首次加载到浏览器中时,执行的脚本可以查找每个相关元素,并相对应地进行设置:
window.addEventListener("DOMContentLoaded",function() {
document.getElementById("date").addEventListener("change",function() {
//code
});
});
命名空间
非侵入式JavaScript应尽量减少将物件添加到运行环境,或全局的命名空间中。其它脚本有可能覆盖掉全局命名空间中,所建立的任何变量或函数;而这将导致发生不预期的结果时,却难以调试的困扰。JavaScript并没有内建明确的命名空间机制,但利用语言设计很容易可产生需求的效果。Flanagan建议以Java编程的开发风格,将开发人员自己的域名反转,作为全球独一的名前空间发布。
var org;
if (!org) {
org = {};
} else if (typeof org != 'object') {
throw new Error("org already exists and is not an object.");
}
if (!org.example) {
org.example = {};
} else if (typeof org.example != 'object') {
throw new Error("org.example already exists and is not an object.");
}
如在上面的org对象中,便可定义各种变量和函数。但还是建议在命名空间内,使用闭包进一步隔离,作为私有的变量和函数来使用,以共享接口回传每个函数作用的结果。上列代码可依照以下内容,改写为非侵入式:
org.example.Highlight = function() {
// Define private data and functions
var highlightId = 'x';
function setHighlight(color) {
document.getElementById(highlightId).style.color = color;
}
// Return public pointers to functions or properties
// that are to be public.
return {
goGreen: function() { setHighlight('green'); },
goBlue: function() { setHighlight('blue'); }
}
}(); // End closure definition and invoke it.
从任何其它的模块,可以调用这些共享接口的方法,如下列:
org.example.Highlight.goBlue();
var h = org.example.Highlight;
h.goGreen();
以这种方式,每个模块-开发人员的代码都包含在私有或唯一的命名空间中,并不会干扰或侵入任何其它代码。
最佳实务
非侵入式Javascript的本质是增加了分离的行为层概念,而且这范型的提倡者认同一些相关的原则,如下列:
- DOM脚本,即遵循W3C DOM和事件模型,并避免使用某一浏览器特定的扩展。
- 功能检测,即在使用特定功能之前先检查是否支持;对比相反于过去只检测客户端使用的浏览器(版本)。
- 更一般来说,JavaScript最佳实务通常与其它编程语言(例如封装和抽象层,避免全局变量,有意义的命名法约定,使用适当的设计模式式和系统测试)平行。这些原则对大规模软件工程开发非常重要,但过去的JavaScript设计过程中并不受重视。这些原则的采行,使JavaScript被认为是从“玩具”的脚本语言,转变为正规编程发展工具的重要组成。
参考文献
- ^ ASP.NET MVC 3高级编程. 清华大学出版社. 2012-06 [2016-06-30]. ISBN 978-7-302-28675-2. (原始内容存档于2017-10-14).
- ^ Keith, Jeremy. Behavioral Separation. 2006-06-20 [2016-09-13]. (原始内容存档于2012-04-01).
- ^ Olsson, Tommy. Graceful Degradation & Progressive Enhancement. 2007-02-06 [2016-09-13]. (原始内容存档于2017-07-18).