使用面向对象的技术创建高级 Web 应用程序

本文来自:

使用面向对象的技术创建高级 Web 应用程序

本文讨论:

  • JavaScript 是基于原型的语言
  • 用 JavaScript 进行面向对象的编程
  • JavaScript 编码技巧
  • JavaScript 的未来
本文使用了以下技术:
  • JavaScript

面向对象编程 (OOP) 是一种流行的编程方法,很多 JavaScript 库中都使用这种方法,以便更好地管理和维护基本代码。JavaScript 支持 OOP,但它支持 OOP 的方式非常不同,因此主要使用这些语言的开发人员开始可能会觉得在 JavaScript 中使用 OOP 很奇怪而且不直观。我写本文就是为了深入讨论 JavaScript 语言实际上如何支持面向对象编程,以及您如何使用这一支持在 JavaScript 中高效地进行面向对象开发。

JavaScript 对象是词典

在谈论对象时,是指类或结构的实例。对象有不同的属性和方法,具体取决于将它们实例化的模板(即类)。而 JavaScript 对象却不是这样。在 JavaScript 中,对象只是一组名称/值对,就是说,将 JavaScript 对象视为包含字符串关键字的词典。我们可以使用熟悉的“.”(点)运算符或“[]”运算符,来获得和设置对象的属性,这是在处理词典时通常采用的方法。

以下代码段:

var userObject = new Object();
userObject.lastLoginTime = new Date();
alert(userObject.lastLoginTime); 
  的功能与下面的代码段完全相同:

var userObject = {}; // equivalent to new Object()
userObject[“lastLoginTime”] = new Date();
alert(userObject[“lastLoginTime”]);
 我们还可以直接在 userObject 的定义中定义 lastLoginTime 属性,如下所示:

var userObject = { “lastLoginTime”: new Date() };
alert(userObject.lastLoginTime);
 
JavaScript 对象/词典只接受字符串关键字。这些示例还显示 JavaScript 对象比 C++ 或 C# 对象具有更大的可延展性。您不必预先声明属性 lastLoginTime — 如果 userObject 没有该名称的属性,该属性将被直接添加到 userObject。如果记住 JavaScript 对象是词典,您就不会对此感到吃惊了,毕竟,我们一直在向词典添加新关键字(和其各自的值)。
这样,我们就有了对象属性。对象方法呢?同样,JavaScript 与 C++/C# 不同。若要理解对象方法,首先需要仔细了解一下 JavaScript 函数。
 

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 构造函数的 String 参数。这意味着,您可以在运行时构造任意函数
为了进一步演示函数是对象,您可以像对其他任何 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.”

作为对象,函数还可以赋给变量、作为参数传递给其他函数、作为其他函数的值返回,并可以作为对象的属性或数组的元素进行存储等等。例子如下:
// assign an anonymous function to a variable
var greet = function(x) {
    alert(“Hello, “ + x);
};
greet(“MSDN readers”);

// passing a function as an argument to another
function square(x) {
    return x * x;
}
function operateOn(num, func) {
    return func(num);
}
// displays 256
alert(operateOn(16, square));

// functions as return values
function makeIncrementer() {
    return function(x) { return x + 1; };
}
var inc = makeIncrementer();
// displays 8
alert(inc(7));

// functions stored as array elements
var arr = [];
arr[0] = function(x) { return x * x; };
arr[1] = arr[0](2);
arr[2] = arr[0](arr[1]);
arr[3] = arr[0](arr[2]);
// displays 256
alert(arr[3]);

// functions as object properties
var obj = { “toString” : function() { return “This is an object.”; } };
// calls obj.toString()
alert(obj);

记住这一点后,向对象添加方法将是很容易的事情:只需选择名称,然后将函数赋给该名称。因此,我通过将匿名函数分别赋给相应的方法名称,在对象中定义了三个方法:
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!
函数中使用的“this”关键字 — 它引用一个对象,通过对象调用方法。因此在上面的示例中,displayFullName 中的“this”的值是 myDog 对象。
但是,“this”的值不是静态的。通过不同对象调用“this”时,它的值也会更改以便指向相应的对象,如下所示:
最后一行表示的是将函数作为对象的方法进行调用的另一种方式。请记住,JavaScript 中的函数是对象。每个函数对象都有一个名为 call 的方法,它将函数作为第一个参数的方法进行调用。
就是说,作为函数第一个参数传递给 call 的任何对象都将在函数调用中成为“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!

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



 

  



 
posted @ 2011-06-27 23:09  wkylin  阅读(233)  评论(0编辑  收藏  举报