(免责声明:删除了导致一些新的基本问题的先前问题,因此再次尝试更明智的问题)。
我有一个具有一些必需初始化属性的类:
var CustomRequest = require('./request'),
ok = require('objectkit'),
helpers = require('../helpers')
var MySDKClient = function(orgId, appId) {
var self = this
if (ok(orgId).exists() && ok(appId).exists()) {
self.orgId = orgId
self.appId = appId
return self
} else {
throw new Error('orgId and appId must be passed during initialization')
}
}
MySDKClient.prototype = {
GET: function(uri, options, callback) {
return new CustomRequest('GET', uri, options, callback)
}
}
// Exports
module.exports = MySDKClient
这样就像这样:
var MySDKClient = require('./lib/client')
var client = new MySDKClient('orgId', 'appId')
但是我需要将它包装在 new 类中,它包含MySDKClient
的单个实例并继承其所有方法/属性。我们称之为MySDK
,它需要有一个自定义初始化方法:
var MySDK = require('./mysdk')
MySDK.initialize('orgId', 'appId')
module.exports = MySDK
(或不太喜欢):
var MySDK = require('./lib/client').initialize('orgId', 'appId')
module.exports = MySDK
如果初始化方法有MySDKClient
,我希望它无法通过throw
中的MySDKClient
初始化(因此无法调用任何var MySDK = require('./lib/client')
MySDK.initialize('orgId', 'appId')
MySDK.GET('...') // should work!
方法)没被打电话。
例如,这应该有效:
var MySDK = require('./lib/client')
MySDK.GET('...') // should throw error because of 'throw new Error()`
// that already exists in MySDKClient -- more accurately,
// MySDK should be null or undefined because it wasn't initialized.
这不应该:
util.inherits()
我该怎么做?我尝试使用Object.create()
和// mysdk.js
var MySDKClient = require('./lib/client'),
ok = require('objectkit'),
helpers = require('./helpers'),
util = require("util")
function MySDK() {
// new MySDKClient?
}
MySDK.prototype = {
initialize: function(orgId, appId) {
return new MySDKClient(orgId, appId)
}
}
// Should I still be doing this?
// util.inherits(MySDK, MySDKClient)
// Exports
module.exports = new MySDK
来创建子类',但无论我做什么,MySDKClient类的原型方法都不是&n;无论客户端是否已正确初始化,它们都可以使用。
更新:尝试@ sg.cc的解决方案,MySDKClient的行为与以前相比更好/更少,但我仍然无法在模块中正确启动MySDK实例:
var MySDK = require('./mysdk')
MySDK.initialize('peter', 'wolf')
MySDK.GET() // undefined is not a function
致电:
{{1}}
答案 0 :(得分:2)
你需要停止思考类,并开始接受javascript的原型继承。另外,请尝试将代码片段简化为最低限度,以便于重现。
我简化了您的再现性示例,但以下内容应指向正确的方向:
这是我简化的MySDKClient构造函数:
var MySDKClient = function(orgId) { this.orgId = orgId; }
MySDKClient.prototype.GET = function() { alert(this.orgId); }
您的MySDK不一定是构造函数(如果您愿意,也可以是class
):
var MySDK = {
initialize: function(orgId) {
Object.setPrototypeOf(MySDK, new MySDKClient(orgId))
}
}
在控制台中试用:
MySDK.GET()
会抛出错误,因为当解释器走向MySDK的原型链时,它找不到GET函数。
现在,如果您调用MySDK.initialize(10);
,则会修改对象的原型链以包含MySDKClient。现在如果你运行MySDK.GET()
,你会看到10被警告。
虽然Object.setPrototypeOf
是对javascript的新增功能,但使用polyfill可以使用非常简单的Object.prototype.__proto__
,可用于几乎所有主要平台
答案 1 :(得分:1)
var CustomRequest = require('./request'),
ok = require('objectkit'),
helpers = require('../helpers')
var MySDKClient = function(org, app){
return (function init(orgId, appId) {
var init = false;
if( ok(orgId).exists() && ok(appId).exists() ) {
this.orgId = orgId;
this.appId = appId;
init = true;
} else {
throw new Error('orgId and appId must be passed during initialization')
}
if( !init ) return;
return {
GET: function(uri, options, callback){
// Where are you using orgId that customRequest needs to fail if they aren't present?
return new CustomRequest('GET', uri, options, callback);
}
}
})(org, app);
}
module.exports = MySDKClient;
测试:
var MySDK = require('./lib/client');
var a = MySDK(123, abc);
var b = MySDK(); // -> Exception thrown
a.GET(some, args, here); // Works
b.GET(some, args, here); // property GET of undefined is not a function