??xml version="1.0" encoding="utf-8" standalone="yes"?> public class PngDispatcherServlet extends HttpServlet { private static final long serialVersionUID = 6230740581031996144L; /** var WordApp = function(wordTplPath){ WordApp.prototype.closeApp = function(){ WordApp.prototype.replaceBookmark = function(strName,content,type){ WordApp.prototype.replaceBookmarkUsevo = function(voObj){ WordApp.prototype.replaceBookmarkUsepicvo = function(voObj){ WordApp.prototype.replaceBookmarkUsevolist = function(strName,voListObj){ WordApp.prototype.getSingleVo = function(formName,arrayObj){//W二个参数可以ؓI,不填旉认ؓ表单里的所有元?br />
var formObj = document.forms[formName]; WordApp.prototype.getVoList = function (formName,arrayObj){//表单名,属性数l?可以为空) function objToString(obj){ function getRootPath()
前提条gQ?br />
1.览器安全别降低,可以使用ActiveXObject控g?/p>
2.装有office word?br />
目前实现了替换单个书{,多行表格书签Q和囄Q基本上满需求。不q还有很多操作word的用方法不太清楚,|上大部分都使用的VBQ有不清楚的地方Q大家可以交?br />
下面说一下我的设计实现思\Q?br />
首先当然是定义word模板Q在需要替换的地方加上标签?菜单Q插入-书签Q输入属性名Q如year,date,pic1,voList{等?br />
打印面Q?br />
需要把打印的数据从后台取出Q以单个vo(一个对?Zl,或以voListQ对象的列表集合Qؓ一l?l织好页面上 再得到这些数据后q行替换?br />
数据l织形式如下Q?br />
<div id="export2word">
<form id="singleVo" name="singleVo">
<textarea name="jcxcrs" style="display:none"><c:out value="${zywstjfxbgVO.jcxcrs }"/></textarea>
<textarea name="xcjhl" style="display:none"><c:out value="${zywstjfxbgVO.xcjhl }"/></textarea>
<textarea name="tbjcxcrs" style="display:none"><c:out value="${tbjcxcrs }"/></textarea>
<textarea name="tptest" style="display:none">../zwgl/zw008-ZwMkjbxxCTRL-showWxytp.png?xh=3041</textarea>
</form>
<c:forEach var="mxvo" items="${jgList}" varStatus="s">
<form name="mxvoForm">
<!-- 注:q里的宽度设|ؓ表格单元格宽?厘米*100)-->
<textarea name="tbjcmcrs" style="width:349;display:none"><c:out value="${mxvo.tbjcmcrs }"/></textarea>
<textarea name="tbjcmcrsbl" style="width:270;display:none"><c:out value="${mxvo.tbjcmcrsbl }"/></textarea>
<textarea name="tbjcxcrs" style="width:477;display:none"><c:out value="${mxvo.tbjcxcrs}"/></textarea>
<textarea name="tbjcxcrsbl" style="display:none"><c:out value="${mxvo.tbjcxcrsbl }"/></textarea>
</form>
</c:forEach>
</div>
使用Q?br />
<input type="button" id="select2" name="select2" class="button" value="导出数据" onclick="print2doc();">
<script type="text/javascript" src="../public/scripts/export2word.js"></script>
<script type="text/javascript">
function print2doc(){
//参数为模?与页面的相对)路径
var word = new WordApp("test.doc");
//参数为form名,vo中需要添加的属性(为空时form里所有属性)
var vo = word.getSingleVo("singleVo",["jcxcrs","xcjhl","tbjcxcrs"]);
//var vo = word.getSingleVo("singleVo");
//l织成的囄vo
var tpvo = word.getSingleVo("singleVo",["tptest"]);
//参数?form名,需要添加的属性(序为生成表格列的顺序,为空时form里的所有属性和序Q?br />
var voList = word.getVoList("mxvoForm",["tbjcmcrs","tbjcmcrsbl","tbjczsrs"]);
//var voList = word.getVoList("mxvoForm");
//替换普通书{?br />
word.replaceBookmarkUsevo(vo);
//替换囄书签
word.replaceBookmarkUsepicvo(tpvo);
//替换书签jgListQ画格Ş成多行数据?br />
word.replaceBookmarkUsevolist("jgList",voList);
//文档可见
word.wordObj.visible=true;
//word.closeApp();
}
</script>
注意Q?br />
替换囄的值需要解释一下:
1.可以设ؓ相对本页面的路径?./zbgl/abc.png
2.如果是输出流Q则需要把h输出的url映射成以囄格式l尾的。如/.../abc.do?id=123换成/../abc.png?id=123
可以在web.xml里配一个servletQ如?.png的请求{?do的。如Q?br />
public void init() throws ServletException {
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
doGet(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws
ServletException, IOException {
//StringBuffer url = request.getRequestURL();
StringBuffer url = new StringBuffer(request.getRequestURI());
if(request.getQueryString() != null) {
url.append('?');
url.append(request.getQueryString());
}
String newUrl = url.toString().replaceAll(".png", ".do");
ServletContext sc = getServletContext();
RequestDispatcher rd = sc.getRequestDispatcher(newUrl); //定向的页?br />
rd.forward(request, response);
}
}
export2word.js代码Q?/p>
* <p> Title: 用word书签替换的方式将内容导出到word</p>
* <p> Description: **</p>
* <p> Copyright: Copyright (c) 2007-2010 </p>
* <p> Company: ** </p>
* @author zhu
* @version 1.0
*/
var baseVoListObj = function(){
this.volist = new Array();
this.cols = new Array();
this.widths = new Array();
}
var wordObj = new ActiveXObject("Word.Application");
if(wordObj==null){
alert( "不能创徏Word对象Q?);
}
wordObj.visible=false;
this.wordObj = wordObj;
this.docObj = this.wordObj.Documents.Open(getRootPath() + wordTplPath);
}
if (this.wordObj !=null){
this.wordObj.Quit();
}
}
if (this.wordObj.ActiveDocument.BookMarks.Exists(strName)) {
if (type != null && type == "pic") {//囄
var objDoc = this.wordObj.ActiveDocument.BookMarks(strName).Range.Select();
var objSelection = this.wordObj.Selection;
objSelection.TypeParagraph();
//alert(getRootPath()+content);
var objShape = objSelection.InlineShapes.AddPicture(getRootPath()+content);
}
else {
this.wordObj.ActiveDocument.BookMarks(strName).Range.Select();
this.wordObj.Application.selection.Text = content;
}
}else{
//alert("标签不存?);
}
}
if(typeof voObj != "object"){
alert("误入正的vo对象");
}else{
for(var i in voObj){
this.replaceBookmark(i,voObj[i]);
}
}
}
if(typeof voObj !="object"){
alert("误入正的vo对象");
}else{
for(var i in voObj){
this.replaceBookmark(i,voObj[i],"pic");
}
}
}
if(typeof voListObj != "object"){
alert("参数应ؓ数组cd");
}else{
var row = voListObj.volist.length;
var col = voListObj.cols.length;
var objDoc = this.wordObj.ActiveDocument.BookMarks(strName).Range;
var objTable = this.docObj.Tables.Add(objDoc,row,col) ;//插入表格
for (var i = 0; i < row; i++) {
for(var j=0; j<col; j++){
//todo 列表里面如果有图片类型不支持Q需要判?br />
objTable.Cell(i+1,j+1).Range.InsertAfter(voListObj.volist[i][voListObj.cols[j]]);
var width = voListObj.widths[j];
if(width.indexOf("px")!=-1){
objTable.Cell(i+1,j+1).Width = (width.substr(0,width.length-2)/100) * 28.35;//1厘米=28.35?br />
}
}
}
//objTable.AutoFormat(16);
objTable.Borders.InsideLineStyle = 1
objTable.Borders.OutsideLineStyle = 0;
}
}
if(formObj!=null){
if(arrayObj!=null){
if(arrayObj instanceof Array){
var vo = {};
for(var i=0;i<arrayObj.length;i++){
if(formObj.elements[arrayObj[i]]!= undefined ){
eval("vo." + arrayObj[i] + " = formObj.elements[arrayObj[i]].value;");
}
}
//alert(objToString(vo));
return vo;
}else{
alert("弟二个参数应为数l类?);
}
}else{
var vo = {};
for(var i=0;i<formObj.elements.length;i++){
eval("vo." + formObj.elements[i].name + " = formObj.elements[i].value;");
}
return vo;
}
}else{
alert("W一个参数表C的表单不存?);
return null;
}
}
//var formArray = document.forms[formName];
var formArray = document.getElementsByName(formName);
if (formArray != null) {
if (arrayObj instanceof Array) {
var voListObj = new baseVoListObj();
for(var i=0;i<formArray.length;i++){
var vo = {};
for(var j=0;j<arrayObj.length;j++){
if(formArray[i].elements[arrayObj[j]]!= undefined ){
eval("vo."+arrayObj[j]+" = formArray[i].elements[arrayObj[j]].value;");
if(i==0){//W一ơ的时候定义有效属性和宽度
voListObj.cols.push(arrayObj[j]);
voListObj.widths.push(formArray[i].elements[arrayObj[j]].style.width);
}
}
}
voListObj.volist.push(vo);
}
return voListObj;
}else{
var voListObj = new baseVoListObj();
for(var i=0;i<formArray.length;i++){
var vo = {};
for(var j=0;j<formArray[i].elements.length;j++){
eval("vo."+formArray[i].elements[j].name+" = formArray[i].elements[j].value;");
if(i==0){//W一ơ的时候定义宽?br />
voListObj.cols.push(formArray[i].elements[j].name);
voListObj.widths.push(formArray[i].elements[j].style.width);
}
}
voListObj.volist.push(vo);
}
return voListObj;
}
}else{
return null;
}
}
if(obj instanceof Array){
var str="";
for(var i=0;i<obj.length;i++){
str+="[";
for(var j in obj[i]){
str+=j+"="+obj[i][j]+" ";
}
str+="]\n";
}
return str;
}else if(obj instanceof Object){
var str="";
for(var i in obj){
str+=i+"="+obj[i]+" ";
}
return str;
}
}
{
var location=document.location;
if ("file:" == location.protocol) {
var str = location.toString();
return str.replace(str.split("/").reverse()[0], "");
}
var pathName=location.pathname.split("/");
return location.protocol+"http://"+location.host+"/"+pathName[1]+"/";
}
先说到这里吧Q以后有更好的再更新Q希望对大家有用?/p>
]]>
onerror事g处理函数是第一个用来协助javascript处理错误的机制。页面上出现异常Ӟerror事g便在window对象上触发?br>例如Q?br>
c?/td> | 发生原因 |
EvalError | 错误发生在eval()函数?/td> |
RangeError | 数字的D出javascript可表C的范围 |
ReferenceError | 使用了非法的引用 |
SyntaxError | 在eval()函数调用中发生了语法错误。其他的语法错误由浏览器报告Q无法通过try...catch语句处理 |
TypeError | 变量的类型不是预期所需?/td> |
URIError | 在encodeURI()或者decodeURI()函数中发生了错误 |
Ҏ?Ҏ | cd/q回cd | 说明 |
nodeName | String | 节点的名?Ҏ节点的类型而定?/td> |
nodeValue | String | 节点的?Ҏ节点的类型而定?/td> |
nodeType | Number | 节点的类型常量g一 |
ownerDocument | Document | 指向q个节点所属的文 |
firstChild | Node | 指向在childNodes列表中的W一个节?/td> |
lastChild | Node | 指向在childNodes列表中的最后一个节?/td> |
childNodes | NodeList | 所有子节点的列?/td> |
previousSibling | Node | 指向前一个兄弟节?如果q个节点是W一个兄弟节点,那么该gؓnull |
nextSibling | Node | 指向后一个兄弟节?如果q个节点是最后一个兄弟节点,那么该gؓnull |
hasChildNodes() | Boolean | 当childNodes包含一个或多个节点?q回?/td> |
attributes | NamedNodeMap | 包含了代表一个元素的Ҏ的Attr对象;仅用于Element节点 |
appendChild(node) | Node | noded到childNodes的末?/td> |
removeChild(node) | Node | 从childNodes中删除node |
replaceChild(newnode,oldnode) | Node | childNodes中的oldnode替换成newnode |
insertBefore(newnode,refnode) | Node | 在childNodes中的refnode之前插入newnodd |
Ҏ?Ҏ | 说明 |
caption | 指向<caption/>元素q将其放入表?/td> |
tBodies | <tbody/>元素的集?/td> |
tFoot | 指向<tfoot/>元素Q如果存在) |
tHead | 指向<thead/>元素Q如果存在) |
rows | 表格中所有行的集?/td> |
createTHead() | 创徏<thead/>元素q将其放入表?/td> |
createTFood() | 创徏<tfoot/>元素q将其放入表?/td> |
createCpation() | 创徏<caption/>元素q将其放入表?/td> |
deleteTHead() | 删除<thead/>元素 |
deleteTFood() | 删除<tfoot/>元素 |
deleteCaption() | 删除<caption/>元素 |
deleteRow(position) | 删除指定位置上的?/td> |
insertRow(position) | 在rows集合中的指定位置上插入一个新?/td> |
Ҏ?Ҏ | 说明 |
rows | <tbody/>中所有行的集?/td> |
deleteRow(position) | 删除指定位置上的?/td> |
insertRow(position) | 在rows集合中的指定位置上插入一个新?/td> |
Ҏ?Ҏ | 说明 |
cells | <tr/>元素中所有的单元格的集合 |
deleteCell(postion) | 删除l定位置上的单元?/td> |
insertCell(postion) | 在cells集合的给点位|上插入一个新的单元格 |
EventUtil.formatEvent = function (oEvent) {
if (isIE && isWin) {
oEvent.charCode = (oEvent.type == "keypress") ? oEvent.keyCode : 0;
oEvent.eventPhase = 2;
oEvent.isChar = (oEvent.charCode > 0);
oEvent.pageX = oEvent.clientX + document.body.scrollLeft;
oEvent.pageY = oEvent.clientY + document.body.scrollTop;
oEvent.preventDefault = function () {
this.returnValue = false;
};
if (oEvent.type == "mouseout") {
oEvent.relatedTarget = oEvent.toElement;
} else if (oEvent.type == "mouseover") {
oEvent.relatedTarget = oEvent.fromElement;
}
oEvent.stopPropagation = function () {
this.cancelBubble = true;
};
oEvent.target = oEvent.srcElement;
oEvent.time = (new Date).getTime();
}
return oEvent;
};
EventUtil.getEvent = function() {
if (window.event) {
return this.formatEvent(window.event);
} else {
return EventUtil.getEvent.caller.arguments[0];
}
};
function compareVersions(sVersion1, sVersion2) {
var aVersion1 = sVersion1.split(".");
var aVersion2 = sVersion2.split(".");
if (aVersion1.length > aVersion2.length) {
for (var i=0; i < aVersion1.length - aVersion2.length; i++) {
aVersion2.push("0");
}
} else if (aVersion1.length < aVersion2.length) {
for (var i=0; i < aVersion2.length - aVersion1.length; i++) {
aVersion1.push("0");
}
}
for (var i=0; i < aVersion1.length; i++) {
if (aVersion1[i] < aVersion2[i]) {
return -1;
} else if (aVersion1[i] > aVersion2[i]) {
return 1;
}
}
return 0;
}
var isOpera = sUserAgent.indexOf("Opera") > -1;
var isMinOpera4 = isMinOpera5 = isMinOpera6 = isMinOpera7 = isMinOpera7_5 = false;
if (isOpera) {
var fOperaVersion;
if(navigator.appName == "Opera") {
fOperaVersion = fAppVersion;
} else {
var reOperaVersion = new RegExp("Opera (\\d+\\.\\d+)");
reOperaVersion.test(sUserAgent);
fOperaVersion = parseFloat(RegExp["$1"]);
}
isMinOpera4 = fOperaVersion >= 4;
isMinOpera5 = fOperaVersion >= 5;
isMinOpera6 = fOperaVersion >= 6;
isMinOpera7 = fOperaVersion >= 7;
isMinOpera7_5 = fOperaVersion >= 7.5;
}
var isKHTML = sUserAgent.indexOf("KHTML") > -1
|| sUserAgent.indexOf("Konqueror") > -1
|| sUserAgent.indexOf("AppleWebKit") > -1;
var isMinSafari1 = isMinSafari1_2 = false;
var isMinKonq2_2 = isMinKonq3 = isMinKonq3_1 = isMinKonq3_2 = false;
if (isKHTML) {
isSafari = sUserAgent.indexOf("AppleWebKit") > -1;
isKonq = sUserAgent.indexOf("Konqueror") > -1;
if (isSafari) {
var reAppleWebKit = new RegExp("AppleWebKit\\/(\\d+(?:\\.\\d*)?)");
reAppleWebKit.test(sUserAgent);
var fAppleWebKitVersion = parseFloat(RegExp["$1"]);
isMinSafari1 = fAppleWebKitVersion >= 85;
isMinSafari1_2 = fAppleWebKitVersion >= 124;
} else if (isKonq) {
var reKonq = new RegExp("Konqueror\\/(\\d+(?:\\.\\d+(?:\\.\\d)?)?)");
reKonq.test(sUserAgent);
isMinKonq2_2 = compareVersions(RegExp["$1"], "2.2") >= 0;
isMinKonq3 = compareVersions(RegExp["$1"], "3.0") >= 0;
isMinKonq3_1 = compareVersions(RegExp["$1"], "3.1") >= 0;
isMinKonq3_2 = compareVersions(RegExp["$1"], "3.2") >= 0;
}
}
var isIE = sUserAgent.indexOf("compatible") > -1
&& sUserAgent.indexOf("MSIE") > -1
&& !isOpera;
var isMinIE4 = isMinIE5 = isMinIE5_5 = isMinIE6 = false;
if (isIE) {
var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
reIE.test(sUserAgent);
var fIEVersion = parseFloat(RegExp["$1"]);
isMinIE4 = fIEVersion >= 4;
isMinIE5 = fIEVersion >= 5;
isMinIE5_5 = fIEVersion >= 5.5;
isMinIE6 = fIEVersion >= 6.0;
}
var isMoz = sUserAgent.indexOf("Gecko") > -1
&& !isKHTML;
var isMinMoz1 = sMinMoz1_4 = isMinMoz1_5 = false;
if (isMoz) {
var reMoz = new RegExp("rv:(\\d+\\.\\d+(?:\\.\\d+)?)");
reMoz.test(sUserAgent);
isMinMoz1 = compareVersions(RegExp["$1"], "1.0") >= 0;
isMinMoz1_4 = compareVersions(RegExp["$1"], "1.4") >= 0;
isMinMoz1_5 = compareVersions(RegExp["$1"], "1.5") >= 0;
}
var isNS4 = !isIE && !isOpera && !isMoz && !isKHTML
&& (sUserAgent.indexOf("Mozilla") == 0)
&& (navigator.appName == "Netscape")
&& (fAppVersion >= 4.0 && fAppVersion < 5.0);
var isMinNS4 = isMinNS4_5 = isMinNS4_7 = isMinNS4_8 = false;
if (isNS4) {
isMinNS4 = true;
isMinNS4_5 = fAppVersion >= 4.5;
isMinNS4_7 = fAppVersion >= 4.7;
isMinNS4_8 = fAppVersion >= 4.8;
}
var isWin = (navigator.platform == "Win32") || (navigator.platform == "Windows");
var isMac = (navigator.platform == "Mac68K") || (navigator.platform == "MacPPC")
|| (navigator.platform == "Macintosh");
var isUnix = (navigator.platform == "X11") && !isWin && !isMac;
var isWin95 = isWin98 = isWinNT4 = isWin2K = isWinME = isWinXP = false;
var isMac68K = isMacPPC = false;
var isSunOS = isMinSunOS4 = isMinSunOS5 = isMinSunOS5_5 = false;
if (isWin) {
isWin95 = sUserAgent.indexOf("Win95") > -1
|| sUserAgent.indexOf("Windows 95") > -1;
isWin98 = sUserAgent.indexOf("Win98") > -1
|| sUserAgent.indexOf("Windows 98") > -1;
isWinME = sUserAgent.indexOf("Win 9x 4.90") > -1
|| sUserAgent.indexOf("Windows ME") > -1;
isWin2K = sUserAgent.indexOf("Windows NT 5.0") > -1
|| sUserAgent.indexOf("Windows 2000") > -1;
isWinXP = sUserAgent.indexOf("Windows NT 5.1") > -1
|| sUserAgent.indexOf("Windows XP") > -1;
isWinNT4 = sUserAgent.indexOf("WinNT") > -1
|| sUserAgent.indexOf("Windows NT") > -1
|| sUserAgent.indexOf("WinNT4.0") > -1
|| sUserAgent.indexOf("Windows NT 4.0") > -1
&& (!isWinME && !isWin2K && !isWinXP);
}
if (isMac) {
isMac68K = sUserAgent.indexOf("Mac_68000") > -1
|| sUserAgent.indexOf("68K") > -1;
isMacPPC = sUserAgent.indexOf("Mac_PowerPC") > -1
|| sUserAgent.indexOf("PPC") > -1;
}
if (isUnix) {
isSunOS = sUserAgent.indexOf("SunOS") > -1;
if (isSunOS) {
var reSunOS = new RegExp("SunOS (\\d+\\.\\d+(?:\\.\\d+)?)");
reSunOS.test(sUserAgent);
isMinSunOS4 = compareVersions(RegExp["$1"], "4.0") >= 0;
isMinSunOS5 = compareVersions(RegExp["$1"], "5.0") >= 0;
isMinSunOS5_5 = compareVersions(RegExp["$1"], "5.5") >= 0;
}
}
字符 | 描述 |
\t | 制表W?/td> |
\n | 换行W?/td> |
\r | 回RW?/td> |
\f | 换页W?/td> |
\a | alert字符 |
\e | escape字符 |
\cx | 与X相对应的控制字符 |
\b | 回退字符 |
\v | 垂直制表W?/td> |
\0 | I字W?/td> |
代码 | {同?/td> | 匚w |
. | [^\n\r] | 除了换行和回车之外的L字符 |
\d | [0-9] | 数字 |
\D | [^0-9] | 非数字字W?/td> |
\s | [\t\n\x0B\f\r] | I白字符 |
\S | [^\t\n\x0B\f\r] | 非空白字W?/td> |
\w | [a-zA-Z_0-9] | 单词字符Q所有字母,所有的数字和下划线Q?/td> |
\W | [^a-zA-Z_0-9] | 非单词字W?/td> |
代码 | 描述 |
? | 出现零次或一?/td> |
* | 出现零次或多?/td> |
+ | 出现一ơ或多次Q至出Cơ) |
{n} | 一定出现n?/td> |
{n,m} | 臛_出现nơ但不超qm?/td> |
{n,} | 臛_出现n?/td> |
贪婪 | 惰?/td> | 支配 | 描述 |
? | ?? | ?+ | 零次或一ơ出?/td> |
* | *? | *+ | 零次或多ơ出?/td> |
+ | +? | ++ | 一ơ或多次出现 |
{n} | {n}? | {n}+ | 恰好nơ出?/td> |
{n,m} | {n,m}? | {n,m}+ | 臛_nơ至多mơ出?/td> |
{n,} | {n,}? | {n,}+ | 臛_nơ出?/td> |
览器对支配量词的支持还很不完善。IE和Opera不支持,Mozilla支配量词看作是贪婪的?br>
二、复杂模?br>1.分组
分组是通过一pd括号包围一pd字符、字W类以及量词来用的?br>/dogdog/可用分l来重写?(dog){2}/
/([bd]ad?)*/匚w零个和多?ba","da","bad"?dad"
/(mom( and dad)?)/匚w"mom" 或 "mom and dad"
2.反向引用
在表辑ּ计算完成后还可以怎样利用分组Q每个分l都被存攑֜一个特D的地方以备来使用。这些存储在分组中的Ҏ|我们UC为反向引用?br>反向引用是按照从左到右遇到的左括号字W的序q行创徏和编L。例如表辑ּ(A?(B?(C?)))生编号从1-3的三个反向引?br>(1).(A?(B?(C?)))
(2).(B?(C?))
(3).(C?)
反向引用可以有几U不同的使用Ҏ?br>首先Q用正则表辑ּ对象的test(),match()或search()Ҏ后,反向引用的值可以从RegExp构造函C获得。例
var sToMatch = "#123456789";
var reNumbers = /#(\d+)/;
reNumbers.test(sToMatch);
alert(RegExp.$1); //outputs "123456789"
然后Q还可以直接在定义分l的表达式中包含反向引用Q这可以通过使用Ҏ转义序列如\1,\2{等实现
例如
var sToMatch = "dogdog";
var reDogDog = /(dog)\1/;
alert(reDogDog.test(sToMatch)); //outputs "true"
正则表达式reDogDog首先创徏单词dog的组Q然后又被特D{义序列\1引用Q得这个正则表辑ּ{同?dogdog/
W三Q反向引用可以用在String对象的replace()Ҏ中,q通过使用Ҏ字符序列$1,$2{等来实现。例?br>var sToChange = "1234 5678";
var reMatch = /(\d{4}) (\d{4})/
var sNew = sToChange.replace(reMatch,"$2 $1");
alert(sNew); //outputs "5678 1234"
3.候?br>有时候要构徏一个能够正匹配想得到所有可能性的模式是十分困隄。如果要对同一个表辑ּ同时匚w"red"?break"时要怎么做呢Q这些单词完全没有相同的字符Q这样就要写两个不同的正则表辑ּQƈ分别对两个字W串q行匚wQ像q样Q?br>var sToMatch1 = "red";
var sToMatch2 = "black";
var reRed = /red/;
var reBlack = /black/;
alert(reRed.test(sToMatch1)||reBlack.test(sToMatch1)); //outputs "true"
alert(reRed.test(sToMatch2)||reBlack.test(sToMatch2)); //outputs "true"
q完成了dQ但是十分冗ѝ还有另一U方式就是用正则表辑ּ的候选操作符。例Q?br>var sToMatch1 = "red";
var sToMatch2 = "black";
var reRedOrBlack = /(red|black)/;
alert(reRedOrBlack.test(sToMatch1)); //outputs "true"
alert(reRedOrBlack.test(sToMatch2)); //outputs "true"
4.非捕h分l?br>创徏反向引用的分l,我们UC为捕h分l。同时还有一U非捕获性分l,它不会创建反向引用。在较长的正则表辑ּ中,存储反向引用会降低匹配速度?br>如果要创Z个非捕获性分l,只要在左括号的后面加上一个问号和一个紧跟的冒号Q?br>var sToMatch = "#123456789";
var reNumbers = /#(?:\d+)/;
reNumbers.test(sToMatch);
alert(RegExp.$1); //outputs ""
5.前瞻
有时候,可能希望Q当某个特定的字W分l出现在另一个字W串之前Ӟ才去捕获它。如果?#8220;前瞻”可以让q个q程变得十分单?br>前瞻Q告诉正则表辑ּq算器向前看一些字W而不Ud其位|。同样存在正向前d负向前瞻。正向前L查的是接下来出现的是不是某个特定字符集。而负向前d是检查接下来的不应该出现的特定字W集?br>创徏正向前瞻要将模式攑֜(?=?之间。注意这不是分组Q虽然它也用到括受?br>var sToMatch1 = "bedroom";
var sToMatch2 = "bedding";
var reBed = /(bed(?=room)/;
alert(reBed.test(sToMatch1)); //outputs "true"
alert(RegExp.$1); //outputs "bed"
alert(reBed.test(sToMatch2)); //outputs "false"
负向前瞻Q则要将模式攑֜(?!?之间?br>var sToMatch1 = "bedroom";
var sToMatch2 = "bedding";
var reBed = /(bed(?!room)/;
alert(reBed.test(sToMatch1)); //outputs "false"
alert(reBed.test(sToMatch2)); //outputs "true"
alert(RegExp.$1); //outputs "bed"
6.边界
边界 用于正则表达式中表示模式的位|。下表列Z几种可能的边?br>
边界 | 描述 |
^ | 行开?/td> |
$ | 行结?/td> |
\b | 单词的边?/td> |
\B | 非单词的边界 |
长名 | 短名 | 描述 |
input | $_ | 最后用于匹配的字符?传递给exec()或test()的字W串) |
lastMatch | $& | 最后匹配的字符 |
lastParen | $+ | 最后匹配的分组 |
leftContext | $` | 在上ơ匹配的前面的子?/td> |
multiline | $* | 用于指定是否所有的表达式都使用多行模式的布?/td> |
rightContext | $' | 在上ơ匹配之后的子串 |
function ClassB(sColor, sName) {
this.newMethod = ClassA;
this.newMethod(sColor);
delete this.newMethod;
this.name = sName;
this.sayName = function () {
alert(this.name);
};
}
var objA = new ClassA("red");
var objB = new ClassB("blue", "Nicholas");
objA.sayColor();
objB.sayColor();
objB.sayName();
所有新的属性和新的Ҏ都必d删除了新Ҏ的代码行后定义。否则,可能会覆盖超cȝ相关属性和Ҏ?br>对象冒充可以支持多ѝ?br>function ClassZ(){
this.newMethod = ClassX;
this.newMethod(sColor);
delete this.newMethod;
this.newMethod = ClassY;
this.newMethod(sColor);
delete this.newMethod;
}
q里存在一个弊端,如果ClassX和ClassYh相同的属性或ҎQClassYh高优先Q因为承的是最后的cR?br>
2.call()Ҏ
call()Ҏ是与l典的对象冒充方法最怼的方法,它的W一个参数用作this的对象,其他参数都直接传递函数自w?br>function ClassA(sColor) {
this.color = sColor;
this.sayColor = function () {
alert(this.color);
};
}
function ClassB(sColor, sName) {
//this.newMethod = ClassA;
//this.newMethod(color);
//delete this.newMethod;
ClassA.call(this, sColor);
this.name = sName;
this.sayName = function () {
alert(this.name);
};
}
var objA = new ClassA("red");
var objB = new ClassB("blue", "Nicholas");
objA.sayColor();
objB.sayColor();
objB.sayName();
3.apply()Ҏ
apply()Ҏ有两个参敎ͼ用作this的对象和要传递参数的数组。例如:
function ClassA(sColor) {
this.color = sColor;
this.sayColor = function () {
alert(this.color);
};
}
function ClassB(sColor, sName) {
//this.newMethod = ClassA;
//this.newMethod(color);
//delete this.newMethod;
ClassA.apply(this, arguments);
this.name = sName;
this.sayName = function () {
alert(this.name);
};
}
var objA = new ClassA("red");
var objB = new ClassB("blue", "Nicholas");
objA.sayColor();
objB.sayColor();
objB.sayName();
当然Q只有超cM的参数顺序与子类中的参数序完全一致时才可以传递参数对象。如果不是,必dZ个单独的数组Q按照正的序攄参数。此外,q可以用call()Ҏ?br>
4.原型?br>function ClassA() {
}
ClassA.prototype.color = "red";
ClassA.prototype.sayColor = function () {
alert(this.color);
};
function ClassB() {
}
ClassB.prototype = new ClassA();
ClassB.prototype.name = "";
ClassB.prototype.sayName = function () {
alert(this.name);
};
var objA = new ClassA();
var objB = new ClassB();
objA.color = "red";
objB.color = "blue";
objB.name = "Nicholas";
objA.sayColor();
objB.sayColor();
objB.sayName();
注意Q调用ClassA的构造函数时Q没有给它传递参数。这在原型链中是标准做法。要保构造函数没有Q何参数?br>原型铄弊端是不支持多重l承?br>
5.混合方式
与创建对象最好方式相|用对象冒充承构造函数的属性,用原型链l承prototype对象的方法?br>function ClassA(sColor) {
this.color = sColor;
}
ClassA.prototype.sayColor = function () {
alert(this.color);
};
function ClassB(sColor, sName) {
ClassA.call(this, sColor);
this.name = sName;
}
ClassB.prototype = new ClassA();
ClassB.prototype.sayName = function () {
alert(this.name);
};
var objA = new ClassA("red");
var objB = new ClassB("blue", "Nicholas");
objA.sayColor();
objB.sayColor();
objB.sayName();
var car1 = createCar("red", 4, 23);
var car2 = createCar("blue", 3, 25);
car1.showColor(); //outputs "red"
car2.showColor(); //outputs "blue"
q个例子中,每次调用函数createCar()Q都要创建新函数showColor()Q意味着每个对象都有自己的showColor()版本Q事实上Q每个对象都׃n了同一个函数?br>有些开发者在工厂函数外定义对象的ҎQ然后通过属性指向该ҎQ从而避开q个问题?br>function showColor(){
alert(this.color);
}
function createCar(color, doors, mpg) {
var tempcar = new Object;
tempcar.color = color;
tempcar.doors = doors;
tempcar.mpg = mpg;
tempcar.showColor = showColor;
return tempcar;
}
var car1 = createCar("red", 4, 23);
var car2 = createCar("blue", 3, 25);
car1.showColor(); //outputs "red"
car2.showColor(); //outputs "blue"
从功能上Ԍq样解决了重复创建函数对象的问题Q但该函数看h不像对象的方法。所有这些问题引发了开发者定义的构造函数的出现?br>
2.构造函数方?br>function Car(sColor, iDoors, iMpg) {
this.color = sColor;
this.doors = iDoors;
this.mpg = iMpg;
this.showColor = function () {
alert(this.color)
};
}
var oCar1 = new Car("red", 4, 23);
var oCar2 = new Car("blue", 3, 25);
oCar1.showColor(); //outputs "red"
oCar2.showColor(); //outputs "blue"
像工厂函数Q构造函C重复生成函数Qؓ每个对象都创建独立的函数版本。不q,也可以用外部函数重写构造函敎ͼ同样Q这么做语义上无M意义?br>
3.原型方式
function Car(){
}
Car.prototype.color = "red";
Car.prototype.doors= 4;
Car.prototype.mpg= 23;
Car.prototype.showColor = function(){
alert(this.color);
}
var oCar1 = new Car();
var oCar2 = new Car();
它解决了前面两种方式存在的两个问题。但q不h意。首先,q个构造函数没有参数。用原型方式时Q不能通过构造函C递参数初始化属性的|q点很o厌,但还没完Q真正的问题出现在属性指向的是对象,而不是函数时。考虑下面的例子:
function Car(){
}
Car.prototype.color = "red";
Car.prototype.doors= 4;
Car.prototype.mpg= 23;
Car.prototype.drivers = new Array("Mike","Sue");
Car.prototype.showColor = function(){
alert(this.color);
}
var oCar1 = new Car();
var oCar2 = new Car();
oCar1.drivers.push("Matt");
alert(oCar1.drivers); //outputs "Mike,Sue,Matt"
alert(oCar2.drivers); //outputs "Mike,Sue,Matt"
4.混合的构造函?原型方式
function Car(sColor, iDoors, iMpg) {
this.color = sColor;
this.doors = iDoors;
this.mpg = iMpg;
this.drivers = new Array("Mike", "Sue");
}
Car.prototype.showColor = function () {
alert(this.color);
};
var oCar1 = new Car("red", 4, 23);
var oCar2 = new Car("blue", 3, 25);
oCar1.drivers.push("Matt");
alert(oCar1.drivers); //outputs "Mike,Sue,Matt"
alert(oCar2.drivers); //outputs "Mike,Sue"
现在更像创Z般对象了。所有的非函数属性都有构造函C创徏Q意味着又可用构造函数的参数赋予属性默认g。因为只创徏showColor()函数的一个实例,所以没有内存浪贏V?br>
5.动态原型方?br>function Car(sColor, iDoors, iMpg) {
this.color = sColor;
this.doors = iDoors;
this.mpg = iMpg;
this.drivers = new Array("Mike", "Sue");
if (typeof Car._initialized == "undefined") {
Car.prototype.showColor = function () {
alert(this.color);
};
Car._initialized = true;
}
}
var oCar1 = new Car("red", 4, 23);
var oCar2 = new Car("blue", 3, 25);
oCar1.drivers.push("Matt");
alert(oCar1.drivers); //outputs "Mike,Sue,Matt"
alert(oCar2.drivers); //outputs "Mike,Sue"
动态原型方法的基本x与合的构造函?原型方式相同Q即在构造函数内定义非函数属性,而函数属性则利用原型属性定义。唯一的区别是赋予对象Ҏ的位|?/p>
6.混合工厂方式
q种方式通常是在不能应用前一U方式时的变通方法。它的目的是创徏假构造函敎ͼ只返回另一U对象的新实例?br>function Car() {
var tempcar = new Object;
tempcar.color = "red";
tempcar.doors = 4;
tempcar.mpg = 23;
tempcar.showColor = function () {
alert(this.color)
};
return tempcar;
}
与经典方式不同,q种方式使用newq算W,使它看v来像真正的构造函数?br>
7.采用哪种方式
如前所qͼ目前使用最q泛的是混合的构造函?原型方式。些外,动态原型方法也很流行,在功能上与前者等P可以采用q两U方式中的Q何一U?br>
二、修改对?br>1.创徏新方?br>可以用prototype属性ؓM已有的类定义新方法,像处理自己的类一栗?br>例:
Array.prototype.indexOf = function(vItem){
for(var i=0;i<this.length;i++){
if(vItem == this[i]){
return i;
}
}
retunr -1;
}
最后,如果想给ECMAScript中的每个本地对象d新方法,必须在Object对象的prototype属性上定义它?br>
2.重定义已有方?br>像能给自己的类定义新方法一P也可重定义已有的Ҏ。函数名只是指向函数的指针,因此可以LC它指向其他函数?br>?br>Function.prototype.toString = function(){
return "Function code hidden";
}
function sayHi(){
alert("hi");
}
alert(sayHi.toString()); //outputs "Function code hidden"