JavaScript/最佳實踐
本章將介紹當前 JavaScript 社群的標準和最佳實踐,每個程式設計師都應該知道。
此方法已過時。請改用 innerHTML 或 DOM 操作方法。
在 XHTML 中,document.write 不起作用,但您可以使用 DOM 操作方法來實現相同的效果[1].
嘗試避免僅用於執行 JavaScript 程式碼的連結。
<a href="javascript:resumeFancyVersion()">See my résumé!</a>
相反,考慮
<a href="resumePlainVersion.html" onclick="return !resumeFancyVersion()">See my résumé!</a>
啟用 JavaScript 的使用者將獲得包含 JavaScript 增強內容的版本(可能使用 DHTML),而未啟用 JavaScript 的使用者將被重定向到以靜態方式提供此內容的 XHTML 頁面。這比使用沒有正常 href 屬性值的 <a> 元素更易於訪問。首先,它使用 正確的語言語義。其次,它為沒有 JavaScript 的使用者提供訪問內容的途徑。第三,它檢測函式執行是否成功,並在失敗的情況下也重定向支援 JavaScript 的讀者。
onclick 表示式計算為布林值。如果函式成功執行所需的效果並返回 true,onclick 將返回失敗,並且超連結不會執行。當函式由於任何原因失敗時,false、null 或 undefined 值將計算為 true,並且不會阻止連結執行。或者,如果您不想提供靜態等效項,您可以在語義要求不高的元素內嵌入 onclick 屬性
<strong onclick="resumeFancyVersion()">See my résumé!</strong>
因此,任何使用者代理在閱讀簡化的 <a> 元素時都不會感到困惑。
許多人使用 JavaScript 函式來立即捕獲表單輸入中最常見的錯誤型別。例如,一些網頁表單要求人們兩次輸入相同的內容。其他網頁表單要求人們輸入電子郵件地址。然後,他們快速檢查一下輸入的內容是否至少看起來有點像電子郵件地址
function isValidEmail(string) {
// These comments use the following terms from RFC2822:
// local-part, domain, domain-literal and dot-atom.
// Does the address contain a local-part followed an @ followed by a domain?
// Note the use of lastIndexOf to find the last @ in the address
// since a valid email address may have a quoted @ in the local-part.
// Does the domain name have at least two parts, i.e. at least one dot,
// after the @? If not, is it a domain-literal?
// This will accept some invalid email addresses
// BUT it doesn't reject valid ones.
var atSym = string.lastIndexOf("@");
if (atSym < 1) { return false; } // no local-part
if (atSym == string.length - 1) { return false; } // no domain
if (atSym > 64) { return false; } // there may only be 64 octets in the local-part
if (string.length - atSym > 255) { return false; } // there may only be 255 octets in the domain
// Is the domain plausible?
var lastDot = string.lastIndexOf(".");
// Check if it is a dot-atom such as example.com
if (lastDot > atSym + 1 && lastDot < string.length - 1) { return true; }
// Check if could be a domain-literal.
if (string.charAt(atSym + 1) == '[' && string.charAt(string.length - 1) == ']') { return true; }
return false;
}
不幸的是,一些其他“電子郵件驗證”JavaScript 函式會拒絕完全有效的電子郵件地址。例如,一些 錯誤地拒絕 包含“+”號的有效地址。
原始電子郵件地址語法(RFC 821)確實允許“+”號。 RFC 822 於同一個月(1982 年 8 月)釋出,也允許它們。當前版本的語法在 RFC2821/RFC2822 中給出。RFC3696 的第 3 節給出了非同尋常的有效電子郵件地址的實用示例。
驗證後,許多 JavaScript 程式設計師使用 encodeURIComponent() 對電子郵件地址進行編碼,以解決某些客戶端語言似乎無法正確處理加號的問題。[1][2]
用於電子郵件地址的引用規則的複雜性使得對地址的本地部分或域文字進行完整測試變得不切實際。鑑於不一定存在與有效本地部分相對應的真實郵箱,花多少額外下載時間來執行復雜的驗證指令碼才值得呢?
me@example.coma.nonymous@example.comname+tag@example.coma.name+tag@example.comme.example@com"spaces must be quoted"@example.com!#$%&'*+-/=.?^_`{|}~@[1.0.0.127]!#$%&'*+-/=.?^_`{|}~@[IPv6:0123:4567:89AB:CDEF:0123:4567:89AB:CDEF]me(this is a comment)@example.com– RFC2822 不鼓勵註釋,但沒有禁止。
me@@example.comme.@example.com.me@example.comme@example..comme\@example.comspaces\ must\ be\ within\ quotes\ even\ when\ escaped@example.coma\@mustbeinquotes@example.com
註釋:此程式碼設計不當,會拒絕某些實際上有效的電子郵件。如果對有效和無效電子郵件的更改被接受,則應同時檢查以下程式碼。
以下測試頁面可用於測試電子郵件驗證函式。將三個檔案儲存在同一目錄中,然後在網頁瀏覽器中開啟 validEmail.htm。
validEmail.js
function isValidEmail(string) {
// These comments use the following terms from RFC2822:
// local-part, domain, domain-literal and dot-atom.
// Does the address contain a local-part followed an @ followed by a domain?
// Note the use of lastIndexOf to find the last @ in the address
// since a valid email address may have a quoted @ in the local-part.
// Does the domain name have at least two parts, i.e. at least one dot,
// after the @? If not, is it a domain-literal?
// This will accept some invalid email addresses
// BUT it doesn't reject valid ones.
var atSym = string.lastIndexOf("@");
if (atSym < 1) { return false; } // no local-part
if (atSym == string.length - 1) { return false; } // no domain
if (atSym > 64) { return false; } // there may only be 64 octets in the local-part
if (string.length - atSym > 255) { return false; } // there may only be 255 octets in the domain
// Is the domain plausible?
var lastDot = string.lastIndexOf(".");
// Check if it is a dot-atom such as example.com
if (lastDot > atSym + 1 && lastDot < string.length - 1) { return true; }
// Check if could be a domain-literal.
if (string.charAt(atSym + 1) == '[' && string.charAt(string.length - 1) == ']') { return true; }
return false;
}
function testIsValidEmail(string) {
alert("'" + string + "' is " + (isValidEmail(string) ? "" : "NOT ") + " a valid email address.");
}
function checkSamples() {
var validAddress = [
'me@example.com',
'a.nonymous@example.com',
'name+tag@example.com',
'name\\@tag@example.com',
'spaces\\ are\\ allowed@example.com',
'"spaces may be quoted"@example.com',
'!#$%&\'*+-/=.?^_`{|}~@[1.0.0.127]',
'!#$%&\'*+-/=.?^_`{|}~@[IPv6:0123:4567:89AB:CDEF:0123:4567:89AB:CDEF]',
'me(this is a comment)@example.com'
];
var invalidAddress = [
'me@',
'@example.com',
'me.@example.com',
'.me@example.com',
'me@example..com',
'me.example@com',
'me\\@example.com'
];
var results = new StringBuffer();
var handlesValidAddressesCorrectly = true;
results.append('<table border="1">');
results.append('<caption>Does the function accept all the valid sample addresses?</caption>');
results.append('<tr><th>Valid address</th><th>Function returns</th></tr>');
for (var i = 0; i < validAddress.length; i++) {
results.append('<tr><td>');
results.append(validAddress[i]);
results.append('</td><td>');
if (isValidEmail(validAddress[i])) {
results.append('<span class="good">true</span>');
} else {
handlesValidAddressesCorrectly = false;
results.append('<strong class="fail">false</strong>');
}
results.append('</td></tr>');
}
results.append('</table>');
var handlesInvalidAddressesCorrectly = true;
results.append('<table border="1">');
results.append('<caption>Does the function reject all the invalid sample addresses?</caption>');
results.append('<tr><th>Valid address</th><th>Function returns</th></tr>');
for (var i = 0; i < invalidAddress.length; i++) {
results.append('<tr><td>');
results.append(invalidAddress[i]);
results.append('</td><td>');
if (!isValidEmail(invalidAddress[i])) {
results.append('<span class="good">false</span>');
} else {
handlesInvalidAddressesCorrectly = false;
results.append('<em class="warning">true</em>');
}
results.append('</td></tr>');
}
results.append('</table>');
var conclusion;
if (handlesValidAddressesCorrectly) {
if (handlesInvalidAddressesCorrectly) {
conclusion = '<p><strong class="good">The function works correctly with all the sample addresses.</strong></p>';
} else {
conclusion = '<p><em class="warning">The function incorrectly accepts some invalid addresses.</em></p>';
}
} else {
conclusion = '<p><strong class="fail">The function incorrectly rejects some valid addresses.</strong></p>';
}
document.getElementById('testResults').innerHTML = conclusion + results.toString();
}
function StringBuffer() {
this.buffer = "";
}
StringBuffer.prototype.append = function(string) {
this.buffer += string;
return this;
};
StringBuffer.prototype.toString = function() {
return this.buffer;
};
validEmail.css
body {
background-color: #fff;
color: #000
}
table {
margin-bottom: 2em
}
caption {
margin-top: 2em
}
.good {
background-color: #0f0;
color: #000
}
.warning {
background-color: #fc9;
color: #000
}
.fail {
background-color: #f00;
color: #fff
}
validEmail.htm
<!DOCTYPE html>
<html lang="en">
<head>
<title>Valid email test</title>
<link rel="stylesheet" href="validEmail.css">
<script src="validEmail.js"></script>
</head>
<body onload="checkSamples()">
<h1>Unit test for email address validation functions</h1>
<h2>Interactive test</h2>
<form action="#">
<fieldset>
<legend>Email address</legend>
<label for="emailAddress">Email</label>
<input type="text" size="40" value="" name="email" id="emailAddress">
<input type="button" name="validate" value="Check address"
onclick="testIsValidEmail(this.form.email.value)">
</fieldset>
</form>
<h2>Selected samples</h2>
<p>This section shows the results of testing the function with sample strings.
The sample includes both valid strings and invalid strings
according to <a href="http://www.faqs.org/rfcs/rfc2822.html">RFC2822</a>.
</p>
<div id="testResults">You need to enable JavaScript for this unit test to work.</div>
</body>
</html>
許多 JavaScript 程式設計師建議透過在任何其他語句之前放置精確語句 "use strict"; 來啟用 ECMAScript 5 的嚴格模式:[3][4][5]
"use strict";
function …
JavaScript 最佳實踐
- 編碼手冊/驗證電子郵件地址
- Christian Heilmann 的“我們不再需要的六個 JavaScript 功能”.
- Apple 推薦的 JavaScript 驗證函式的原始碼:checkEmail() 等。
- JavaScript 表單驗證 - 做對方法
- "FORM 提交和 ENTER 鍵?" 討論了按下 Enter 鍵時提交的表單;按下 Enter 鍵時不提交的表單;以及如何使表單以另一種方式工作。
- Matt Kruse 的“JavaScript 最佳實踐”
- "比較電子郵件地址驗證正則表示式" 包含一個有效和無效電子郵件地址列表以及各種正則表示式,以及每個正則表示式在該列表中的工作效果。