2008-10-22 67 views
9

我一直在试图学习如何添加测试到现有的代码 - 目前阅读阅读Working Effectively With Legacy Code。我一直在尝试应用JavaScript中的一些原则,现在我试图提取一个接口。有没有一种“正确”的方式来在JavaScript中进行继承?如果是这样,那是什么?

在寻找在JavaScript中创建接口,我找不到很多 - 我发现有关继承,似乎他们有几种不同的方式。 (有些人创建了自己的基类来提供有用的方法来使继承更容易,一些使用函数,一些使用原型)。

什么是正确的方法?有一个在JavaScript中提取接口的简单示例?

回答

13

有没有权利正确的方式,因为这么多人做这么多不同的事情..有许多有用的模式。

Crockford暗示你“随谷物走”,或者以对应于javascript原型性质的方式写javascript。

当然,他继续表明,Netscape建议的原始模型实际上已经被破坏。他将其标记为“伪古典”,并指出了遵循该模型所涉及的许多错误方向和不必要的复杂性。

他写了“对象”函数作为补救措施(现在称为Object.create())。它允许一些非常强大的原型模式。

当你不得不使用遗留的javascript时,开发干净的界面并不总是很容易,特别是当你处理大型系统时,通常包括多个库,并且每个实现独特的样式和不同的继承模式。一般来说,我认为继承的“正确方法”是允许您编写一个干净的界面,该界面在遗留代码的上下文中表现良好,但也允许您重构并消除一段时间内的旧依赖关系。

考虑到主要库模式之间的差异,我发现在我自己的工作中最成功的路线是让我的接口完全独立于库接口。如果有用的话,我会使用一个库或模块,但不会被绑定到它。这使我可以重构很多代码,逐步淘汰一些库,并将库用作脚手架,这些脚手架可以稍后进行优化。

沿着这些路线,我写了灵感来自Crockford寄生继承模式的接口。这简直就是一场胜利。在硬币的另一面,我相信你可能会挑选一个图书馆,在你的团队中执行它,并遵守它的继承模式和它的接口约定。

+2

怎么样的联系? – pc1oad1etter 2009-09-17 13:20:08

3

还可以查看Dean Edwards的Base.js。你可以看看它here,博客文章是不言自明的。

5

您正在看两件不同的事情。

首先你有接口。实现这一点的最可接受的方式是通过鸭子打字(“如果它看起来像一只鸭子,鸭子像鸭子那么它是一只鸭子”)。这意味着如果一个对象实现了接口的一组方法,那么它就是那个接口。您可以通过定义一个接口的方法名称来实现这一点。然后检查一个对象是否实现了这个干涉,如果它实现了这些方法。这里是我掀起的代码示例:

function Implements(obj, inter) 
{ 
    var len = inter.length, i = 0; 
    for (; i < len; ++i) 
    { 
     if (!obj[inter[i]]) 
      return false; 
    } 
    return true; 
} 

var IUser = ["LoadUser", "SaveUser"]; 

var user = { 
     LoadUser : function() 
     { 
      alert("Load"); 
     }, 

     SaveUser : function() 
     { 
      alert("Save"); 
     } 
    }; 

var notUser = { 
     LoadUser : function() 
     { 
      alert("Load"); 
     } 
    }; 

alert(Implements(user, IUser)); 
alert(Implements(notUser, IUser)); 

现在你有继承。 JS没有内置的继承;所以你必须手动实现它。这只是将一个对象的属性“复制”到另一个对象的问题。下面是另一个代码示例(并非十全十美,但它说明了这一点):

function InheritObject(base, obj) 
{ 
    for (name in base) 
    { 
     if (!obj[name]) 
      obj[name] = base[name]; 
    } 
} 

var Base = { 
     BaseFunc : function() { alert("BaseFunc from base"); }, 
     InheritFunc : function() { alert("InheritFunc from base"); } 
    } 

var Inherit = { 
     InheritFunc : function() { alert("InheritFunc from inherit"); }, 
     AnotherFunc : function() { alert("AnotherFunc from inherit"); } 
    } 

InheritObject(Base, Inherit); 

Inherit.InheritFunc(); 
Inherit.BaseFunc(); 
Inherit.AnotherFunc(); 

Base.BaseFunc(); 
Base.InheritFunc(); 

你可能想看看http://www.mootools.net。它有我最喜欢的类实现。你也一定要看看“专业的Javascript设计模式”

http://www.amazon.com/JavaScript-Design-Patterns-Recipes-Problem-Solution/dp/159059908X

这本书介绍了有关如何在JavaScript模仿OOP良好的细节。

+0

+1简单明了的解释! – 2010-03-31 14:44:42

6

JavaScript中没有类,只有对象。
但如果你坚持模拟类基于面向对象的模型,你可以使用这个:

 
function ChildClass() { 
    ParentClass.call(this); 
    // Write the rest of your constructor function after this point. 
}; 
ChildClass.prototype = jQuery.extend({}, ParentClass.prototype, ChildClass.prototype); 

jQuery.extend是从jQuery库中的“浅拷贝”功能。您可以用任何其他对象复制/克隆功能来替换它。

+1

第一句话不能再强调 – Claudiu 2010-07-01 16:26:24

0

原型提供自己拿上继承,从http://www.prototypejs.org/api/class/create

var Animal = Class.create({ 
    initialize: function(name, sound) { 
    this.name = name; 
    this.sound = sound; 
    }, 

    speak: function() { 
    alert(this.name + " says: " + this.sound + "!"); 
    } 
}); 

// subclassing Animal 
var Snake = Class.create(Animal, { 
    initialize: function($super, name) { 
    $super(name, 'hissssssssss'); 
    } 
}); 
相关问题