13

我的术语有点不对劲,因此请在必要时进行更正。我想在 javascript 和“基类”中重载一个函数,以利用重载的方法以及继承的类来访问基类的方法。到目前为止,我想出了一个(工作的)jquery.extend()对象字面量组合,但这看起来并不漂亮。我想知道是否有更好的方法(可以使用 jquery)。

var Base = new function(args, m) {
   $.extend(this, m);
   var self = this;
   this.bar = function() {
     self.foo();
   }
   this.foo = function() {
     self.blah();
   }
   this.dosomething = function() {}
};

var Child = function(arg1) {
   $.extend(this, new Base(args, {
     blah: function() {
       self.dosomething()
     }
   }));
}
4

2 回答 2

20

What you're looking for is a way to share functionality across objects. This is exactly the sort of thing the JavaScript prototypical inheritance model excels at.

There's no need to use jQuery or other libraries in order to accomplish this. Consider going with the language's way of doing things.

Prototypes

In JavaScript, objects have 'prototypes'. When JavaScript looks for a method in an object that does not have it, it looks for it up on the prototype 'chain'. So all you need to do is override that functionality at a lower level on that chain.

This is explained in detail in the tutorial about it on MDN.

Your specific case

If I want a Base and Child class, where the Base has a method that Child needs to override, all we need to do is assign it anywhere lower in that chain.

The order of look-up is

Child Object --> Child's prototype (a Base object) --> Base's prototype (an Object)

For example, let's say you have a class Base

function Base(){

}
Base.prototype.bar = function() {
     //bar logic here
     console.log("Hello");
};
Base.prototype.foo= function() {
     //foo logic here
};

Function Child(){

}

Child.prototype = new Base();

I'd like Child to implement Bar differently, in which case I can do

Child.prototype.bar = function(){
   console.log("World");
}

Which results in

var a = new Base();
a.bar(); //outputs "Hello" to the console
var b = new Child();
b.bar(); //outputs "World" to the console
         //The Base instance that is the prototype of b has the bar method changed above

Note On Abstract Classes in JavaScript

Two of the primary reasons abstract methods inheritance is used in languages that are based on classical inheritance (like Java) is Polymorphism and code sharing.

In JavaScript neither are a problem. Code sharing can be done using prototypical inheritance just as easily. Moreoever, you can take just about any function and run it in another context. For example, I can even call the bar method of a Child object on an empty array by doing b.bar.call([]).

As for polymorphism JavaScript is a dynamic language with duck typing. This means it looks at objects based on their ability and not the way they were declared. If several objects have a method called bar I would have no problem calling that method on each of them if they are in an array or other collection. In Java that would require a common interface,type or ancestor.

For these reasons, things like abstract classes don't play a big role in JavaScript.

于 2013-03-09T01:18:15.463 回答
2

I recommend doing it the way CoffeeScript does it. You can put the first var declaration in a separate file to keep the code looking nice. As far as I know __extends is equivalent to $.extends

var __hasProp = {}.hasOwnProperty,
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };


var Fruit = (function() {

  function Fruit() {
    console.log("New fruit");
  }

  return Fruit;

})();

var Apple = (function(_super) {

  __extends(Apple, _super);

  function Apple() {
    console.log("New apple");
    Apple.__super__.constructor.apply(this, arguments);
  }

  return Apple;

})(Fruit);

var apple = new Apple();

Or, if you can use CoffeeScript, it looks like this:

class Fruit
  constructor: ->
    console.log "New fruit"

class Apple extends Fruit
  constructor: ->
    console.log "New apple"
    super
于 2013-03-09T01:15:53.330 回答