有名函数表达式全面解析(翻译教程)(5)

http://www.itjxue.com  2015-08-06 23:10  来源:未知  点击次数: 

可替代的解决方案

It’s worth mentioning that there actually exist alternative ways of having descriptive names in call stacks. Ways that don’t require one to use named function expressions. First of all, it is often possible to define function via declaration, rather than via expression. This option is only viable when you don’t need to create more than one function:

需要说明,实际上纯在一个种使得在调用栈上显示描述名称(函数名)的替代方法。一个不需要使用有名函数表达式的方法。首先,通常可以使用声明而不是使用表达式来定义函数。这种选择通常只是适应于你不需要创建多个函数的情况。

  var hasClassName = (function(){

    // 定义一些私有变量define some private variables
    var cache = { };

    //使用函数定义 use function declaration
    function hasClassName(element, className) {
      var _className = '(?:^|\\s+)' + className + '(?:\\s+|$)';
      var re = cache[_className] || (cache[_className] = new RegExp(_className));
      return re.test(element.className);
    }

    // 返回函数return function
    return hasClassName;
  })();

This obviously wouldn’t work when forking function definitions. Nevertheless, there’s an interesting pattern that I first seen used by Tobie Langel. The way it works is by defining all functions upfront using function declarations, but giving them slightly different identifiers:

这种方法显然对于多路的函数定义不适用。但是,有一个有趣的方法,这个方法我第一次在看到Tobie Langel.在使用。这个用函数声明定义所有的函数,但是给这个函数声明以稍微不同的标示符。

  var addEvent = (function(){

    var docEl = document.documentElement;

    function addEventListener(){
      /* ... */
    }
    function attachEvent(){
      /* ... */
    }
    function addEventAsProperty(){
      /* ... */
    }

    if (typeof docEl.addEventListener != 'undefined') {
      return addEventListener;
    }
    elseif (typeof docEl.attachEvent != 'undefined') {
      return attachEvent;
    }
    return addEventAsProperty;
  })();

While it’s an elegant approach, it has its own drawbacks. First, by using different identifiers, you loose naming consistency. Whether it’s good or bad thing is not very clear. Some might prefer to have identical names, while others wouldn’t mind varying ones; after all, different names can often “speak” about implementation used. For example, seeing “attachEvent” in debugger, would let you know that it is an attachEvent-based implementation of addEvent. On the other hand, implementation-related name might not be meaningful at all. If you’re providing an API and name “inner” functions in such way, the user of API could easily get lost in all of these implementation details.

虽然这是一个比较优雅的方法,但是他也有自己的缺陷。首先,通过使用不同的标示符,你失去的命名的一致性。这是件好的事情还是件坏的事情还不好说。有些人希望使用一支的命名,有些人则不会介意改变名字;毕竟,不同的名字通常代表不同的实现。例如,在调试器中看到“attachEvent”,你就可以知道是addEvent基于attentEvent的一个实现。另外一方面,和实现相关的名字可能根本没有什意义。如果你提供一个api并用如此方法命名内部的函数,api的使用者可能会被这些实现细节搞糊涂。

A solution to this problem might be to employ different naming convention. Just be careful not to introduce extra verbosity. Some alternatives that come to mind are:

解决这个问题的一个方法是使用不同的命名规则。但是注意不要饮用过多的冗余。下面列出了一些替代的命名方法

  `addEvent`, `altAddEvent` and `fallbackAddEvent`
  // or
  `addEvent`, `addEvent2`, `addEvent3`
  // or
  `addEvent_addEventListener`, `addEvent_attachEvent`, `addEvent_asProperty`

Another minor issue with this pattern is increased memory consumption. By defining all of the function variations upfront, you implicitly create N-1 unused functions. As you can see, if attachEvent is found in document.documentElement, then neither addEventListener nor addEventAsProperty are ever really used. Yet, they already consume memory; memory which is never deallocated for the same reason as with JScript’s buggy named expressions - both functions are “trapped” in a closure of returning one.

这种模式的另外一个问题就是增加了内存的开销。通过定义所有上面的函数变种,你隐含的创建了N-1个函数。你可以发现,如果attachEvent在document.documentElement中发现,那么addEventListener和addEventAsProperty都没有被实际用到。但是他们已经消耗的内存;和Jscript有名表达式bug的原因一样的内存没有被释放,在返回一个函数的同时,两个函数被‘trapped‘在闭包中。

This increased consumption is of course hardly an issue. If a library such as Prototype.js was to use this pattern, there would be not more than 100-200 extra function objects created. As long as functions are not created in such way repeatedly (at runtime) but only once (at load time), you probably shouldn’t worry about it.

这个递增的内存使用显然是个严重的问题。如果和Prototype.js类似的库需要使用这种模式,将有另外的100-200个多于的函数对象被创建。如果函数没有被重复地(运行时)用这种方式创建,只是在加载时被创建一次,你可能就不用担心这个问题。

(责任编辑:IT教学网)

更多

推荐Javascript/Ajax文章