
(因為那段代碼是錯的,現已修正)。下面再說一下這段代碼的特點和問題,歡迎有興趣并能看到詩的博友斧正。
而仔細看昨天那段代碼,除了行數多外,從效率上來說基本已是無懈可擊。這麼說有什麼依據,憑什麼說這個代碼很優化?那麼我們來看一下.NET Framework
1.1中QuoteJScriptString(string)方法的實作:
public static string QuoteJScriptString(string value)
{
StringBuilder strbQuoted = new StringBuilder(value.Length + 5);
for ( int i = 0; i < value.Length; i++)
char ch = value[i];
if (ch <= '"')
switch(ch)
case '\t':
strbQuoted.Append(@"\t");
continue;
}
case '\n':
strbQuoted.Append(@"\n");
case '\v':
case '\f':
strbQuoted.Append(value[i]);
case '\r':
strbQuoted.Append(@"\r");
case '"':
strbQuoted.Append("\\\"");
}
}
else
if (ch == '\'')
strbQuoted.Append(@"\'");
continue;
if (ch == '\\')
strbQuoted.Append(@"\\");
strbQuoted.Append(value[i]);
}
return strbQuoted.ToString();
}
要想知道自己寫的代碼是否是業餘水準,我認為可以參考一下上面這段代碼
。這段代碼我覺得唯一有意義的地方就是建立StringBuilder對象的時候,給出了Capacity的大小,而且也僅此這一點顯得和業餘水準之間有了一點點的差距。至于為什麼判斷ch
<= '"',我沒有太明白,是因為swith中case太多會有什麼效率問題嗎?雖然'"'是ASCII中順序裡的第二個可列印字元(不算Space),但是這樣将ch的檢測路徑分開,我沒有覺得有什麼大的意義。
那麼2.0中的QuoteJScriptString有什麼特點呢?一是:修改了bug,給QuoteJScriptString添加了一個forUrl的bool參數,訓示轉換時是否轉換"%"為其escape(JScript中的全局函數)形式。因為如果當你把腳本代碼使用到link的href中時,IE會自動的unescape這個字元串,再作為代碼解析執行。看下面的示例:
<a href="JavaScript: alert('%25%');">click</a>
如果在IE中你點選了click後,你覺得MsgBox裡會顯示啥?是"%25%"嗎?實際上顯示的是:"%%"。這就是為什麼新版的方法要添加forUrl開關參數的原因,是為了修複bug。二是:優化了QuoteJScriptString方法的效率,除了繼續沿用了建立StringBuilder那個地方外,還有三點。1)
做了參數合法性檢查;2) 消除了不必要的StringBuilder執行個體的建立;3)
對于不用替換的字元,使用區段處理代替了逐字處理。
既然都說昨天那段挺不錯了,那麼還重構個頭啊?其實重構隻是一個镢頭了
。至于考證代碼是不是微軟原版的,我隻能說:别人看到了詩
,有的人看到屎
。真的要重構,也就主要是節省點代碼了,我相信程式員都是很懶的,即使打字再快,畢竟我們也不是打字員哈。給一個重構後的版本,代碼如下:
public static string QuoteJScript(string value, bool forUrl)
if (StringHelper.IsEmpty(value))
return string.Empty;
StringBuilder strbQuoted = null;
int i, position;
i = position = 0;
const string QUOTED_CHARS= "\t\n\v\f\r\"%'\\";
string [] QUOTED_STRINGS =
{ @"\t", @"\n", @"\v", @"\f", @"\r", @"\""", @"%25", @"\'", @"\\" };
for ( ; i < value.Length; i++)
int index = QUOTED_CHARS.IndexOf(ch);
if ( index >= 0 )
if ( ch != '%' || ( ch == '%' && forUrl ) )
if ( strbQuoted == null )
strbQuoted = new StringBuilder(value.Length + 5);
if ( i-position >= 1 )
strbQuoted.Append(value, position, i-position);
strbQuoted.Append(QUOTED_STRINGS[index]);
position = i + 1;
if (strbQuoted == null)
return value;
if ( i-position >= 1 )
strbQuoted.Append(value, position, i-position);
最後有一個有趣的問題,你認為Fx 1.1和2.0中兩個QuoteJScriptString是同一個人寫的嗎?你覺得這種重構方式好不好?是你會怎麼做呢?
本文轉自部落格園鳥食軒的部落格,原文連結:http://www.cnblogs.com/birdshome/,如需轉載請自行聯系原部落客。