《javascript实战》Part1——2成功javascript开发者的7个习惯
一、更多面向对象的javascript
1)简单创建对象
var newObject = new Object();
//变量newObject指向一个Object实例,Object是javascript所有对象的基类。
可以在任何时候给对象添加属性和方法
newObject.firstName = "frank"; newObject.sayName = function(){ alert(this.firstName); }
调用对象的方法:newOjbect.sayName();
与大多成熟的面向对象语言不同的是——不必为一个对象实例创建类或者蓝图!
如上面所写,在运行时创建它;可以随时给对象添加属性和方法!
本质:javascript把所有对象当做关联数组,使用点分隔表示法。
可以这样使用:
var theFirstName = newObject["fitstName"];
newObject["sayName"]();
若你想基于某种逻辑调用某个对象的方法——
var whatFunction ; if(whatVolume == 1){ whatFunction = "sayName"; }else if(whatVolume == 2){ whatFunction = "sayLoudly"; }; newObject[whatFunction]();
可以向一个对象添加一个已经存在的函数:
function sayLoudly(){ alert(this.firstName.toUpperCase()); } newObject.sayLoudly = sayLoudly;
注意this关键字的使用法:它指向的对象将会在运行时动态计算。上面的this指向的是函数sayLoudly()作为其成员的那个类——即Object。即如果sayLoudly是另外一个对象的一部分,this就会引用另一个对象。即运行时绑定!它允许代码的共享,本质上是一种继承。
2)使用JSON创建对象
JSON——Javascript对象表示法。是javascript规范中的一个核心部分。最初目的是为了快速简便地定义复杂的对象关系图,即嵌套于其他对象中的对象实例。
JSON可运转的因素:javascript对象只是隐藏在面具下的关联数组。
用JSON创建刚才的newObject:
function sayLoudly(){ return this.firstName.toUpperCase(); } var newObject = { firstName : "frank", sayName : function(){alert this.firstName;}, sayLoudly : sayLoudly, lastName : { lastName : "Zammetti" , sayName : function(){alert(this.lastName);} } }; newObject.lastName.sayName();
注意:
(1)函数可以是内联的也可以引用外部函数;
(2)第一个say是对象的一个成员,这里是方法;第二个是对一个已经存在的对象的引用;
(3)JSON中可以随意地嵌套对象定义来创建对象的层级关系
3)类的定义
所有的东西都是对象(只有一小部分例外,如一些内置的原语)函数本身就是对象。
每次创建对象的一个新实例都从零开始,更好的方法是——创建一个类!
类就是一个函数,这个函数同样被当做类的构造函数来提供服务
重新把newObject 写成一个类,重新命名为newClass:
function newClass(){ this.firstName = "frank"; this.sayName = function(){ alert(this.firstName); } } var nc = new newClass(); nc.sayName();
创建多少个newClass的实例就创建多少,它们含有同样的属性和方法,同样的属性初始值
缺点:newClass的每个实例都含有类里面的属性和方法的副本,占用了更多的内存。
改进:所有的实例可以共享相同的sayName()副本的话,可以节省内存。(适合更多代码的情况下)。具体见下面的方法
4)原型
javascript中每一个独立的对象都有一个与之关联的原型(prototype)属性。
其他语言没有完全与prototype相等的东西;prototype可以看做一个简化的继承形式;
其工作方式:当你构造一个对象的新实例时,定义在对象的原型中的所有属性和方法,在运行时都会附着在哪个新的实例上
例子:
function newClass(){ this.firstName = "frank"; } newClass.prototype.sayName = function(){ alert(this.firstName); } var nc = new newClass(); nc.sayName();
优点:无论创建多少个实例,在内存中sayName()函数只会有一个单独的实例。这个方法实际上市附加在每个实例上,而且this关键字仍然是在运行时被计算的。this通常指向它所属的那个特定的newClass实例。比如有两个newClass的实例分别叫做nc1和nc2,nc1.sayName()的调用将this指向nc1,对nc2.sayName()的调用将this指向nc2.
5)四种方法的比较:
一些准则:
a)创建一个非常大的类,可能会有复杂的实例——一定是原型方法(带来最好的内存使用效率)
b)创建一个单独的类,且这个类将只有一个实例,推荐定义一个类(使逻辑化最强、最类似于更全面的面向对象语言的,易于项目新开发人员理解)
c)① 对象层级关系嵌套层次很多
② 需要在一个动态方式中定义一个对象(一段逻辑代码的输出结果)
③ 需要将对象序列化并且通过网络进行传输
④ 需要重构一个从服务器传送来的对象时
以上一定首选JSON
6)面向对象的好处
a)每一个对象本质上就是一个命名空间(以此来模拟java和c#的包)
b)使用对象来隐藏数据。例如
function newClass(){ this.firstName = "frank"; lastName = "Zammetti"; } var nc = new newClass(); alert(nc.firstName); //弹出警告 alert(nc.lastName); //undefined
注意定义字段的不同:(对于方法也适用)
①任何使用this关键字定义的字段,都可以在类之外访问;
②任何没有使用this定义的字段,都只能在类的内部访问;
c)javascript的内置对象可以通过使用它们的原型来扩展(扩展内置对象要谨慎)
d)可以从其他的对象中“借”函数,并把它们添加到自己的对象中。例如:
通过输出newClass本身来显示newClass的firstName字段——实现一个toString()函数;
还要在它上面使用String对象中的toUpperCase()函数
function newClass(){ this.firstName = "frank"; this.changeUpper = String.toUpperCase; this.toString = function(){ alert(this.changeUpper(this.firstName)); } } var nc = new newClass(); alert(nc);
注意思想:调用了toString()函数,但不是作为String对象的一个方法。而是通过名为changeUpper()的newClass的属性指向String对象toUpperCase()方法的一个引用调用的。
好处是:当创建一个对象后又想创建一个新的,要使用原来的代码,只需引用其他类里的已存在的方法即可。
二、柔性衰减和不唐突的javascript
不唐突的javascript基本原则:
(1)保持javascript独立;(作者不完全同意)
(2)通常允许柔性衰减;
(3)从不使用浏览器嗅探脚本来判断一个浏览器的能力;(而是去检查对象的存在和对象的能力。一个好的习惯是在访问一个给定对象之前检查它是否存在)
(4)任何情况都不写浏览器不兼容的代码;
(5)合适的作用域变量;
对于变量,除了真正具有全局意义的,都应该定义成局部变量;
尤其在使用Ajax时,异步时,全局变量可能会引起许多难以调试的问题。一个糟糕例子:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>糟糕的变量的例子</title> <script> var fauxConstant = "123"; function badFunction(){ fauxConstant = "456"; } function goodFunction(){ var fauxConstant = "456" //与外部的全局变量不是一个东西。作为局部变量,外部无法访问 } function test(){ alert(fauxConstant); //输出“123” badFunction(); alert(fauxConstant); goodFunction(fauxConstant); alert(fauxConstant); } </script> </head> <body> <input type="button" onclick="test()"; value="click me!" /> </body> </html>
任何生命在函数内部、没有使用关键字var的变量,都将在这个函数外部存在
(6)对于可访问性,避免用鼠标事件触发的触发器(改成键盘事件)
三、不只是为了秀:关注可访问性
四、错误处理
类似于java和C#,自定义一个错误处理函数。
关于错误和异常:
错误——是一个条件,并不预期其发生,通常会导致程序崩溃(最好生成一个错误提示信息说程序无法继续)
异常——是一个状态。预期可能发生,程序应该能够以某种方法处理并继续运行。
错误实际上是一个伪装的异常,若做合理计划可以像处理其他异常一样处理——使代码更健壮
五、调试机制
六、浏览器扩展
firefox——1、venkman 2、FIrebug 3、Page Info 4、Web Developer
IE——1、httpwatch 2、Web Accessibility工具条 3、 IEDocMon 等等
七、 javascript库