Javascript 动态函数/对象名称
在研究我的框架时,我想到了一个想法。我正在使用$electid.hide来选择一个元素并对其进行处理。没什么问题。但是,如果我想更改选择器$elect并使用其他东西呢?我必须对文档中的每一个$elect进行罚款,并手动替换它们。那太无聊了。所以我在想,如果这样的事情是可能的:Javascript 动态函数/对象名称,javascript,frameworks,Javascript,Frameworks,在研究我的框架时,我想到了一个想法。我正在使用$electid.hide来选择一个元素并对其进行处理。没什么问题。但是,如果我想更改选择器$elect并使用其他东西呢?我必须对文档中的每一个$elect进行罚款,并手动替换它们。那太无聊了。所以我在想,如果这样的事情是可能的: var selector = $elect; // or anything else function [selector](id) { if (!(this instanceof [selector])) {
var selector = $elect; // or anything else
function [selector](id) {
if (!(this instanceof [selector])) {
return new [selector](id);
}
this.elm = document.getElementById(id);
}
[selector].prototype = {
hide: function () { this.elm.style.display = 'none'; return this; }
}
window.[selector] = [selector];
动态更改函数/对象名称。这将节省大量时间。如果其他人使用该框架,他们可以定义自己的选择器。那不是很好吗?有什么想法吗?我最喜欢的这个简单的通用模式怎么样
(function(){ //IIF constructor builder
(this[arguments[0]]= function(/*args*/){ //The constructor
/*constructor payload code*/
}).prototype= { //Methods & Properties to inherit:
method_1: function(){ /*your code*/ } //method 1
, method_2: function(){ /*your code*/ } //method 2
, property_1: /*your code*/ //property 1
, property_2: /*your code*/ //property 2
};
})(/*constructor identifier*/);
这将引用运行此生成函数的上下文。所以,如果构造函数生成器是针对窗口运行的,那么窗口将具有全局函数$elect。因此,您也可以在模块化系统中使用此模式
更新:
您已经询问了instanceof,根据您提供的代码判断,您需要它,以便在调用构造函数时可以省略new。这会让事情变得有点棘手
对我个人来说,‘用户’!='使用x库编写代码供用户使用的程序员和“程序员”应该知道何时使用新库。
虽然在开发过程中抛出new/console.log/alert error可能会很有用,但在最终最小化/优化的生产代码中应该不需要这样做,除非您的论点是您有许多可以省略的新语句,因此您的代码可以进一步缩小
首先,必须决定是否优化
执行速度和新代码的使用是否经常运行?:
if(/*called with new*/){
/*constructor payload code*/
} else {
/*error code*/
}
还是由于缺少新的、以执行速度为代价的最小文件大小代码只运行几次
if(!(/*called with new*/)){ /*error code*/ }
/*constructor payload code*/
请注意,如果您想要使用new,那么最后一个选项可能更实用,可以注释掉/删除生产代码,从而提供最快的执行速度
用new*/调用的行/*可以替换为arguments.callee的instanceof。虽然arguments.callee是一个很好的通用解决方案,因为没有硬编码/命名的内容,但如果“使用strict”,它将引发异常-模式,因为在John Resig中或根据John Resig的说法,由于某些原因,它现在已被弃用,因此将来也可以使用
,因此对于严格模式,我们可以在下面的示例中命名以前的匿名函数C
并检查此实例是否为C而不是参数的实例。被调用方:
如果/*错误代码*/仅通过以下方式防止静默错误:
alert/console.log/throw new Error“错误:忘记新建”
到目前为止,这种模式无论是严格的还是非严格的变体都是令人麻木的通用模式
如果您想通过向编码器返回正确的新对象(现在可选的警告除外)来“修复”调用,那么必须考虑传递给构造函数的参数(如果有)。
因此,对于不需要参数的构造函数,/*错误代码*/应该包含:
返回新参数.callee;对于非严格或
返回新的C;严格地
如果构造函数需要可选的命名参数,则您的/*错误代码*/应通过硬编码传递它们,如下所示:
返回新参数。calleerg_1、arg_2/*等…*/;对于非严格或
返回新的Carg_1、arg_2/*等;严格地
例如:
(function(){ //IIF constructor builder
(this[arguments[0]]= function C(id){ //The constructor
if(!(this instanceof C)) return new C(id); //Fix ID-10-T Error
this.elm= document.getElementById(id);
}).prototype= { //Methods & Properties to inherit:
show: function(){ //Method show
this.elm.style.display= '';
}
, hide: function(){ //Method hide
this.elm.style.display= 'none';
}
, toggle: function(){ //Method toggle
this[this.elm.style.display ? 'show' : 'hide']();
}
};
})('$elect');
我目前还不知道有一种简单而优雅的方法可以为firefox传递最多256个非硬编码的未知预期/可选/命名参数,而不是一个数组/对象作为第一个参数。问题是参数是一个类似数组的对象,所以不能像返回新的Carguments那样简单地传递它;
.apply-to-rescue您可能会想,因为它接受一系列参数作为第二个参数,而不像.call,它需要逗号分隔的参数,我们只是试图避免,但遗憾的是:new和apply/call不能一起使用。。。有人,如果你知道适合这种模式的优雅解决方案,请留言,谢谢
最后给出了上述模式的一个小变化和可能的应用。主要区别在于,此模式返回构造函数,因此您可以简单地命名引用它的变量,而不是直接设置构造函数的上述模式:
var myLibrary= {
$elect: (function(C){
(C= function(id){
if(!(this instanceof C)) return new C(id);
this.elm= document.getElementById(id);
}).prototype= {
addBorder: function(col){
this.elm.style.border='1px solid '+col;
}
, delBorder: function(){
this.elm.style.border='';
}
}; return C;
})()
, var_foo: 'foo'
, var_bar: 'bar'
};
希望这有帮助 因此,您希望将属性分配到原型中,但能够动态地选择要将这些属性添加到哪个对象的原型中,或者沿着这些线添加一些属性?类似的。嗯,我也应该能够更改构造函数的名称。使用选择器变量。这是一个很好的解决方案,但与其传入字符串,不如传入对象。例如,functionobj{obj=which;obj.prototype=which;}$elect@GitaarLAB能否在JSFIDLE中用一个方法展示代码的工作示例?@akinuri:done,请参阅更新的答案@JaniHartikainen:为什么这样更好,而且….,我不能让你的例子使用functionobj{obj=whater;obj.prototype=whater;}$elect;在预编var$elect时也不适用;或v ar$elect={};。你能详细说明一下你的方式吗?这两种模式之间的范围/结束链是否存在差异?
var myLibrary= {
$elect: (function(C){
(C= function(id){
if(!(this instanceof C)) return new C(id);
this.elm= document.getElementById(id);
}).prototype= {
addBorder: function(col){
this.elm.style.border='1px solid '+col;
}
, delBorder: function(){
this.elm.style.border='';
}
}; return C;
})()
, var_foo: 'foo'
, var_bar: 'bar'
};