3

我有一个 BaseService 可以轻松地与我的服务器端 API 交互,我想为特定的 API 资源“子类化”它。有什么比直接继承所有辛苦工作的 BaseService 更好的方法呢?

所以,我已经设置好了,它工作了,但是我不完全确定我这样做是正确的,因为我已经读到 JS 中有多种类型的继承。这是我发现以不同方式执行的一些代码的链接:https ://github.com/roblevintennis/Testing-and-Debugging-JavaScript/blob/master/code/objects/lib/js_inheritance.js

这就是我的做法。为简洁起见,我省略了函数体。

我的BaseService实现将从中继承的 , 。

BaseService.prototype.get = function (resource, data, parameterOverrides) {
    return aPromisedLandOfDragons();
};

BaseService.prototype.post = function (resource, data, parameterOverrides) {
    return aPromisedLandOfDragons();
};

BaseService.prototype.put = function (resource, data, parameterOverrides) {
    return aPromisedLandOfDragons();
};

BaseService.prototype.destroy = function (resource, data, parameterOverrides) {
    return aPromisedLandOfDragons();
};

function BaseService(resource) {
    this.apiEndpoint = "/api/" + resource + "/";
}

这是一个可以直接使用的实现BaseService,将API资源传递给构造函数。

AccountService.prototype = new BaseService("Accounts");
AccountService.prototype.getAll = function(searchString) {
    // Uses the BaseService method. Lovely!
    return this.get(null, {
        searchString: searchString || ""
    });
};

function AccountService() {

}

所以,我的问题是(希望它不会因为过于本地化而关闭):这是在 JavaScript 中进行继承的好方法吗?它是否有任何可以显着改善的性能影响?

顺便说一句:如果我想直接覆盖基类中的方法,例如.get,是否可以这样做,同时仍然能够调用基类的实现?

PS:我知道从技术上讲,JavaScript 中没有类之类的东西,但请耐心等待。

4

2 回答 2

6

虽然很有可能按照您编写和打算的方式进行操作,但有很多理由要避免经典继承(请参阅Classical Vs prototypal inheritance),并且有很多理由支持组合。让我们看看原型继承可能是什么:

var base = {
  get: function (resource, data, parameterOverrides) {
    return aPromisedLandOfDragons();
  },

  post: function (resource, data, parameterOverrides) {
    return aPromisedLandOfDragons();
  },

  put: function (resource, data, parameterOverrides) {
    return aPromisedLandOfDragons();
  },

  destroy: function (resource, data, parameterOverrides) {
    return aPromisedLandOfDragons();
  }
};

// Use a factory to instantiate instances:
function baseService(resource) {
  var instance = Object.create(base);
  instance.apiEndpoint = "/api/" + resource + "/";
  return instance;
}

var withAccount = {
  getAll: function(searchString) {
    // Uses the BaseService method. Lovely!
    return this.get(null, {
        searchString: searchString || ""
    });
  }
};

function accountService(resource) {
  var instance = mixIn({}, base, withAccount);
  instance.apiEndpoint = "/api/" + resource + "/";
  return instance;
}

这样做可以在以后提供更大的灵活性。如果您使用 Stampit 库,它会变得更加容易:

var base = stampit().methods({
  get: function (resource, data, parameterOverrides) {
    return aPromisedLandOfDragons();
  },

  post: function (resource, data, parameterOverrides) {
    return aPromisedLandOfDragons();
  },

  put: function (resource, data, parameterOverrides) {
    return aPromisedLandOfDragons();
  },

  destroy: function (resource, data, parameterOverrides) {
    return aPromisedLandOfDragons();
  }
}).enclose(function () {
  this.apiEndpoint = '/api/' + this.resource + '/';
  delete this.resource;
});

var withAccount = stampit().methods({
  getAll: function(searchString) {
    // Uses the BaseService method. Lovely!
    return this.get(null, {
        searchString: searchString || ""
    });
  }
});

var accountService = stampit.compose(base, withAccount);

// Watch it work:

var myAccountService = accountService({resource: 'foo'});
// { apiEndpoint: '/api/foo/' }
于 2013-09-10T08:28:11.933 回答
2

base看起来不错,并且可以从另一个(例如新)方法调用覆盖的方法

AccountService.prototype.get = function(resource, data, parameterOverrides) {
    …
    // this passes all arguments just as received:
    BaseService.prototype.get.apply(this, arguments);
    // or pass some parameters explicitly:
    BaseService.prototype.get.call(this, resource, data);
    …
}
于 2013-09-05T18:04:08.707 回答