我有一个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
,是否可以这样做,同时仍然能够调用基类的实现?
P.S:我知道技术上没有JavaScript中的类,但请耐心等待。
答案 0 :(得分: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/' }
答案 1 :(得分: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);
…
}