JavaScript 规范Word文档格式.docx
《JavaScript 规范Word文档格式.docx》由会员分享,可在线阅读,更多相关《JavaScript 规范Word文档格式.docx(39页珍藏版)》请在冰豆网上搜索。
10.
11.}(window.console.log,window));
IIFE(立即执行的函数表达式)
无论何时,想要创建一个新的封闭的定义域,那就用IIFE。
它不仅避免了干扰,也使得内存在执行完后立即释放。
所有脚本文件建议都从IIFE开始。
立即执行的函数表达式的执行括号应该写在外包括号内。
虽然写在内还是写在外都是有效的,但写在内使得整个表达式看起来更像一个整体,因此推荐这么做。
1.(function(){})();
1.(function(){}());
so,用下列写法来格式化你的IIFE代码:
1.(function(){
4.
//Codegoeshere
5.
6.}());
如果你想引用全局变量或者是外层IIFE的变量,可以通过下列方式传参:
1.(function($,w,d){
$(function(){
w.alert(d.querySelectorAll('
div'
).length);
});
7.}(jQuery,window,document));
严格模式
ECMAScript5严格模式可在整个脚本或独个方法内被激活。
它对应不同的javascript语境会做更加严格的错误检查。
严格模式也确保了javascript代码更加的健壮,运行的也更加快速。
严格模式会阻止使用在未来很可能被引入的预留关键字。
你应该在你的脚本中启用严格模式,最好是在独立的IIFE中应用它。
避免在你的脚本第一行使用它而导致你的所有脚本都启动了严格模式,这有可能会引发一些第三方类库的问题。
1.//Scriptstartshere
2.'
4.(function(){
//Yourcodestartshere
8.}());
9.推荐
11.(function(){
12.
13.
14.
15.
16.}());
变量声明
总是使用var来声明变量。
如不指定var,变量将被隐式地声明为全局变量,这将对变量难以控制。
如果没有声明,变量处于什么定义域就变得不清(可以是在Document或Window中,也可以很容易地进入本地定义域)。
所以,请总是使用var来声明变量。
采用严格模式带来的好处是,当你手误输入错误的变量名时,它可以通过报错信息来帮助你定位错误出处。
不推
1.x=10;
2.y=100;
理解JavaScript的定义域和定义域提升
在JavaScript中变量和方法定义会自动提升到执行之前。
JavaScript只有function级的定义域,而无其他很多编程语言中的块定义域,所以使得你在某一function内的某语句和循环体中定义了一个变量,此变量可作用于整个function内,而不仅仅是在此语句或循环体中,因为它们的声明被JavaScript自动提升了。
我们通过例子来看清楚这到底是怎么一回事:
原function
1.(function(log){
vara=10;
for(vari=0;
i<
a;
i++){
7.
varb=i*i;
log(b);
}
11.
if(a===10){
varf=function(){
13.
log(a);
};
15.
f();
16.
17.
18.
functionx(){
19.
log('
Mr.X!
);
20.
21.
x();
22.
23.}(window.console.log));
被JS提升过后
//Allvariablesusedintheclosurewillbehoistedtothetopofthefunction
vara,
i,
b,
f;
//Allfunctionsintheclosurewillbehoistedtothetop
10.
12.
a=10;
14.
for(i=0;
b=i*i;
17.
19.
//Functionassignmentswillonlyresultinhoistedvariablesbutthefunctionbodywillnotbehoisted
22.
//Onlybyusingarealfunctiondeclarationthewholefunctionwillbehoistedwithitsbody
23.
f=function(){
24.
25.
26.
27.
28.
29.
30.
31.}(window.console.log));
根据以上提升过程,你是否可理解以下代码?
有效代码
i=5;
9.
for(vari;
20.
varf;
23.
27.
28.}(window.console.log));
正如你所看到的这段令人充满困惑与误解的代码导致了出人意料的结果。
只有良好的声明习惯,也就是下一章节我们要提到的声明规则,才能尽可能的避免这类错误风险。
提升声明
为避免上一章节所述的变量和方法定义被自动提升造成误解,把风险降到最低,我们应该手动地显示地去声明变量与方法。
也就是说,所有的变量以及方法,应当定义在function内的首行。
只用一个var关键字声明,多个变量用逗号隔开。
varb=10;
6.
10;
varc=a*b*i;
functionf(){
vard=100;
varx=function(){
returnd*d;
};
log(x());
21.}(window.console.log));
vara=10,
b=10,
c,
d,
x;
c=a*b*i;
18.
d=100;
x=function(){
26.
27.}(window.console.log));
把赋值尽量写在变量申明中。
1.vara,
b,
c;
5.a=10;
6.b=10;
7.c=100;
1.vara=10,
b=10,
c=100;
总是使用带类型判断的比较判断
总是使用===精确的比较操作符,避免在判断的过程中,由JavaScript的强制类型转换所造成的困扰。
如果你使用===操作符,那比较的双方必须是同一类型为前提的条件下才会有效。
如果你想了解更多关于强制类型转换的信息,你可以读一读DmitrySoshnikov的这篇文章。
在只使用==的情况下,JavaScript所带来的强制类型转换使得判断结果跟踪变得复杂,下面的例子可以看出这样的结果有多怪了:
log('
0'
==0);
//true
==false);
1'
==true);
log(null==undefined);
8.
varx={
valueOf:
function(){
return'
X'
}
log(x=='
16.
17.}(window.console.log));
明智地使用真假判断
当我们在一个if条件语句中使用变量或表达式时,会做真假判断。
if(a==true)是不同于if(a)的。
后者的判断比较特殊,我们称其为真假判断。
这种判断会通过特殊的操作将其转换为true或false,下列表达式统统返回false:
false,0,undefined,null,NaN,'
(空字符串).
这种真假判断在我们只求结果而不关心过程的情况下,非常的有帮助。
以下示例展示了真假判断是如何工作的:
functionlogTruthyFalsy(expr){
if(expr){
truthy'
}else{
falsy'
11.
logTruthyFalsy(true);
//truthy
logTruthyFalsy
(1);
logTruthyFalsy({});
logTruthyFalsy([]);
logTruthyFalsy('
logTruthyFalsy(false);
//falsy
logTruthyFalsy(0);
logTruthyFalsy(undefined);
logTruthyFalsy(null);
logTruthyFalsy(NaN);
24.
25.}(window.console.log));
变量赋值时的逻辑操作
逻辑操作符||和&
&
也可被用来返回布尔值。
如果操作对象为非布尔对象,那每个表达式将会被自左向右地做真假判断。
基于此操作,最终总有一个表达式被返回回来。
这在变量赋值时,是可以用来简化你的代码的。
1.if(!
x){
if(!
y){
x=1;
}else{
x=y;
7.}
1.x=x||y||1;
这一小技巧经常用来给方法设定默认的参数。
functionmultiply(a,b){
a=a||1;
b=b||1;
Result'
+a*b);
multiply();
//Result1
multiply(10);
//Result10
multiply(3,NaN);
//Result3
multiply(9,5);
//Result45
16.}(window.console.log));
分号
总是使用分号,因为隐式的代码嵌套会引发难以察觉的问题。
当然我们更要从根本上来杜绝这些问题[1]。
以下几个示例展示了缺少分号的危害:
1.//1.
2.MyClass.prototype.myMethod=function(){
return42;
4.}
//Nosemicolonhere.
6.(function(){
//Someinitializationcodewrappedinafunctiontocreateascopeforlocals.
8.})();
11.varx={
i'
:
1,
j'
2
14.}
16.//2.
TryingtodoonethingonInternetExplorerandanotheronFirefox.
17.//Iknowyou'
dneverwritecodelikethis,butthrowmeabone.
18.[ffVersion,ieVersion][isIE]();
21.varTHINGS_TO_EAT=[apples,oysters,sprayOnCheese]
23.//3.conditionalexecutionalabash
24.-1==resultOfOperation()||die();
Sowhathappens?
JavaScript错误——首先返回42的那个function被第二个function当中参数传入调用,接着数字42也被“调用”而导致出错。
八成你会得到‘nosuchpropertyinundefined’的错误提示,因为在真实环境中的调用是这个样子:
x[ffVersion,ieVersion][isIE]().
die总是被调用。
因为数组减1的结果是NaN,它不等于任何东西(无论resultOfOperation是否返回NaN)。
所以最终的结果是die()执行完所获得值将赋给THINGS_TO_EAT.
Why?
JavaScript中语句要以分号结束,否则它将会继续执行下去,不管换不换行。
以上的每一个示例中,函数声明或对象或数组,都变成了在一句语句体内。
要知道闭合圆括号并不代表语句结束,JavaScript不会终结语句,除非它的下一个token是一个中缀符[2]或者是圆括号操作符。
这真是让人大吃一惊,所以乖乖地给语句末加上分号吧。
澄清:
分号与函数
分号需要用在表达式的结尾,而并非函数声明的结尾。
区分它们最好的例子是:
1.varfoo=function(){
returntrue;
3.};
//semicolonhere.
5.functionfoo(){
7.}
//nosemicolonhere.
嵌套函数
嵌套函数是非常有用的,比如用在持续创建和隐藏辅助函数的任务中。
你可以非常自由随意地使用它们。
语句块内的函数声明
切勿在语句块内声明函数,在ECMAScript5的严格模式下,这是不合法的。
函数声明应该在定义域的顶层。
但在语句块内可将函数申明转化为函数表达式赋值给变量。
1.if(x){
functionfoo(){}
3.}
varfoo=function(){};
异常
基本上你无法避免出现异常,特别是在做大型开发时(使用应用开发框架等等)。
在没有自定义异常的情况下,从有返回值的函数中返回错误信息一定非常的棘手,更别提多不优雅了。
不好的解决方案包括了传第一个引用类型来接纳错误信息,或总是返回一个对象列表,其中包含着可能的错误对象。
以上方式基本上是比较简陋的异常处理方式。
适时可做自定义异常处理。
在复杂的环境中,你可以考虑抛出对象而不仅仅是字符串(默认的抛出值)。
1.if(name===undefined){
throw{
name:
SystemError'
message:
Anameshouldalwaysbespecified!
6.}
标准特性
总是优先考虑使用标准特性。
为了最大限度地保证扩展性与兼容性,总是首选标准的特性,而不是非标准的特性(例如:
首选string.charAt(3)而不是string[3];
首选DOM的操作方法来获得元素引用,而不是某一应用特定的快捷方法)。
简易的原型继承
如果你想在JavaScript中继承你的对象,请遵循一个简易的模式来创建此继承。
如果你预计你会遇上复杂对象的继承,那可以考虑采用一个继承库,比如
Proto.jsbyAxelRauschmayer.
简易继承请用以下方式:
//Constructorfunction
functionApple(name){