简体   繁体   English

在JavaScript中有继承的“正确”方法吗?如果是这样,它是什么?

[英]Is there a “right” way to do inheritance in JavaScript? If so, what is it?

I have been trying to learn how to add testing to existing code -- currently reading reading Working Effectively With Legacy Code . 我一直在努力学习如何为现有代码添加测试 - 目前阅读阅读阅读有效使用遗留代码 I have been trying to apply some of the principles in JavaScript, and now I'm trying to extract an interface. 我一直在尝试在JavaScript中应用一些原则,现在我正在尝试提取一个接口。

In searching for creating interfaces in JavaScript, I can't find a lot -- and what I find about inheritance seems like their are several different ways. 在JavaScript中搜索创建接口时,我找不到很多 - 我发现继承的内容似乎有几种不同的方式。 (Some people create their own base classes to provide helpful methods to make it easier to do inheritance, some use functions, some use prototypes). (有些人创建自己的基类,以提供有用的方法,使其更容易进行继承,有些使用函数,有些使用原型)。

What's the right way? 什么是正确的方法? Got a simple example for extracting an interface in JavaScript? 有一个简单的例子用于在JavaScript中提取界面?

There's no definitive right way , because so many people are doing so many different things.. There are many useful patterns. 没有明确的正确方法 ,因为有很多人在做很多不同的事情。有很多有用的模式。

Crockford suggests that you "go with the grain", or write javascript in a way that corresponds to javascript's prototypal nature. 克罗克福德建议你“顺其自然”,或者以与javascript的原型性质相对应的方式编写javascript。

Of course, he goes on to show that the original model that Netscape suggested is actually broken. 当然,他继续表明Netscape建议的原始模型实际上已经被破坏了。 He labels it "pseudoclassical", and points out a lot of the misdirection and unnecessary complexity that is involved in following that model. 他将其标记为“伪经典”,并指出了遵循该模型所涉及的许多误导和不必要的复杂性。

He wrote the "object" function as a remedy (now known as Object.create() ). 他将“对象”函数编写为补救措施(现在称为Object.create())。 It allows for some very powerful prototypal patterns. 它允许一些非常强大的原型模式。

It's not always easy to do develop a clean interface when you have to work with legacy javascript, especially not when you're dealing with large systems, usually including multiple libraries, and each implementing a unique style and different inheritance pattern. 当你必须使用传统的javascript时,开发一个干净的界面并不总是那么容易,尤其是当你处理大型系统时,通常包括多个库,每个系统都实现了独特的风格和不同的继承模式。 In general, I'd say that the "right way" to do inheritance is the one which allows you to write a clean interface which behaves well in the context of your legacy code, but also allows you to refactor and eliminate old dependencies over time. 一般来说,我要说继承的“正确方法”是允许你编写一个干净的接口,它在遗留代码的上下文中表现良好,但也允许你重构并消除旧的依赖关系。 。

Considering the differences between the major library patterns, I've found that the most successful route to take in my own work is to keep my interfaces independent of the library interfaces entirely. 考虑到主要库模式之间的差异,我发现在我自己的工作中最成功的路径是保持我的接口完全独立于库接口。 I'll use a library or module if it's helpful, but won't be bound to it. 如果它有用,我将使用库或模块,但不会受其约束。 This has allowed me to refactor a lot of code, phase out some libraries, and use libraries as scaffolding which can be optimized later. 这使我能够重构大量代码,逐步淘汰一些库,并使用库作为脚手架,以后可以进行优化。

Along these lines, I've written interfaces that were inspired by Crockford's parasitic inheritance pattern. 沿着这些方向,我编写了受Crockford寄生继承模式启发的界面。 It's really a win for simplicity. 这真的是简单的胜利。

On the other side of the coin, I'm sure you could argue for picking a library, enforcing it across your team, and conforming to both its inheritance patterns and its interface conventions. 另一方面,我确信您可以争取选择一个库,在整个团队中执行它,并遵守其继承模式和接口约定。

There are no class in javascript, only objects. javascript中没有类,只有对象。
But if you insist on emulating the class based object-oriented model you can use this: 但是如果你坚持模仿基于类的面向对象模型,你可以使用:

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 is a 'shallow copy' function from the jQuery library. jQuery.extend是jQuery库中的“浅拷贝”函数。 You can replace it with any other object copying/cloning function. 您可以将其替换为任何其他对象复制/克隆功能。

You are looking at two different things. 你正在看两件不同的事情。

First you have interfaces. 首先你有接口。 The most accepted way of implementing this is though Duck Typing ("if it looks like a duck and quacks like a duck then it is a duck"). 实现这一目标最常被接受的方式是Duck Typing(“如果它看起来像鸭子,嘎嘎叫像鸭子那么它就是鸭子”)。 This means that if an object implements a set of methods of the interface then it is that interface. 这意味着如果一个对象实现了一组接口方法,那么它就是那个接口。 You implement this by having an array of method names that define an interface. 您可以通过定义一个接口的方法名数组来实现它。 Then to check if an object implements that interfece you see if it implements those methods. 然后检查一个对象是否实现了那个interfece,你看它是否实现了那些方法。 Here is a code example I whipped up: 这是一个我掀起的代码示例:

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));

Now you have inheritance. 现在你有了继承权。 JS has no inheritance built in; JS没有内置的继承; so you have to implement it manually. 所以你必须手动实现它。 This is just a matter of "copying" the properties of one object to another. 这只是将一个对象的属性“复制”到另一个对象的问题。 Here is another code sample (not perfect but it demonstrates the point): 这是另一个代码示例(不完美,但它证明了这一点):

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();

You probably want to look at http://www.mootools.net . 你可能想看看http://www.mootools.net It has my favorite implementation of Classes. 它有我最喜欢的Classes实现。 You also definitely want to check out "Pro Javascript Design Patterns" 你也一定想看看“Pro Javascript Design Patterns”

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

This book goes into good detail about how to emulate OOP in javascript. 本书详细介绍了如何在javascript中模拟OOP。

Also check out Dean Edwards' Base.js. 还可以查看Dean Edwards的Base.js. You can have a look at it here , the blog post is self-explanatory. 你可以看看它在这里的博客文章是不言自明。

Prototype offers its own take on inheritance, from http://www.prototypejs.org/api/class/create : Prototype提供了自己的继承,来自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');
  }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM