javascript - 动态函数/对象名称

标签 javascript frameworks

在我的框架上工作时,我想到了一个想法。我正在使用 $elect(id).hide()选择一个元素并用它做一些事情。没有错。但是如果我想更改选择器 $elect() 怎么办?并使用其他东西?我必须罚款每个 $elect在文档中并手动替换所有这些。那很无聊。所以我在想这样的事情是否可行:

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*/);
this将引用运行此构建功能的上下文。因此,如果构造函数生成器针对 window 运行,然后 window将具有全局函数 $elect .所以你也可以在你的模块化系统中使用这个模式。

更新:
您已询问 instanceof (根据您提供的代码判断,您需要它以便在调用构造函数时可以省略 new)。这会使事情变得更加棘手。

对我个人而言,'users' !== 'coders' 和 'coders'(编写代码(使用 x 库)供用户使用)应该知道何时使用 new .
虽然它可能对 throw new 有用/console.log/alert开发过程中的错误,在最终(最小化/优化)生产代码中应该不需要这个(除非你的论点是你有很多 new 可以省略的语句,所以你的代码甚至可以被缩小进一步)。

第一个必须决定是否优化new 的执行速度和使用(代码经常运行?):
if(/*called with new*/){ 
    /*constructor payload code*/ 
} else { 
    /*error code*/ 
}

或因缺少 new 而导致的最小文件大小以执行速度为代价(代码只运行几次?):
if(!(/*called with new*/)){ /*error code*/ } 
/*constructor payload code*/

请注意,如果您打算要求使用 new,则最后一个选项对于生产代码的注释/删除也可能更实用。 ,给出最快的执行速度。

/*called with new*/可以替换为 this instanceof arguments.callee虽然 arguments.callee是一个很好的通用解决方案(因为没有硬编码/命名),如果您 'use strict';,它将引发异常-mode,因为它现在在 favor of named function expressions 中已被弃用(出于某种原因) (根据 John Resig 的说法,将来也可以使用 expression this function )。

MDN specifies that a function name can be used only within the function's body ,所以对于严格模式,我们可以命名我们的(以前是匿名的)函数(C 在下面的例子中)
并检查 this instanceof C (而不是 this instanceof arguments.callee ):
(function(){                                  //IIF constructor builder
   (this[arguments[0]]= function C(id){       //The constructor
      if(!(this instanceof C)){ /*error code*/ }  //Catch ID-10-T Error
      /*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
   };
})('$elect');

如果 /*error code*/仅通过以下方式防止静默错误:alert/console.log/throw new Error ('Error: forgot new')然后到现在为止,这种模式(严格和非严格的变体)是令人 NumPy 的通用。

如果您想通过返回正确的新对象(除了现在对编码器的可选警告)来“修复”调用,那么必须考虑传递给构造函数的参数(如果有的话)。
所以对于不期望参数的构造函数,你的 /*error code*/应包含:return new arguments.callee();对于非严格或return new C();为严格
期望(可选)命名参数的构造函数,您的 /*error code*/应该像这样通过硬编码传递它们:return new arguments.callee(arg_1, arg_2 /*,etc..*/);对于非严格或return new C(arg_1, arg_2 /*,etc..*/);为严格

例如:
(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 个)非硬编码未知(预期/可选/命名)参数(缺少一个数组/对象作为第一个参数)。问题是 arguments是一个数组(类)对象,所以不能像 return new C(arguments); 那样简单地传递它.apply()为了救援,人们可能会想,因为它接受一组参数作为第二个参数(不像 .call() 需要逗号分隔的参数,我们只是试图避免),但是唉:newapply/call不能一起用1 , 2 ...(有人,如果您知道适合此模式的优雅解决方案,请发表评论,谢谢)

最后是上述模式的一个小变化(和可能的应用)。主要区别在于此模式返回一个构造函数(因此您可以简单地命名引用它的变量)(而不是上述直接设置构造函数的模式):
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'
};

Example fiddle here .

希望这可以帮助!

关于javascript - 动态函数/对象名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18945606/

相关文章:

php - 如何使用 composer 安装 Zend Framework 2 工具

xcode - 将二进制文件与库链接 VS 嵌入框架

javascript - 如何使用backbone.js中的事件对象触发事件

javascript - 如何使用 Javascript 更改 PHP 变量的值?

php - 如何防止 Internet Explorer 重写我的文本?

PHP 身份验证/ session 处理 : Ground Up or Framework/Package?

ios - 未找到自动链接框架

javascript - AngularJS ng-repeat 获取单击的按钮的索引并在 jquery 中使用

javascript - 如何使用 Javascript/jQuery 隐藏/显示启用/禁用 HTML 元素?

php - 一个 Web 框架,其中 AJAX 不是事后的想法