实用的JavaScript面向对象设计模式示例

81
你的应用程序中使用了哪些面向对象设计模式的javascript,并且为什么使用它们?
即使没有正式的设计模式,也可以发布代码。
我已经写了很多JavaScript,但我没有将很多面向对象的模式应用到我所做的事情上,我确定我错过了很多东西。

你可能没有看到过传统意义上的面向对象编程(classical OOP),但你很可能已经使用了基于原型的面向对象编程(prototypical OOP)的功能,只是没有真正意识到它。 - dave
我其实有时候会意识到自己在使用面向对象编程 - 我想要开始更有意识地使用面向对象编程,因为我想更加谨慎地使用它。 - meow
我投票关闭此问题,因为它只是在询问其他人在他们的代码中做了什么的清单,与主题无关。 - Almo
7个回答

54

不错!柯里看起来是一种更聪明的方式来做我试图做的一些泛化。已经在使用模块和记忆化的简单形式,但需要研究这些示例来推动我目前的做法。你最常使用哪些? - meow
@明:很可能是模块模式。非常容易实现和理解,而且它还带有一些很酷的功能,包括命名空间和私有变量/方法。 - Daniel Vassallo

26

继承

我使用的继承符号基于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。这是一本关于此类内容的杰出书籍。


20

我是模块模式的粉丝。它是实现可扩展、非依赖(大多数情况下)框架的一种方式。

示例:

框架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

1
这看起来非常有用。你在代码中如何使用它?谢谢分享! - meow
我最近在一个项目中使用了它,该项目中我有单独的JavaScript文件用于通用函数、UI和另外两个专门机制。所有文件都向同一框架添加函数(使用我上面展示的方法定义),并像我上面所做的那样调用函数。 - Chris Laplante
这种技术的主要用途之一是避免全局命名空间的污染。是单个 Q 框架变量更污染,还是成堆的函数和变量更污染呢? - Chris Laplante

6

太棒了 - 这是我一直在使用的!但这几乎就是我对JavaScript面向对象编程的全部了。 ;) - meow

5
我非常喜欢jQuery的方法链模式,它允许您在一个对象上调用多个方法。这使得在一行代码中执行多个操作变得非常容易。
例如:
$('#nav').click(function() {
   $(this).css('color','#f00').fadeOut();
});

没错 - 同意!你之前开发过自己的定制方法,以这种方式工作吗? - meow

3

在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关键字,它可以访问计算器函数中的其他公共成员。


3
我非常喜欢使用jQuery插件的装饰者模式。与其修改插件以满足您的需求,不如编写一个自定义插件,只需转发请求并添加附加参数和功能。
例如,如果您需要始终传递一组默认参数,并且需要与业务逻辑相关的略微不同的行为,则编写一个插件,执行必要的prepost工作以满足您的需求,并在没有指定特定参数的情况下传递您的默认参数。
这样做的主要好处是,您可以更新库而不必担心移植库更改。您的代码可能会出现问题,但至少有机会不会出现问题。

这听起来是个好主意。你有实际的代码示例来进行扩展吗?即使是一个简单的例子也会对大家有很大帮助。 - meow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接