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".