JavaScript/Best practices
document.write
[編輯]這已被棄用。 請改用 innerHTML
或 DOM 操作方法。
在 XHTML 中,document.write
不起作用,但您可以使用 DOM 操作方法實現相同的效果[1]。
JavaScript協議
[編輯]儘量避免只為執行 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的用戶提供對內容的訪問。第三,它檢測函數執行是否成功,並在失敗的情況下重定向支持JS的閱讀器。
onclick表達式的計算結果為布爾值。如果函數成功執行預期效果並返回true,則onclick將返回失敗並且超連結不執行。當函數由於某種原因失敗時,false、null 或 undefined 值將評估為 true,並且不會阻止連結被執行。或者,如果您不希望提供靜態等效項,則可以將 onclick 屬性嵌入到語義要求較低的元素中:
<strong onclick="resumeFancyVersion()">See my résumé!</strong>
因此,用戶代理在讀取簡化的 <a> 元素時不會感到困惑。
Email驗證
[編輯]許多人使用 JavaScript 函數來立即捕獲表單輸入中最常見的錯誤類型。例如,一些 Web 表單要求人們輸入兩次相同的內容。其他網絡表單要求人們輸入電子郵件地址。然後他們會快速檢查輸入的內容是否至少有點像電子郵件地址:
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) 確實允許使用「+」號。 同月(1982 年 8 月)發佈的 RFC 822 也允許使用它們。 當前版本的語法在 RFC2821/RFC2822 中給出。 RFC3696 的第 3 節給出了異常有效電子郵件地址的有用示例。
驗證後,許多 JavaScript 程式設計師對電子郵件地址進行編碼使用 encodeURIComponent()
解決某些似乎無法正確處理加號的客戶端語言。[1][2]
用於電子郵件地址的引用規則的複雜性使得完全測試地址的本地部分或域文字是不切實際的。 鑑於不一定存在對應於有效本地部分的真實郵箱,在複雜的驗證腳本上花費多少額外的下載時間是值得的?
按照RFC2822驗證通過的例子
[編輯]me@example.com
a.nonymous@example.com
name+tag@example.com
a.name+tag@example.com
me.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
– 不鼓勵comment,但 RFC2822 不禁止comment.
按照RFC2822驗證不通過的例子
[編輯]me@
@example.com
me.@example.com
.me@example.com
me@example..com
me\@example.com
spaces\ must\ be\ within\ quotes\ even\ when\ escaped@example.com
a\@mustbeinquotes@example.com
測試頁
[編輯]評論:此代碼被錯誤地設計為拒絕某些實際有效的電子郵件。如果接受對有效和無效電子郵件的更改,則還應查看以下代碼。
以下測試頁面可用於測試電子郵件驗證功能。將這三個文件保存在同一目錄中,然後在 Web 瀏覽器中打開「validEmail.htm」。
validEmail.js
function isValidEmail(string) {
// 这些注释使用 RFC2822 中的以下术语:
// 本地部分、域、域文字和点原子(local-part, domain, domain-literal, dot-atom)
// 地址是否包含一个本地部分,后跟一个@,后跟一个域?
// 注意使用lastIndexOf 查找地址中最后一个@
// 因为一个有效的电子邮件地址可能在本地部分有一个带引号的@。
// 域名是否至少有两部分,即至少有一个点,
// 之后 @? 如果不是,它是域文字吗?
// 这将接受一些无效的电子邮件地址
// 但它不会拒绝有效的。
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>
use strict
[編輯]許多 JavaScript 程式設計師建議通過將確切的語句 "use strict";
放在任何其他語句之前來啟用 ECMAScript 5 的嚴格模式:[3][4][5]
"use strict";
function …
進一步閱讀
[編輯]- Coding Cookbook/Validate Email Address
- "Six JavaScript features we do not need any longer" by Christian Heilmann.
- source code for Apple's recommended JavaScript validation functions: checkEmail(), etc.
- JavaScript form validation - doing it right
- "FORM submission and the ENTER key?" discusses forms that submit when you press Enter; forms that don't submit when you press Enter; and how to make a form work the other way.
- "JavaScript Best Practices" by Matt Kruse
- "Comparing E-mail Address Validating Regular Expressions" has a list of valid and invalid email addresses and a variety of regular expressions and how well each one works on that list.
參考文獻
[編輯]- ↑ Jan Wolter. "JavaScript Madness: Query String Parsing" 2011.
- ↑ PHP bug #39078: Plus sign in URL arg received as space.
- ↑ Nicholas C. Zakas. "It’s time to start using JavaScript strict mode". 2012.
- ↑ "What does 「use strict」 do in JavaScript, and what is the reasoning behind it?"
- ↑ Mozilla Developer Network: "Strict mode".