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

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

调试器中的函数名

When a function has a corresponding identifier, debuggers show that identifier as a function name, when inspecting call stack. Some debuggers (e.g. Firebug) helpfully show names of even anonymous functions - making them identical to names of variables that functions are assigned to. Unfortunately, these debuggers usually rely on simple parsing rules; Such extraction is usually quite fragile and often produces false results.

当一个函数有一个相应的标示符的时候,当检查调用堆栈的时候调试器把这个标示符显示为函数名。有些调试器(例如Firebug)将显示甚至是匿名函数的名称,使他们的名字和函数被赋值给的变量的名字一致。不幸的是,这些调试器通常依赖于简单的解释规则;这些提取出来的名称通常是非常不稳定的,而且通常产生错误的结果

Let’s look at a simple example:

让我们看一个简单的例子

  function foo(){
    return bar();
  }
  function bar(){
    return baz();
  }
  function baz(){
    debugger;
  }
  foo();

  // 这里我们用函数声明来定义所有3个函数Here, we used function declarations when defining all of 3 functions
  // 当调试器停止在`debugger`语句的时候When debugger stops at the `debugger` statement,
  //调用堆栈看上去非常具有描述性的 the call stack (in Firebug) looks quite descriptive:
  baz
  bar
  foo
  expr_test.html()

We can see that foo called bar which in its turn called baz (and that foo itself was called from the global scope of expr_test.html document). What’s really nice, is that Firebug manages to parse the “name” of a function even when an anonymous expression is used:

我们看以看到,foo调用bar,bar调用baz,foo本身是从expr_test.html的全局作用域中被调用的。Firebug非常突出的一点是即是使用一个匿名的表达式,他都试图去解释函数名

  function foo(){
    return bar();
  }
  var bar = function(){
    return baz();
  }
  function baz(){
    debugger;
  }
  foo();

  // 调用堆栈Call stack
  baz
  bar()
  foo
  expr_test.html()

What’s not very nice, though, is that if a function expression gets any more complex (which, in real life, it almost always is) all of the debugger’s efforts turn out to be pretty useless; we end up with a shiny question mark in place of a function name

但是调试器还不是很完美,当函数表达式变得非常复杂的时候,这些调试器就很难去解释这些函数名,通常是以一个问号来代替函数名

  function foo(){
    return bar();
  }
  var bar = (function(){
    if (window.addEventListener) {
      return function(){
        return baz();
      }
    }
    else if (window.attachEvent) {
      return function() {
        return baz();
      }
    }
  })();
  function baz(){
    debugger;
  }
  foo();

  // Call stack
  baz
  (?)()
  foo
  expr_test.html()

Another confusion appears when a function is being assigned to more than one variable:

另外一个令人迷惑的事情是,当一个函数被赋值给不止一个变量

  function foo(){
    return baz();
  }
  var bar = function(){
    debugger;
  };
  var baz = bar;
  bar = function() {
    alert('spoofed');
  }
  foo();

  // Call stack:
  bar()
  foo
  expr_test.html()

You can see call stack showing that foo invoked bar. Clearly, that’s not what has happened. The confusion is due to the fact that baz was “exchanged” references with another function - the one alerting “spoofed”. As you can see, such parsing - while great in simple cases - is often useless in any non-trivial script.

你可以看到调用栈显示foo调用bar。显然,刚才发生地不是这样。引起这种困惑是因为baz引用了另外一个函数---提示 “spoofed”的那个函数。就如你所看到的,这些解释虽然在简单的情况下非常有用,但是在复杂的脚本中却基本上没什么用。

What it all boils down to is the fact that named function expressions is the only way to get a truly robust stack inspection. Let’s rewrite our previous example with named functions in mind. Notice how both of the functions returning from self-executing wrapper, are named as bar:

归根结底,有名函数表达式实际上是得到真正的调用栈检查的唯一方法。让我们用有名函数表达式来重写我们前面的例子。请注意,两个从自执行包裹中返回的函数都有名为bar

  function foo(){
    return bar();
  }
  var bar = (function(){
    if (window.addEventListener) {
      return function bar(){
        return baz();
      }
    }
    else if (window.attachEvent) {
      return function bar() {
        return baz();
      }
    }
  })();
  function baz(){
    debugger;
  }
  foo();

  // And, once again, we have a descriptive call stack!
  baz
  bar
  foo
  expr_test.html()

Before we start dancing happily celebrating this holy grail finding, I’d like to bring a beloved JScript into the picture.

在我们开始跳舞庆祝找到这个方法之前,我们还是先来看看JScript中的情况是如何的

JScript bugs

Unfortunately, JScript (i.e. Internet Explorer’s ECMAScript implementation) seriously messed up named function expressions. JScript is responsible for named function expressions being recommended against by many people these days.

不幸的是,JScript(也就是EcMAScript的IE实现)处理有名函数表达式却非常糟糕。JScript应对有名函数表达式不被很多人推荐负责

Let’s look at what exactly is wrong with its broken implementation. Understanding all of its issues will allow us to work around them safely. Note that I broke these discrepancies into few examples - for clarity - even though all of them are most likely a consequence of one major bug.

让我们来看看这个ECMASCript的不好的实现中都有什么问题。理解所有这些问题将使我们可以安全的使用它。虽然下面的这些例子都很可能是一个主要的bug的结果,但是为了清晰起见,我把这些差异分为了几个例子。

(责任编辑:IT教学网)

更多

推荐Javascript/Ajax文章