即使没有正式的设计模式,也可以发布代码。
我已经写了很多JavaScript,但我没有将很多面向对象的模式应用到我所做的事情上,我确定我错过了很多东西。
继承
我使用的继承符号基于ExtJS 3,我发现它非常接近模拟Java中的经典继承。其基本原理如下:
// Create an 'Animal' class by extending
// the 'Object' class with our magic method
var Animal = Object.extend(Object, {
move : function() {alert('moving...');}
});
// Create a 'Dog' class that extends 'Animal'
var Dog = Object.extend(Animal, {
bark : function() {alert('woof');}
});
// Instantiate Lassie
var lassie = new Dog();
// She can move and bark!
lassie.move();
lassie.bark();
命名空间
我也同意Eric Miraglia的看法,坚持使用命名空间,因此上面的代码应该在其自己的上下文之外运行,这对于你希望你的代码作为许多并发框架/库在浏览器窗口中执行的其中之一至关重要。
这意味着,唯一访问window对象的方法是通过你自己的命名空间/模块对象:
// Create a namespace / module for your project
window.MyModule = {};
// Commence scope to prevent littering
// the window object with unwanted variables
(function() {
var Animal = window.MyModule.Animal = Object.extend(Object, {
move: function() {alert('moving...');}
});
// .. more code
})();
接口
您还可以利用更高级的面向对象编程构造,例如接口,以增强应用程序设计。 我对这些的方法 是增强 Function.prototype
以获得以下类似的表示:
var Dog = Object.extend(Animal, {
bark: function() {
alert('woof');
}
// more methods ..
}).implement(Mammal, Carnivore);
OO模式
就Java中的“模式”而言,我只发现了单例模式(对于缓存非常有用)和观察者模式,用于事件驱动功能,例如当用户单击按钮时分配某些操作。
利用观察者模式的一个示例是:
// Instantiate object
var lassie = new Animal('Lassie');
// Register listener
lassie.on('eat', function(food) {
this.food += food;
});
// Feed lassie by triggering listener
$('#feeding-button').click(function() {
var food = prompt('How many food units should we give lassie?');
lassie.trigger('eat', [food]);
alert('Lassie has already eaten ' + lassie.food + ' units');
});
这只是我 OO JS 技巧袋里的几个小窍门,希望对您有用。
如果您打算走这条路,我建议您阅读 Douglas Crockford 的 Javascript: the Good Parts。这是一本关于此类内容的杰出书籍。
我是模块模式的粉丝。它是实现可扩展、非依赖(大多数情况下)框架的一种方式。
示例:
框架Q
的定义如下:
var Q = {};
添加一个函数:
Q.test = function(){};
这两行代码一起用于形成模块。模块的理念是它们都扩展了某个基础框架,在这种情况下是Q
,但彼此不依赖(如果设计正确),可以以任意顺序包含。
在一个模块中,如果该框架对象不存在,你首先需要创建它(这是单例模式的一个示例):
if (!Q)
var Q = {};
Q.myFunction = function(){};
这样,您可以在不同的文件中有多个模块(例如上面的一个),并按任意顺序包含它们。其中任何一个都将创建框架对象,然后扩展它。无需手动检查框架是否存在。然后,要检查自定义代码中是否存在模块/函数:
if (Q.myFunction)
Q.myFunction();
else
// Use a different approach/method
Q
框架变量更污染,还是成堆的函数和变量更污染呢? - Chris Laplante单例模式通常非常有助于“封装”和组织代码。您甚至可以更改可访问性。
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
$('#nav').click(function() {
$(this).css('color','#f00').fadeOut();
});
在JavaScript世界中,一种有用的模式是链式编程模式,最初由LINQ流行起来,并在jQuery中使用。
这种模式使我们能够以链式方式调用类的不同方法。
该模式的主要结构如下:
var Calaculator = function (init) {
var result = 0;
this.add = function (x) { result += (init + x); return this; };
this.sub = function (x) { result += (init - x); return this; };
this.mul = function (x) { result += (init * x); return this; };
this.div = function (x) { result += (init / x); return this; };
this.equals = function (callback) {
callback(result);
}
return this;
};
new Calaculator(0)
.add(10)
.mul(2)
.sub(5)
.div(3)
.equals(function (result) {
console.log(result);
});
这个模式的关键思想在于this
关键字,它可以访问计算器函数中的其他公共成员。
pre
和post
工作以满足您的需求,并在没有指定特定参数的情况下传递您的默认参数。