主要内容
静态函数与实例方法
在开始算法 #3 (朝向光标加速) 之前,们需要涉及到向量和
PVector
对象的一个相当重要方面:使用静态函数和实例方法之间的区别。暂时忘记向量,请看下面的代码:
var x = 0;
var y = 5;
x = x + y;
很简单吧?
x
的值为 0,加上 y
,那么 x
现在等于 5。我们可以很容易在 PVector
对象中写出相应功能的代码。var v = new PVector(0,0);
var u = new PVector(4,5);
v.add(u);
向量 v 的值为 (0, 0),再加上 u,现在 v 等于 (4, 5)。很简单,对吧?
我们再看另一个例子:
var x = 0;
var y = 5;
var z = x + y;
x
的值为 0,把它加上 y
,并将结果存储在一个新变量 z
中。这样的话 x
的值不会改变,y 也不会改变!这似乎是一个微不足道的问题,在数学方面也很直观。然而,在PVector
对象中可没那么简单,我们来试写相应的代码。var v = new PVector(0,0);
var u = new PVector(4,5);
var w = v.add(u); // 别被唬住了,这是不正确的!!!
上面的代码看起来没问题,但
PVector
对象可不能这么写。我们来看看 add()
方法的定义...PVector.prototype.add = function(v) {
this.x = this.x + v.x;
this.y = this.y + v.y;
};
...这个代码不能实现我们的目标。首先,它不会返回一个新的
PVector
(代码中没有 return
语句),其次,它改变了调用它的 PVector
的值。为了将两个 PVector
对象相加并将结果返回为新的 PVector
,我们必须使用 “静态”add()
函数。“静态”函数是在对象上定义的函数,但它不会更改对象的属性。那么为什么还要在对象上定义它呢?通常情况下,它与对象有关,因此将其附加到该对象是合乎逻辑的。它对对象的影响更像是一个命名空间。例如,
PVector
上的所有静态函数都对传入的 PVector
对象执行某种操作,并通常有返回值。我们当然也可以在全局定义这些函数,但用静态函数这个办法,我们可以避开全局函数,并更好的对相关功能进行分组。我们来做一对比,下面是使用实例方法
add()
:v.add(u);
这行代码修改了
v
的值,所以我们不需要保存一个返回值。相反,下面是如何使用静态函数 add()
:var w = PVector.add(v, u);
如果我们不将该函数的结果保存到变量中,那么这行代码将是无用的,因为静态函数不会更改对象本身。
PVector
的静态函数允许我们对 PVector
对象执行通常的数学运算,而不会改动传入的 PVectors
。下面是我们编写静态函数
add()
的方法:PVector.add = function(v1, v2) {
var v3 = new PVector(v1.x + v2.x, v1.y + v2.y);
return v3;
};
这里有几个区别:
- 静态函数直接定义在对象上,而不是原型对象上
- 在函数中没有用
this
关键字 - 函数有返回值
PVector 对象有静态函数版本的
add()
、sub()
、mult()
和 div()
。也有无对应实例方法的其他静态函数,如 angleBetween()
、dot()
和 cross()
。在用 PVector
编写程序时,这些静态函数很常用。“自然模拟”系列课程是由 Daniel Shiffman 的 "编程的本质" 衍生而来,基于 知识共享 著名-非商用性 3.0 本地化许可协议。