prototype Element学习笔记(篇一)


Posted in Javascript onOctober 26, 2008

先说一下Element对DOM扩展的技术思路,我也是看了一天的代码,这才有了点心得。
使用prototype,我们最常用的莫过于$('div1')之类的代码。从而获得扩展后的element对象,然后,我们就可以用它的各种扩展出来的方法了,如:
$('div1').addClassName('loading').show();
所以,我们研究Element的扩展正应当以此为入口。
function $(element) {
if (arguments.length > 1) {
for (var i = 0, elements = [], length = arguments.length; i < length; i++)
elements.push($(arguments[i]));
return elements;
}
if (Object.isString(element))
element = document.getElementById(element);
return Element.extend(element);
}
这个函数一个巧妙的递归就可以处理多个参数的情况,实在令我赞叹啊。代码中的关键是:Element.extend(element),在extend之前,element还仅仅是一个普通的DOM对象,extend之后就被扩展了,可见,秘密就在extend之中。
既然是Element.extend(element),那么,我们当然不能单独去研究extend,还是得先了解一下Element是何物。
(function() {

var element = this.Element;

this.Element = function(tagName, attributes) {

attributes = attributes || { };

tagName = tagName.toLowerCase();

var cache = Element.cache;

if (Prototype.Browser.IE && attributes.name) {

tagName = ' <' + tagName + ' name="' + attributes.name + '">';

delete attributes.name;

return Element.writeAttribute(document.createElement(tagName), attributes);

}

if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));

return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);

};

Object.extend(this.Element, element || { });
}).call(window);
这种代码比较有个性,基本结构是:(function(){……}).call(window);所以,看到这个结构,就要晓得,省略号部分出现的this都是指向window的。
var element=this.Element;这行不难理解,但是,关键是this.Element这时还没有被定义。后面则是定义一个类:window.Element类,它有两个参数:tagName、attributes。它的作用就是创建一个元素,并把一个纯洁的指定标签对应的DOM对象放入缓存。创建元素后,并且写入指定的属性值。这儿要提醒一下:
writeAttribute、readAttribute这两个函数功能显然,读、写属性,但是,它的代码并不简单啊,它的复杂性主要源于不同的浏览器中,读、写属性的方法的不同。
这是Element类的构造函数的定义,它之后的Element.cache = { };缓存,什么的缓存,不大好描述,各种标签的纯洁版DOM元素对象的缓存?这话说得太恶心了。后面紧跟着就是一个:Element.Methods={……},在这里,几乎定义了所有的扩展方法。这里的扩展方法都有一个特征,代码中没有一个用this的,都是老老实实传进去一个element引用。这是一个伏笔,为什么要定义成这样,是有原因的。且容后交待。
现在Element大概说了一下,就得讲一讲Element.extend了。
Element.extend = (function() {

if (Prototype.BrowserFeatures.SpecificElementExtensions)

return Prototype.K;

var Methods = { }, ByTag = Element.Methods.ByTag;

var extend = Object.extend(function(element) {

if (!element || element._extendedByPrototype ||

element.nodeType != 1 || element == window) return element;

var methods = Object.clone(Methods),

tagName = element.tagName, property, value;

// extend methods for specific tags

if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);

for (property in methods) {

value = methods[property];

if (Object.isFunction(value) && !(property in element))

element[property] = value.methodize();

}

element._extendedByPrototype = Prototype.emptyFunction;

return element;

}, {

  refresh: function() {

// extend methods for all tags (Safari doesn't need this)

if (!Prototype.BrowserFeatures.ElementExtensions) {

Object.extend(Methods, Element.Methods);

Object.extend(Methods, Element.Methods.Simulated);

}

}

});

extend.refresh();

return extend;
})();
第一行的原理我不大肯定,不说,下面的代码看似复杂,待我抽出它的大概结构来:
var extend=Object.extend(function(element){……},{refresh:function(){……}});
extend内,第一个函数作用是从XXXX.Methods中获取方法,并复制到本element中。这儿主要基于这样的考虑:
一、元素如果是一个Form,就得从Form.Methods取方法
二、元素如果是表单内的可输入元素,就得从Form.Element中取方法
三、所有元素都应当从Element.Methods中取得通用方法(后面的refresh所考虑的)。
也就是说,这儿要考虑多种情况,本来应当是个if语句的事,但是,这儿巧妙地设计了一个Element.Methods.ByTag。从而解决了这个问题。
if (Object.isFunction(value) && !(property in element))
element[property] = value.methodize();
如果Methods中的成员不是函数或者函数在element中已存在,则不会覆盖。这儿到了关键了,那个value.methodize(),这时,前面的伏笔生效了,methodize的作用就是把当前调用者传递进方法。且作为第一个参数传入。它的使用方法一般是:
obj.methodname=functionname.methodize();
这样,调用时,obj对象就会作为第一个参数传入functionsname这个函数。
到此为止,这个extend函数中的大概思路应当清晰了,现在还有一个问题没有清楚:根据元素的tagName来获得应当从哪个Methods获得扩展,那么,我们有必要了解一下ByTag的详情,查找一下,找到了:
Object.extend(Element.Methods.ByTag, {
"FORM": Object.clone(Form.Methods),
"INPUT": Object.clone(Form.Element.Methods),
"SELECT": Object.clone(Form.Element.Methods),
"TEXTAREA": Object.clone(Form.Element.Methods)
});
ok,差不多就这样了。

Javascript 相关文章推荐
jQuery验证Checkbox是否选中的代码 推荐
Sep 04 Javascript
js网页中的(运行代码)功能实现思路
Feb 04 Javascript
js setTimeout 参数传递使用介绍
Aug 13 Javascript
JS之Date对象和获取系统当前时间详解
Jan 13 Javascript
js捕捉键盘事件和按键键值的方法
Oct 10 Javascript
JS 全屏和退出全屏详解及实例代码
Nov 07 Javascript
AngularJS动态加载模块和依赖的方法分析
Nov 08 Javascript
js实现本地图片文件拖拽效果
Jul 18 Javascript
JS实现的图片选择顺序切换和循环切换功能示例【测试可用】
Dec 28 Javascript
微信小程序框架的页面布局代码
Aug 17 Javascript
vue实现禁止浏览器记住密码功能的示例代码
Feb 03 Vue.js
vue使用refs获取嵌套组件中的值过程
Mar 31 Vue.js
JS对URL字符串进行编码/解码分析
Oct 25 #Javascript
在html页面中包含共享页面的方法
Oct 24 #Javascript
IE浏览器兼容Firefox的JS脚本的代码
Oct 23 #Javascript
Javascript客户端将指定区域导出到Word、Excel的代码
Oct 22 #Javascript
checkbox 多选框 联动实现代码
Oct 22 #Javascript
javascript网页关闭时提醒效果脚本
Oct 22 #Javascript
javascript Select标记中options操作方法集合
Oct 22 #Javascript
You might like
JavaScript中的常见问题解决方法(乱码,IE缓存,代理)
2013/11/28 Javascript
js自定义鼠标右键的实现原理及源码
2014/06/23 Javascript
JS脚本根据手机浏览器类型跳转WAP手机网站(两种方式)
2015/08/04 Javascript
js实现显示当前状态的导航效果代码
2015/08/28 Javascript
jquery中checkbox使用方法简单实例演示
2015/11/24 Javascript
javascript 数组的定义和数组的长度
2016/06/07 Javascript
javascript实现table单元格点击展开隐藏效果(实例代码)
2017/04/10 Javascript
基于nodejs 的多页面爬虫实例代码
2017/05/31 NodeJs
详解vue模拟加载更多功能(数据追加)
2017/06/23 Javascript
微信小程序使用scroll-view标签实现自动滑动到底部功能的实例代码
2018/11/09 Javascript
微信小程序实现分享朋友圈的图片功能示例
2019/01/18 Javascript
vue实现随机验证码功能(完整代码)
2019/12/10 Javascript
JavaScript设计模式--桥梁模式引入操作实例分析
2020/05/23 Javascript
[56:21]LGD vs IG 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
使用setup.py安装python包和卸载python包的方法
2013/11/27 Python
Linux下用Python脚本监控目录变化代码分享
2015/05/21 Python
Python的时间模块datetime详解
2017/04/17 Python
python中numpy的矩阵、多维数组的用法
2018/02/05 Python
python 动态生成变量名以及动态获取变量的变量名方法
2019/01/20 Python
在linux下实现 python 监控usb设备信号
2019/07/03 Python
Python 获取项目根路径的代码
2019/09/27 Python
Python文件时间操作步骤代码详解
2020/04/13 Python
解决Keras自带数据集与预训练model下载太慢问题
2020/06/12 Python
opencv+pyQt5实现图片阈值编辑器/寻色块阈值利器
2020/11/13 Python
css3使网页、图片变成灰色兼容大多数浏览器
2014/07/02 HTML / CSS
Beauty Expert美国/加拿大:购买奢侈美容产品
2018/12/05 全球购物
新西兰便宜隐形眼镜购买网站:QUICKLENS New Zealand
2019/03/02 全球购物
SEPHORA丝芙兰德国官方购物网站:化妆品、护肤品和香水
2020/01/21 全球购物
Kingsoft金山公司C/C++笔试题
2016/05/10 面试题
销售实习自我鉴定
2013/12/07 职场文书
函授毕业自我鉴定
2013/12/19 职场文书
授权委托书公证
2014/09/14 职场文书
项目合作协议书
2014/09/23 职场文书
无罪辩护词范文
2015/05/21 职场文书
行政处罚听证告知书
2015/07/01 职场文书
使用PostGIS完成两点间的河流轨迹及流经长度的计算(推荐)
2022/01/18 PostgreSQL