gpt4 book ai didi

javascript - 改进插件架构的实现

转载 作者:搜寻专家 更新时间:2023-11-01 04:32:02 26 4
gpt4 key购买 nike

我的库中包含一个扩展方法,可以将方法添加到核心库中:

library.prototype.extend = function(name,plugin) {

library.prototype[name] = plugin.init;

for (var method in plugin) {

if(method !== 'init') {

library.prototype[name].prototype[method] = plugin[method];

}

}

};

在使用中它看起来像这样:

library.prototype.extend('aReallyInterestingPlugin', {

//the init method gets added to the base libraries prototype
init: function() {

this.shouldBePrivate;

},

//another other methods are created as a prototype of the newly added Plugin
anotherMethod : function() {
//this should have access to the shouldBePrivate var
}
});

然后用户可以像这样调用插件:

var test = new library();
test.aReallyInterestingPlugin();

这行得通,但我对这种方法并不十分满意,并且一直在尝试寻找一种替代模式来使它行得通。

它的问题是,init 和 anotherMethod 被直接添加到库原型(prototype)链中,因此它们的作用域也是全局库作用域,这很困惑,因为如果声明了任何实例变量(如上面的 shouldBePrivate),它们也是添加到库原型(prototype)链。

我怎样才能启用要添加的插件并拥有它自己的私有(private)范围?我想到的一种方法是,插件始终可以作为构造函数调用(因此将拥有自己的作用域和 this 上下文)但是我不确定那有多干净......例如它是否可以工作用户在调用插件时必须做这样的事情:

var test = new library();
test.aPlugin = new aReallyInterestingPlugin();

最佳答案

你可以做的是将插件方法绑定(bind)到一个新对象,这样它们就不会“污染”库。
但是与其将插件作为库实例的方法,不如将其作为惰性 getter,因此语法更加流畅,并且您可以仅在需要时构建新实例。
然后可以简化插件语法:只需使用一个 javascript 类 => 一个在其原型(prototype)上定义了方法的函数。
我还认为将“扩展”作为库的属性而不是在其原型(prototype)上设置的方法是有意义的,因为任何实例都不应该使用它。

有了这个你可以添加一个插件

library.extend('aReallyInterestingPlugin',AReallyInterestingPluginClass);

使用你可以写

var myLibrary = new Library();

myLibrary.somePlugin.someMethod(arg1, arg2, ...);

代码看起来像:

library.extend = function(name,plugin) {    
var pluginInstance = null; // lazy evaluation to avoid useless memory consumption

var pluginGetter = function() {
if (pluginInstance == null) pluginInstance = new plugin();
return pluginInstance; };

Object.defineProperty( Library.prototype, name,
{ get: pluginGetter, enumerable : true } );
} ;

插件只是标准的 javascript 类:

 function MyPlugin() {
this.pluginProperty1 = 'some value';
}

MyPlugin.prototype = {
method1 : function() { /* do things */} ,
method2 : function() { /* do other things */ }
};

请注意,在这个方案中,插件是单例的,即当请求相同的插件时,每个 Library 实例都将返回相同的对象。

如果您更喜欢每个库一个插件实例,只需让库构造函数保存插件实例即可。 (也许在隐藏的属性中)。

function Library() {
// the code allready here...
var pluginInstances = {};
Object.defineProperty(this, 'pluginInstances',
{ get : function() { return pluginInstances }, enumerable : false });
}

library.extend = function(name,plugin) {
var pluginGetter = function() {
if (! this.pluginInstances[name] ) this.pluginInstances[name] = new plugin();
return this.pluginInstances[name];
};

Object.defineProperty( Library.prototype, name,
{ get: pluginGetter, enumerable : true } );
} ;

插件和使用的语法保持不变。

编辑:对于旧的浏览器支持,您仍然可以使用函数而不是 getter:

function Library() {
// the code allready here...
this.pluginInstances= {} ;
}

library.extend = function(name,plugin) {
Library.prototype[name] = function() {
if (! this.pluginInstances[name] ) this.pluginInstances[name] = new plugin();
return this.pluginInstances[name];
};
} ;

要使用它你会这样做:

var myLibrary = new Library();

myLibrary.somePlugin().someMethod(arg1, arg2, ...);

编辑 2:带有单例插件且没有 setter/getter 的版本是:

 function Library() {        /* same code */    }

library.extend = function(name,plugin) {
var pluginInstance = null; // lazy evaluation to avoid useless memory consumption
Library.prototype[name] = function() {
if (pluginInstance == null) pluginInstance = new plugin();
return pluginInstance; };
}

关于javascript - 改进插件架构的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20460083/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com