自由的脚本与重构的详细介绍

自由的脚本与重构的详细介绍

自由的脚本 与 重构

关键字:脚本、重构

想想,该写点什么像样的东西了,今天忽然在论坛里看到了一个帖子,给了一个答案,几看都不是很爽,于是就试着重构了几下,写写心得。

问题是这样的:http://community.csdn.net/Expert/topic/3178/3178153.xml?temp=.261532

求一个正则表达式,去除网页上nameyyyimg元素

我急用一个正则表达式,去除网页上nameyyyimg元素,其中yyy是一个变量,我想作成一个函数的形式

funciton qichuimg_name{

//在这里删除name属性为img_nameimg元素,注意img_name是一个字符串变量

}

关于为什么不用正则式的原因:

我知道,正则表达式的替换是非常方便的,但是对于HTML XML这类标记性文档,通过DOMAPI来访问应该比直接的字符串操作要正统,安全(就是说可以保证MLwell formed)。

var count = document.all.tags("IMG").length;

并且,看这里,这里已经提供了替换其他标签的能力。

在贴出代码以前先谈谈对重构的看法:重构是一个概念,跨越了语言的界限,JAVA需要重构,C#需要,C++需要,Scripting同样需要;重构是把垃圾变成艺术品一种手段,我们每天在制造各种各样的垃圾(也许你往往一蹴而就,不制造垃圾,但是这是理想),目的只是为了让程序能够工作,在这些垃圾中,我们挑选出有价值(最基本的价值,是否有人为这种改进付钱,既是价值,当然了,好像有点违背职业道德,但是往往我们需要面对现实)的东西,将它变成艺术品,有人说编程是艺术,但是注意,并不是所有的从事艺术的人都可以成为艺术家,都能够做出艺术品。

同样,由于我写的是自由的脚本,所以也说说脚本:我说的脚本指Javascript(对于其他脚本,可以称作脚本,自然要有比程序语言优越之处),脚本是一种自由的、灵活的、轻量级的编程语言,在javascript中很多特性都是JAVAC#等所不能及的,例如:动态的类型绑定(不是很确切,弱类型)、动态的添加成员等,同时脚本又具有基本的面向对象的特征,不多说了,看正题。

开始:提出解决思路

由于问题是按照元素的name来区分的,又要取得多个,所以不用document.all.yyy来取得collection了,因为如果这样的话需要判断nameyyy的数量如果只有一个,是不会形成collection的(IE和脚本在处理网页元素上的特性吧,算是一个脚本的魅力),判断过程会使程序变得难以理解,所以采用取得所有IMG元素的方法(并非只有一种方法),为了防止collection元素变动造成循环错误,先取得一个循环次数值,定义一个临时数组,存放所有名为 yyy IMG 的元素实例,遍历数组清除目标 IMG 元素,于是有了下面的代码。

var count = document.all.tags("IMG").length;

var tmparray = new Array();

for (var i=0; i<count; i++)

{

if (document.all.tags("IMG")[i].name == "yyy")

tmparray[tmparray.length] = document.all.tags("IMG")[i];

}

for (var i=0; i<tmparray.length; i++)

{

tmparray[i].outerHTML = "";

}

tmparray = null;

进行第一次重构:Extract Method

提取出函数,并将document.body动态(script的魅力)添加一个方法,方法所作操作为函数中内容,由于document.body已经生成实例了,所以没有必要对prototype操作,直接为实例添加就可以了。

注意:前后两个removeElementsWithName的意义是不同的,前一个表示了document.body的一个方法,后一个则是局部的一个函数。

//

// 第一次重构

//

document.body.removeElementsWithName = function removeElementsWithName( elementTag, elementName )

{

var count = document.all.tags(elementTag).length;

var tmparray = new Array();

for (var i=0; i<count; i++)

{

if (document.all.tags(elementTag)[i].name == elementName)

tmparray[tmparray.length] = document.all.tags(elementTag)[i];

}

for (var i=0; i<tmparray.length; i++)

{

tmparray[i].outerHTML = "";

}

tmparray = null;

}

document.body.removeElementsWithName( "IMG", "yyy" );

进行第二次重构:规范第一次重构提取后的代码

第一次着重于封装,将函数封装入对象(类),由于removeElementsByName(指后一个局部函数)现在是一个对象的方法,所以,对脚本内的访问已经没有任何意义,去掉名字,使用匿名函数(脚本的魅力)代替,并在函数内部使用this指代document,并把方法由document.body转移给document,使得方法更具有普遍性,并更改函数名WithBy

//

// 第二次重构

//

document.removeElementsByName = function ( elementTag, elementName )

{

var count = this.all.tags(elementTag).length;

var tmparray = new Array();

for (var i=0; i<count; i++)

{

if (this.all.tags(elementTag)[i].name == elementName)

tmparray[tmparray.length] = this.all.tags(elementTag)[i];

}

for (var i=0; i<tmparray.length; i++)

{

tmparray[i].outerHTML = "";

}

tmparray = null;

}

document.removeElementsByName( "IMG", "yyy" );

完成:实际并没完

至此两次重构已经完成,但是,可以看到,代码里依然有smells,比如removeElementsByName,这个长方法名,暂且放他一马吧。