如何编写高质量的js代码

如果你想编写一个高效的Javascript库,你不必这么做。

试着阅读别人的类库,但理解理解。

我打算好好研究js高级功能,但权限太分散了。

甚至记住使用,但不知道什么时候你想使用它。

也许你和我就像一只无形的力量,制约着我们的计划,使我们反复思考知识的局限性,并引导我们一步一步地向前走。

这段时间,各种功课,课程设计,实验报告,压力倍增,难得挤一点时间,不睡进去,整理你过去读过的书,只是为了接近你自己的图书馆。

本文以Javascript语言精华和有效Javascript为基础,对这些示例进行了调试,在理解之后,我想讲一点深刻的道理。

1。变量范围

的范围,就像氧气对程序员。它无处不在,即使你不想他。但当它被污染(如全局对象的使用),你会感到窒息(例如,应用程序的响应速度变慢),Javascript核心范围规则简单,设计良好的和强大的。为了有效地使用Javascript,我们需要掌握一些基本概念和变量范围理解一些极端情况下可能导致难以捉摸和恼人的问题。

1.1尽可能少地使用全局变量

Javascript很容易在全局命名空间中创建变量。创建全局变量是毫不费力的,因为它不需要任何形式的声明,并且可以由整个程序的所有代码自动访问。

对于我们这些初学者,一些要求(例如,传输的数据被记录下来,等待一次函数调用时使用;或一个函数是经常使用),毫不犹豫地认为全局函数,甚至学会了C语言的面向过程的思维是根深蒂固的,系统地定义全功能。全局变量会污染公共命名空间和可能导致意外的命名冲突。全局变量也不是模块化,因为它会导致在程序之间的独立成分的不必要的耦合严重,过度的全球(包括样式,用div或风格直接定义),融入多人的发展,将一个灾难性的错误。这就是为什么所有的jQuery的代码封装在一个立即执行的匿名表达式中——调用匿名函数,当浏览器加载jQuery文件时,它开始执行匿名函数并初始化jQuery模块,以避免破坏和污染全局变量,从而影响其他代码。

复制代码代码如下所示:

函数(窗口,未定义){

var =…



window.jquery =美元= jQuery的窗口;

}(窗口);



另外,你可能会想到,怎么写就先,做完后比较方便,但好的程序员会继续注意结构,不断地把相关的功能和组件分类,不涉及分离程序,而这些作为编程的一部分。

由于全局命名空间是Javascript程序中独立组件交互的唯一方法,因此不可避免地要使用全局命名控件。组件或程序库必须定义一些全局变量,以便使用程序的其他部分。否则,最好使用本地变量。

复制代码代码如下所示:

this.foo; / /未定义

全局;

this.foo; / /全球foo

全局;

this.foo =改变;

更改



Javascript的全局命名空间也暴露在全局对象,可以在全球范围内的程序访问,这是该关键字的初始值,在Web浏览器中,全局对象被绑定到全局变量。这意味着你有两种方法创建一个全局变量:宣称他与VaR在全球范围内,或将它添加到一个全局对象。使用var声明的优点是明确在程序范围内表示全局变量的影响。

考虑到引用是导致运行时错误的一个全局变量,所以保存范围是明确的和简明的,这使得代码用户更容易理解程序所声明的全局变量。

由于全局对象提供了全局环境的动态响应机制,它可以使用它来查询正在运行的环境,并检测在这个平台上可用的特性。

eg.es5介绍全球JSON对象读写数据以JSON格式。

复制代码代码如下所示:

如果(!这个(JSON){

this.json = { {

解析:,

stringify:…

}

}



如果你提供JSON的实现,当然你可以使用你自己的实现简单和无条件的。但宿主环境提供的内置的实现几乎是更合适的因为他们是写在C语言中的浏览器,因为他们是严格检查的正确性和一致性,根据一定的标准,一般提供比第三方实现更好的性能。

原来的数据结构课程设计模拟字符串的基本操作,它不需要用语言itself.javascript执行很好的数组的基本操作。如果只是为了一般的学习需求,模拟语言本身提供的方法是很好的,但是如果你真的投资于开发,你就不必考虑第一次选择Javascript内置方法了。

1.2避免使用

带语句提供了任何方便,使应用程序不可靠和效率低下。我们需要为一个对象调用一系列方法。使用语句可以轻松避免重复引用对象:

复制代码代码如下所示:

函数状态(信息){

小部件=新的小部件();

带(小部件){

setbackground(蓝色);

setforeground(白);

SetText (Status: +info);

显示();

}

}



使用语句从模块对象导入(导入)变量也是很有诱惑力的。

复制代码代码如下所示:

函数f(x,y){

用(数学){

返回min(圆(x),sqrt(Y)); / /抽象的参考

}

}



事实上,Javascript将所有变量的same.javascript开始寻找变量从最内部的范围。与语言治疗对象如果对象代表一个变量范围。因此,在代码块变量查找从搜索给定的变量名称的属性。如果此属性不在这个对象中发现的,它仍然是在外部范围搜索。在块假定每个外部变量的引用,在对象不一样名称属性(以及任何其原型对象),对象或其原型对象在程序的其他部分的创建或修改不一定遵循这样的假设。当然,Javascript引擎,不会读本地代码让你使用局部变量,Javascript的范围可以表示为一个高效的内部数据结构和变量查找会很快但是,由于代码块需要搜索对象的原型链,以便用代码查找所有变量,所以它比一般代码块运行得快得多。

简单的方法是将对象绑定到一个短变量名,而不是使用语言。

复制代码代码如下所示:

函数状态(信息){

新的小部件();



w.setbackground(蓝色);

w.setforeground(白);

W.setText(状态:+信息);

W.show();



}



在其他情况下,最好的方法是显式地绑定本地变量到相关属性。

复制代码代码如下所示:

函数f(x,y){

VaR最小= Math.min,

圆= math.round,

表示math.sqrt;

返回min(圆(x),sqrt(Y));

}



1.3掌握闭包

理解闭包的概念是单一的:

a)Javascript允许您引用在当前函数之外定义的变量。

复制代码代码如下所示:

功能makesandwich(){

无功magicingredient =花生酱;

函数生成(填充){

返回magicingredient + 和+填充;

}

退货(果冻);

}

MakeSandwich(花生酱); / /果冻



b)即使返回了外部函数,当前函数仍然可以引用外部函数定义的变量。

复制代码代码如下所示:

功能makesandwich(){

无功magicingredient =花生酱;

函数生成(填充){

返回magicingredient + 和+填充;

}

回报;

}

var = sandwichmaker();

f(果冻);花生酱和果冻

F(香蕉);花生酱和香蕉

f(锦葵); / /花生酱和锦葵



比需要调用的代码的更多信息包含的javascriptd函数值。此外,Javascript函数值仍然存储在内部存储,他们可能是在封闭的范围内引用变量,函数,变量的范围内跟踪他们盖被关闭。

该功能是一个关闭的代码指的是两个外部变量:magicingredient加油。每次让函数被调用时,代码可以参考这两个变量,因为关闭商店的两变量。

一个函数可以引用在其范围内的任何变量,包括参数和外部函数的变量,我们可以用这个写的更一般的sandwichmaker功能。

复制代码代码如下所示:

功能makesandwich(magicingredient){

函数生成(填充){

返回magicingredient + 和+填充;

}

回报;

}

var = sandwichmaker(火腿);

f();火腿和奶酪

f(芥末);



闭包是Javascript最优雅、最具表现力的特征之一,也是许多习语的核心。

闭包可以更新外部变量的值。事实上,闭包是作为对外部变量引用的存储,而不是它们值的拷贝。因此,可以对访问这些外部变量的任何闭包进行更新。

复制代码代码如下所示:

函数框(){

var =未定义;

返回{

设置:功能(newval){ val = newval;},

获取函数(){返回;},

类型:函数(){ return类型的值;}

};

}

var(=);

B.type(); / /未定义

b.集合(98.6);

B.get(); / / 98.6

B.type(); / /数量



这个例子产生一个包含三封。这三封集,类型,和得到的属性,所有这些共享访问val变量,并设置关闭更新值的值和类型并调用看到更新的结果。

1.4理解变量声明提升

Javascript支持该方法的作用域(变量的引用绑定到声明的变量的最接近范围),但不支持块级范围。变量定义的范围不是最近关闭的语句或代码块。

目前尚不清楚这一特性是否会导致一些细微的缺陷:

复制代码代码如下所示:

功能iswinner(玩家、其他){

var最高= 0;

对于(var i = 0,n = others.length;i < n;i++){

var播放器=其他{ { };

如果(player.score >最高){

player.score最高=;

}

}

player.score >最高回报;

}



1.5注意命名函数表达式的笨拙范围。

复制代码代码如下所示:

函数双(x){返回x×2;}

函数(x){返回x * 2;}



相同功能的代码也可以被用来作为一种表达,但它有一个非常不同的含义。匿名函数和命名函数表达式之间的官方的区别是,后者将被绑定到一个变量的函数的名字,这是该函数的局部变量,这可以用来编写递归函数表达式。

复制代码代码如下所示:

函数find(树,键){

/…

返回找到(tree.left,关键| |)

(tree.right,找到关键);

}



值得注意的是,变量查找的范围仅在其自身的函数中,与函数声明不同,命名函数表达式不能在函数名之外引用。

复制代码代码如下所示:

发现(mytree,foo); / /错误:找到没有定义;

函数(){返回null;}

函数(){

返回构造函数();

};

(f); / / { }(沙三段环境)



程序看起来会生成null,但实际上会生成一个新对象。

因为命名函数变量继承object.prototype.constructor(对象的构造函数)内的函数变量的范围。就像声明,这个范围是由object.prototype.the办法避免物体污染功能表达系统中表达的动态变化的影响是避免添加属性到Object.prototype在任何时间,以避免使用任何局部变量名称的标准object.prototype属性相同。

流行的Javascript引擎的另一个缺点是对命名函数表达式的声明进行了推广。

复制代码代码如下所示:

函数g(){返回17;}

G(); / / 17(在nonconformat环境)



有些Javascript环境甚至使用F和G的两个函数作为不同的对象,从而导致不必要的内存分配。

1.6本地块函数声明笨拙的范围。

复制代码代码如下所示:

函数f(){返回全局;}

函数测试(x){

函数f(){返回本地;}

var结果{ };

如果(x){

result.push(f());

}

result.push(f());

结果;

}

测试(true)

测试(false)



复制代码代码如下所示:

函数f(){返回全局;}

函数测试(x){

var结果{ };

如果(x){

函数f(){返回本地;}

result.push(f());

}

result.push(f());

结果;

}

测试(true)

测试(false)



Javascript没有一块水平的范围,所以内部函数f的范围应该是整个测试功能。一些Javascript确实,但并不是所有的脚本都是这样的,Javascript严格模式,这种功能是报告为错误(程序下局部块函数声明严格模式报告语法错误),有助于非便携式检测代码的未来版本的标准为本地块函数声明的语义更明智和能。在这种情况下,可以考虑一个局部变量在测试功能点的全局函数F。