用perl来解释JS闭包

nov*_*cik 4 javascript perl

我理解没有任何问题,perl闭包是如何工作的,就像下一个

use 5.012;
use strict;
use warnings;

sub countdown {
        my $start = shift;
        return sub { $start-- }
}

my $c10 = countdown(3);
say while( $_ = $c10->() );
Run Code Online (Sandbox Code Playgroud)

我正在尝试理解下一段Javascript:

var runInSandbox = (function(js, inputPath) {

  (function() {
    if ((!context.initialized__QUERY)) {
      return createContext();
    };
  })();
  (function() {
    if (typeof(inputPath) !== 'undefined') {
      (process.argv)[1] = inputPath;;
      (context)["__dirname"] = path.dirname(inputPath);;
      return (module)["filename"] = inputPath;;
    };
  })();
  return vm.runInContext(js, context, "sibilant");
});
Run Code Online (Sandbox Code Playgroud)

没有机会!:( 有人可以将上面的内容重写为 perl吗?我知道perl有点 - 所以对我来说理解JS基础知识和结构非常有用:

(...)() - more precisely
(function(){.....})()
Run Code Online (Sandbox Code Playgroud)

((在if中加倍

    if ((!context.initialized__QUERY)) {
Run Code Online (Sandbox Code Playgroud)

或者下一个

      (context)["__dirname"] = something ;;
Run Code Online (Sandbox Code Playgroud)

要么

       return (module)["filename"] = inputPath;; // why double ;;?
Run Code Online (Sandbox Code Playgroud)

如果有人向我建议任何类似的资源:Learning Javascript for perl programmers- 会非常好;)

Ps:JS(缩写)来自这里:https://github.com/jbr/sibilant/blob/master/lib/cli.js

Viv*_*ath 7

我对Perl的封闭并不是非常精通,所以我至少会试着为你揭开神秘面纱.

表格:

(function(...) {
 ...
})();
Run Code Online (Sandbox Code Playgroud)

是一个自我调用的匿名函数1.这意味着您编写了一个匿名函数,然后立即调用它.这通常用于封装2.例如,如果您最终创建了一堆变量,但又不希望它污染全局命名空间,则可以将其置于匿名的自调用函数中.但是,在这种情况下,我不明白为什么第一次调用是必要的,因为它只是检查一个标志或什么.更奇怪的是return这些自我调用的函数内部.他们没有被分配任何东西.我会冒险猜测createContext()初始化context变量,但return那里实际上是没用的.以下情况也是如此:

return (module)["filename"] = inputPath;;
Run Code Online (Sandbox Code Playgroud)

至于双(()),他们似乎在很大程度上是不必要的,所以我不知道为什么笔者最初把它放在那里.例如:

if ((!context.initialized__QUERY)) 
Run Code Online (Sandbox Code Playgroud)

与以下内容没有任何不同:

if (!context.initialized__QUERY) 
Run Code Online (Sandbox Code Playgroud)

此外,以下括号也是不必要的,双分号也是如此:

(context)["__dirname"] = something ;;
Run Code Online (Sandbox Code Playgroud)

老实说,它只是看起来写得不好的Javascript,或者是自动生成的JavaScript(这很可能就是这种情况).

你可以像这样重写它:

var runInSandbox = function(js, inputPath) {

    if (!context.initialized__QUERY) {
       createContext();
    };

    if (typeof inputPath !== 'undefined') {
       process.argv[1] = inputPath;
       context["__dirname"] = path.dirname(inputPath);
       module["filename"] = inputPath;
    };

    return vm.runInContext(js, context, "sibilant");
};
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 在Perl中,那就是sub { ... }->().
  2. 在Perl中,一个会用{ my $var; ... },而不是sub { my $var; ... }->()do { my $var; ...; EXPR }代替sub { my $var; ...; return EXPR; }->().