3

在下面来自主干的片段中,这一行

(ev = events[i]).callback.call(ev.ctx);

不清楚。我想假设ev = events[i]之前解释过ev.ctx,因为该变量似乎没有其他目的,除了减少数组索引。

假设这是正确的,这样做是因为数组索引成本高吗?我知道在嵌入式工程中,当您使用有限的资源时,数组索引的成本很高。但我认为这在 JavaScript 中不是一个问题。

主干片段

triggerEvents = function(events, args) {
    var ev, 
        i = -1, 
        l = events.length;
    switch (args.length) {
        case 0: 
            while (++i < l) {
                (ev = events[i]).callback.call(ev.ctx);
            }
            return;
        case 1: 
            while (++i < l) {
               (ev = events[i]).callback.call(ev.ctx, args[0]);
            }
            return;
        case 2: 
            while (++i < l) { 
                (ev = events[i]).callback.call(ev.ctx, args[0], args[1]);
            }
            return;
        case 3: 
            while (++i < l) { 
                (ev = events[i]).callback.call(ev.ctx, args[0], args[1], args[2]);
            }
            return;
        default: 
            while (++i < l) {
                (ev = events[i]).callback.apply(ev.ctx, args);
            }
    }
};
4

1 回答 1

1

好的,使用treehugger.js 演示通过以下简化代码生成一个主干.js 方法的AST :

var ev, i = -1, l = 3;
while (++i < l) { 
  (ev = events[i]).callback.call(ev.ctx, args[0], args[1], args[2]);
}

产生这个 AST:

[
  VarDecls(
      [
        VarDecl("ev"),
        VarDeclInit(
            "i",
            PrefixOp(
                "-",
                Num("1")
            )
        ),
        VarDeclInit(
            "l",
            Num("3")
        )
      ]
  ),
  While(
      Op(
          "<",
          PrefixOp(
              "++",
              Var("i")
          ),
          Var("l")
      ),
      Block(
          [
            Call(
                PropAccess(
                    PropAccess(
                        Assign(
                            Var("ev"),
                            Index(
                                Var("events"),
                                Var("i")
                            )
                        ),
                        "callback"
                    ),
                    "call"
                ),
                [
                  PropAccess(
                      Var("ev"),
                      "ctx"
                  ),
                  Index(
                      Var("args"),
                      Num("0")
                  ),
                  Index(
                      Var("args"),
                      Num("1")
                  ),
                  Index(
                      Var("args"),
                      Num("2")
                  )
                ]
            )
          ]
      )
  )
]

虽然隐含的“更清洁”方法:

var ev, i = -1, l = 3;
while (++i < l) {
  ev = events[i];
  ev.callback.call(ev.ctx, args[0], args[1], args[2]);
}

产生这个 AST:

[
  VarDecls(
      [
        VarDecl("ev"),
        VarDeclInit(
            "i",
            PrefixOp(
                "-",
                Num("1")
            )
        ),
        VarDeclInit(
            "l",
            Num("3")
        )
      ]
  ),
  While(
      Op(
          "<",
          PrefixOp(
              "++",
              Var("i")
          ),
          Var("l")
      ),
      Block(
          [
            Assign(
                Var("ev"),
                Index(
                    Var("events"),
                    Var("i")
                )
            ),
            Call(
                PropAccess(
                    PropAccess(
                        Var("ev"),
                        "callback"
                    ),
                    "call"
                ),
                [
                  PropAccess(
                      Var("ev"),
                      "ctx"
                  ),
                  Index(
                      Var("args"),
                      Num("0")
                  ),
                  Index(
                      Var("args"),
                      Num("1")
                  ),
                  Index(
                      Var("args"),
                      Num("2")
                  )
                ]
            )
          ]
      )
  )
]

这两者之间的唯一区别是Assign()发生在内部,PropAccess()而在“更清洁”的方法中却发生在外部。它们的步数相同。您可以避免Assign所有这些并用第二个交换它Index。恐怕我对 JS 内部的了解不够,不知道这是否更快。我猜它取决于平台。

于 2013-02-19T21:52:47.733 回答