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面向对象编程
Mar 04 Javascript
JS获取图片实际宽高及根据图片大小进行自适应
Aug 11 Javascript
简单漂亮的js弹窗可自由拖拽且兼容大部分浏览器
Oct 22 Javascript
JQuery文本改变触发事件如聚焦事件、失焦事件
Jan 15 Javascript
在父页面得到zTree已选中的节点的方法
Feb 12 Javascript
AngualrJS中的Directive制作一个菜单
Jan 26 Javascript
基于Node的React图片上传组件实现实例代码
May 10 Javascript
微信小程序上传文件到阿里OSS教程
May 20 Javascript
vue 中 elment-ui table合并上下两行相同数据单元格
Dec 26 Javascript
js将日期格式转换为YYYY-MM-DD HH:MM:SS
Sep 18 Javascript
小程序实现左滑删除的效果的实例代码
Oct 19 Javascript
详解微信小程序「渲染层网络层错误」的解决方法
Jan 06 Javascript
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
php dirname(__FILE__) 获取当前文件的绝对路径
2011/06/28 PHP
PHP7下协程的实现方法详解
2017/12/17 PHP
PHP使用Curl实现模拟登录及抓取数据功能示例
2018/04/27 PHP
两种WEB下的模态对话框 (asp.net或js的分别实现)
2009/12/02 Javascript
jquery下json数组的操作实现代码
2010/08/09 Javascript
js中将String转换为number以便比较
2014/07/08 Javascript
关闭页面时window.location事件未执行的原因分析及解决方案
2014/09/01 Javascript
Javascript获取表单名称(name)的方法
2015/04/02 Javascript
Bootstrap每天必学之滚动监听
2016/03/16 Javascript
深入理解JQuery中的事件与动画
2016/05/18 Javascript
JS实现隐藏同级元素后只显示JS文件内容的方法
2016/09/04 Javascript
Bootstrap响应式表格详解
2017/05/23 Javascript
js禁止Backspace键使浏览器后退的实现方法
2017/09/01 Javascript
极简主义法编写JavaScript类
2017/11/02 Javascript
原生js封装添加class,删除class的实例
2017/11/06 Javascript
Angular使用操作事件指令ng-click传多个参数示例
2018/03/27 Javascript
在小程序中使用Echart图表的示例代码
2018/08/02 Javascript
创建nuxt.js项目流程图解
2020/03/13 Javascript
Python的迭代器和生成器
2015/07/29 Python
两个命令把 Vim 打造成 Python IDE的方法
2016/03/20 Python
对python cv2批量灰度图片并保存的实例讲解
2018/11/09 Python
Python对象转换为json的方法步骤
2019/04/25 Python
Python 依赖库太多了该如何管理
2019/11/08 Python
Python的历史与优缺点整理
2020/05/26 Python
Python导入数值型Excel数据并生成矩阵操作
2020/06/09 Python
Jmeter调用Python脚本实现参数互相传递的实现
2021/01/22 Python
全球速卖通西班牙站:AliExpress西班牙
2017/10/30 全球购物
奥地利手表、香水、化妆品和珠宝购物网站:Brasty.at
2021/01/17 全球购物
安全生产管理合理化建议书
2014/03/12 职场文书
优秀本科毕业生自荐信
2014/07/04 职场文书
派出所班子党的群众路线对照检查材料思想汇报
2014/10/01 职场文书
办公室文员岗位职责
2015/02/04 职场文书
2016教师节问候语
2015/11/10 职场文书
自己搭建resnet18网络并加载torchvision自带权重的操作
2021/05/13 Python
PyTorch梯度裁剪避免训练loss nan的操作
2021/05/24 Python
基于Python实现nc批量转tif格式
2022/08/14 Python