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 相关文章推荐
JavaScript-世界上误解最深的语言分析
Aug 12 Javascript
JavaScript的漂亮的代码片段
Jun 05 Javascript
javascript中实现兼容JAVA的hashCode算法代码分享
Aug 11 Javascript
JS实现点击按钮控制Div变宽、增高及调整背景色的方法
Aug 05 Javascript
AngularJS实用开发技巧(推荐)
Jul 13 Javascript
微信小程序 wx.uploadFile在安卓手机上面the same task is working问题解决
Dec 14 Javascript
微信端开发--登录小程序步骤
Jan 11 Javascript
简单实现js无缝滚动效果
Feb 05 Javascript
微信小程序 开发经验整理
Feb 15 Javascript
浅谈js使用in和hasOwnProperty获取对象属性的区别
Apr 27 Javascript
Angular2关于@angular/cli默认端口号配置的问题
Jul 15 Javascript
HTML+VUE分页实现炫酷物联网大屏功能
May 27 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
【动漫杂谈】关于《请在T台上微笑》
2020/03/03 日漫
PHP压缩html网页代码(清除空格,换行符,制表符,注释标记)
2012/04/02 PHP
php遍历目录与文件夹的多种方法详解
2013/11/14 PHP
php使用SAE原生Mail类实现各种类型邮件发送的方法
2016/10/10 PHP
php关联数组与索引数组及其显示方法
2018/03/12 PHP
JQuery在页面中添加和除移DOM示例代码
2013/06/24 Javascript
介绍JavaScript中Math.abs()方法的使用
2015/06/14 Javascript
浅谈setTimeout 与 setInterval
2015/06/23 Javascript
改变checkbox默认选中状态及取值的实现代码
2016/05/26 Javascript
浅谈DOM的操作以及性能优化问题-重绘重排
2017/01/08 Javascript
AngularJS ionic手势事件的使用总结
2017/08/09 Javascript
Angular学习笔记之集成三方UI框架、控件的示例
2018/03/23 Javascript
echarts实现地图定时切换散点与多图表级联联动详解
2018/08/07 Javascript
vue axios基于常见业务场景的二次封装的实现
2018/09/21 Javascript
javascript中this的用法实践分析
2019/07/29 Javascript
layui自定义验证,用ajax查询后台是否有重复数据,form.verify的例子
2019/09/06 Javascript
layui的select联动实现代码
2019/09/28 Javascript
浅谈vue的第一个commit分析
2020/06/08 Javascript
[01:08:57]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第二场
2014/05/24 DOTA
python测试mysql写入性能完整实例
2018/01/18 Python
Python查看微信撤回消息代码
2018/06/07 Python
python 对类的成员函数开启线程的方法
2019/01/22 Python
python 将字符串中的数字相加求和的实现
2019/07/18 Python
python manage.py runserver流程解析
2019/11/08 Python
Python基础之高级变量类型实例详解
2020/01/03 Python
Pytorch技巧:DataLoader的collate_fn参数使用详解
2020/01/08 Python
如何基于python3和Vue实现AES数据加密
2020/03/27 Python
使用Python对Dicom文件进行读取与写入的实现
2020/04/20 Python
佛罗里达州印第安河新鲜水果:Hale Groves
2017/02/20 全球购物
半年思想汇报
2013/12/30 职场文书
就业意向书范文
2014/04/01 职场文书
小学生读书活动总结
2014/06/30 职场文书
幼儿园法制宣传日活动总结
2014/11/01 职场文书
南阳市白酒市场的调查报告
2019/11/08 职场文书
Java反应式框架Reactor中的Mono和Flux
2021/07/25 Java/Android
Win11安全功能升级:内置防网络钓鱼功能
2022/04/08 数码科技