js 面向对象的技术创建高级 Web 应用程序(2)


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!


C++/C# 开发人员应当很熟悉 displayFullName 函数中使用的“this”关键字 — 它引用一个对象,通过对象调用方法(使用 Visual Basic 的开发人员也应当很熟悉它,它在 Visual Basic 中叫做“Me”)。因此在上面的示例中,displayFullName 中的“this”的值是 myDog 对象。但是,“this”的值不是静态的。通过不同对象调用“this”时,它的值也会更改以便指向相应的对象,如图 2 所示。
“this”随对象更改而更改

复制代码 代码如下:


function displayQuote() {
// the value of “this” will change; depends on
// which object it is called through
alert(this.memorableQuote);
}
var williamShakespeare = {
“memorableQuote”: “It is a wise father that knows his own child.”,
“sayIt” : displayQuote
};
var markTwain = {
“memorableQuote”: “Golf is a good walk spoiled.”,
“sayIt” : displayQuote
};
var oscarWilde = {
“memorableQuote”: “True friends stab you in the front.”
// we can call the function displayQuote
// as a method of oscarWilde without assigning it
// as oscarWilde's method.
//”sayIt” : displayQuote
};
williamShakespeare.sayIt(); // true, true
markTwain.sayIt(); // he didn't know where to play golf
// watch this, each function has a method call()
// that allows the function to be called as a
// method of the object passed to call() as an
// argument.
// this line below is equivalent to assigning
// displayQuote to sayIt, and calling oscarWilde.sayIt().
displayQuote.call(oscarWilde); // ouch!


图 2 中的最后一行表示的是将函数作为对象的方法进行调用的另一种方式。请记住,JavaScript 中的函数是对象。每个函数对象都有一个名为 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));


到这里,我们已经介绍了如何创建对象,包括它的属性和方法。但如果注意上面的所有代码 段,您会发现属性和方法是在对象定义本身中进行硬编码的。但如果需要更好地控制对象的创建,该怎么做呢?例如,您可能需要根据某些参数来计算对象的属性 值。或者,可能需要将对象的属性初始化为仅在运行时才能获得的值。也可能需要创建对象的多个实例(此要求非常常见)。
在 C# 中,我们使用类来实例化对象实例。但 JavaScript 与此不同,因为它没有类。您将在下一节中看到,您可以充分利用这一情况:函数在与“new”运算符一起使用时,函数将充当构造函数。
构造函数而不是类
前 面提到过,有关 JavaScript OOP 的最奇怪的事情是,JavaScript 不像 C# 或 C++ 那样,它没有类。在 C# 中,在执行类似下面的操作时:
Dog spot = new Dog();
将返回一个对象,该对象是 Dog 类的实例。但在 JavaScript 中,本来就没有类。与访问类最近似的方法是定义构造函数,如下所示:
代码

复制代码 代码如下:


function DogConstructor(name) {
this.name = name;
this.respondTo = function(name) {
if(this.name == name) {
alert(“Woof”);
}
};
}
var spot = new DogConstructor(“Spot”);
spot.respondTo(“Rover”); // nope
spot.respondTo(“Spot”); // yeah!


那么,结果会怎样呢?暂时忽略 DogConstructor 函数定义,看一看这一行:
var spot = new DogConstructor(“Spot”);
“new”运算符执行的操作很简单。首先,它创建一个新的空对象。然后执行紧随其后的函数调用,将新的空对象设置为该函数中“this”的值。换句话说, 可以认为上面这行包含“new”运算符的代码与下面两行代码的功能相当:

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdssds.html