Javascript入门
hanlray@gmail.comReversion:1.0 Date: 06/07/01
对受C++/Java这种强类型语言影响的程序员,刚开始接触javascript这种语法宽松的语言的时候也许会有点不适应,我想主要在于以下几点:
1. 惯用法的使用
看看javascript怎么表达一个class:
function Car(color, doors, mpg) { this.color = color; this.doors = doors; this.mpg = mpg; this.drivers = new Array("Mike", "Sue"); } Car.prototype.showColor = function() { alert(this.color); }; var car1 = new Car("red", 4, 23); var car2 = new Car("blue", 3, 25);
和Java比较一下:
class Car { public String color = "red"; public int doors = 4; public int mpg = 23; public Car(String color, int doors, int mpg) { this.color = color; this.doors = doors; this.mpg = mpg; } public void showColor() { System.out.println(color); } }
就表现形式而言,两者区别不大,关键在于java是用语言的基础设施来表达的,而javascript使用的是一种惯用法。孰优孰劣?不同的人可能会有不同的看法,不过这似乎并不重要,因为两者都能容易地表达我们想要的概念;实际上两者也没有多大差别,因为一种惯用法也可能被吸收入语言中而演化为语言的基础设施,想想C#的语法糖吧。
2. function也是object
和java一样,所有的reference type都继承自Object,function也是一种reference type,它的class是Function。如何定义一个function?
最熟悉的方式:
function sayHi(name, message) { alert("Hello " + name + "," + messgae); }
另一种方式:
var sayHi = new Function("name", "message", "alert(/"Hello /" + name + /", /" + message + /");");
还可以:
sayHi = function(name, message) { alert("Hello " + name + "," + message); }
这三种方式都创建了一个Function的实例,并以变量sayHi来引用它,第一种方式的function name就是其产生的function实例的引用。
3. 晚绑定语言
看Car的例子,当var car1 = new Car时发生了什么?首先将会创建一个Object实例,接着把Car的prototype里的属性赋值给这个Object实例,由于在Car函数的下面我们已经给Car的prototype设置了showColor属性,因此新创建的Object实例也将会有showColor属性,最后执行Car的函数体,在函数体里用this访问这个Object实例,从而设置了其他的属性。
Car为什么会有prototype属性?因为Car是一个Function instance,而Function是一个reference type,所有的reference type都继承自Object,Object有个prototype属性,类型是Object。
从这里可以看到,car1之所以具有我们期望的Car的接口,完全是因为我们直接或间接地在car1对象上设置了Car的属性,而在Java之类的语言里,这个过程我们是看不到的(如果有的话),通常我们认为在构造函数里这些属性都是已经存在的。这也就是晚绑定语言的特点:一个对象的属性只有在给它赋值后才存在,要使某个对象有我们期望的接口,就必须通过某种方式给它设置该接口的属性,这里的惯用法就是这么一种方式,当然这个工作也也可以在语言层面完成,就像python所作的那样。