- 原文:Create Advanced Web Applications With Object-Oriented Techniques
- 译文(因文章较长,分多篇贴出,此篇为第2部分):
JavaScript函数是最初的类
在很多编程语言中,函数和对象通常被看作两个不同的事物。在JavaScript,他们的区别很模糊–一个JavaScript的函数就是一个关联了可执行代码的真正的对象。想想一个普通的函数是这样的:
function func(x) {
alert(x);
}
func("blah");
这就是在JavaScript中字义函数的方法。但我们也可以像下面那样定义一个函数,即定义一下匿名的函数然后赋值给一个变量func
var func = function(x) {
alert(x);
};
func("blah2");
或者甚至这样,使用Function 构造器:
var func = new Function("x", "alert(x);");
func("blah3");
这个例子告诉我们,函数本质就是一个支持function调用操作符的对象。最后一种使用Function构造器的定义方法并不常用,但为趣味性提供了可能。因为,可能你也意识到,对Function构造器来说,函数主体只是一个字符串参数。这就意味着在运行时你也可以随意构造函数了。
为了进一步证明函数就是一个对象,你可以试着给它添加一个属性,就像给其它JavaScript对象一样:
function sayHi(x) {
alert("Hi, " + x + "!");
}
sayHi.text = "Hello World!";
sayHi["text2"] = "Hello World... again.";
alert(sayHi["text"]); // displays "Hello World!"
alert(sayHi.text2); // displays "Hello World... again."
作为一个对象,函数同样可以被赋值给变量,作为变量传递给其它函数,作为其它函数的返回值,以及作为其它对象的属性或数组的元素等。演算1 提供了这样的一个例子。
根据这个思路,为对象添加方法就像选择一个名字然后把一个函数赋值给这个名字一样容易。现在我在一个对象中通过赋值匿名函数的方式定义了三个函数:
var myDog = {
"name" : "Spot",
"bark" : function() { alert("Woof!"); },
"displayFullName" : function() {
alert(this.name + " The Alpha Dog");
},
"chaseMrPostman" : function() {
// implementation beyond the scope of this article
}
};
myDog.displayFullName();
myDog.bark(); // Woof!
函数displayFullName里面”this”关键字的使用方法对我们之中的C++/C#开发者最熟悉不过了–它是调用这个函数的对象的引用(使用Visual Basic的开发者也应该熟悉–在Visual Basic中它称为”Me”)。所以在上例中,displayFullName函数中”this”的值就是myDog对象。”this”的值不是静态的。调用不同的对象,它的值就会指向那个对象,就像 演算2 所示范那样。
演算2的最后一行展示了把函数作为对象的方法调用的另一种方式。切记,JavaScript的函数就是一个对象。每一个函数都有一个名为call的方法,使得函数在调用时,会成为特定对象的方法来调用,而这个特定对象就是传到call方法的第一个参数。就是说,无论什么对象,只要作为call方法中的第一个参数,都会成为此函数的this的值。这是一个调用基于对象构造器的一个很有用的技巧,这点我们稍后会讨论到。
有一点必须谨记,那就是一个带有this关键字的函数,在它没有自己的归属对象前,千万不要调用它。如果你这样做,就会破坏到最上层的全局命名空间,因为这样的调用中的”this”会指向到全局对象,这可是你的应用程序中的大灾难啊。例如下面的一个例子,它改变了JavaScript的全局函数isNaN。这样做显然是不推荐的!
alert("NaN is NaN: " + isNaN(NaN));
function x() {
this.isNaN = function() {
return "not anymore!";
};
}
// alert!!! trampling the Global object!!!
x();
alert("NaN is NaN: " + isNaN(NaN));
到这里,我们看到过几种建立对象,和完善对象属性和函数的方法。但如果你注意到在上面的代码片段中,属性和方法都是hardcoded在对象定义自身(有待修正)。万一你想在对象的建立中得到更多的控制呢?例如基于一些参数计算对象属性值,或者初始化一些必须在运行时才有值的属性(有待修正),又或者为对象建立更多的实例等(有待修正),这些都是常见的需求了。
在C#,我们使用classes来实例化对象。但JavaScript不同,因为它没有classes。在下一个部分会讲到一个取代classes的方法,利用函数来实现构造器,同时,我们会用到操作符”new”。
To be Continued…


Leave a Reply