$.widget("ui.dialog", {
options: {
autoOpen: true,...
},
_create: function(){ ... },
_init: function() {
if ( this.options.autoOpen ) {
this.open();
}
},
_setOption: function(key, value){ ... }
destroy: function(){ ... }
});
调用 $('#dlg').dialog(options)时, 实际执行的代码基本如下所示:
复制代码 代码如下:
this.each(function() {
var instance = $.data( this, "dialog" );
if ( instance ) {
instance.option( options || {} )._init();
} else {
$.data( this, "dialog", new $.ui.dialog( options, this ) );
}
}
可以看出, 第一次调用$('#dlg').dialog()函数时会创建窗口对象实例,并保存在data中, 此时会调用_create()和_init()函数, 而如果不是第一次调用, 则是在已经存在的对象实例上调用_init()方法. 多次调用$('#dlg').dialog()并不会创建多个实例.
13. browser sniffer vs. feature detection
浏览器嗅探(browser sniffer)曾经是很流行的技术, 比如早期的jQuery中
复制代码 代码如下:
jQuery.browser = {
version:(userAgent.match(/.+(?:rv|it|ra|ie)[/: ]([d.]+)/) || [0,'0'])[1],
safari:/webkit/.test(userAgent),
opera:/opera/.test(userAgent),
msie:/msie/.test(userAgent) && !/opera/.test(userAgent),
mozilla:/mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent)
};
在具体代码中可以针对不同的浏览器作出不同的处理
复制代码 代码如下:
if($.browser.msie) {
// do something
} else if($.browser.opera) {
// ...
}
但是随着浏览器市场的竞争升级, 竞争对手之间的互相模仿和伪装导致userAgent一片混乱, 加上Chrome的诞生, Safari的崛起, IE也开始加速向标准靠拢, sniffer已经起不到积极的作用. 特性检测(feature detection)作为更细粒度, 更具体的检测手段, 逐渐成为处理浏览器兼容性的主流方式.
复制代码 代码如下:
jQuery.support = {
// IE strips leading whitespace when .innerHTML is used
leadingWhitespace: ( div.firstChild.nodeType === 3 ),
...
}
只基于实际看见的,而不是曾经知道的, 这样更容易做到兼容未来.
14. Prototype vs. jQuery
prototype.js是一个立意高远的库, 它的目标是提供一种新的使用体验,参照Ruby从语言级别对javascript进行改造,并最终真的极大改变了js的面貌。$, extends, each, bind...这些耳熟能详的概念都是prototype.js引入到js领域的. 它肆无忌惮的在window全局名字空间中增加各种概念, 大有谁先占坑谁有理, 舍我其谁的气势. 而jQuery则扣扣索索, 抱着比较实用化的理念, 目标仅仅是write less, do more而已.
不过等待激进的理想主义者的命运往往都是壮志未酬身先死. 当prototype.js标志性的bind函数等被吸收到ECMAScript标准中时, 便注定了它的没落. 到处修改原生对象的prototype, 这是prototype.js的独门秘技, 也是它的死穴. 特别是当它试图模仿jQuery, 通过Element.extend(element)返回增强对象的时候, 算是彻底被jQuery给带到沟里去了. prototype.js与jQuery不同, 它总是直接修改原生对象的prototype, 而浏览器却是充满bug, 谎言, 历史包袱并夹杂着商业阴谋的领域, 在原生对象层面解决问题注定是一场悲剧. 性能问题, 名字冲突, 兼容性问题等等都是一个帮助库的能力所无法解决的. Prototype.js的2.0版本据说要做大的变革, 不知是要与历史决裂, 放弃兼容性, 还是继续挣扎, 在夹缝中求生.