JavaScript将范围传递给另一个函数

cio*_*Pep 33 javascript closures scope serverside-javascript node.js

是否有可能以某种方式将函数的范围传递给另一个函数?

例如,

function a(){
   var x = 5;
   var obj = {..};
   b(<my-scope>);
}

function b(){
   //access x or obj....
}
Run Code Online (Sandbox Code Playgroud)

我宁愿直接访问的变量,即不使用任何类似this.a或者this.obj,只是使用xobj直接.

Eri*_*ikE 28

真正获取函数a私有作用域的唯一方法是在b内部声明,a这样就形成了一个允许隐式访问a变量的闭包.

这里有一些选择.

直接访问

  1. b在里面宣布a.

    function a() {
       var x = 5,
          obj = {};
       function b(){
          // access x or obj...
       }
       b();
    }
    
    a();
    
    Run Code Online (Sandbox Code Playgroud)
  2. 如果您不想b在里面a,那么您可以将它们放在更大的容器范围内:

    function container() {
       var x, obj;
       function a(){
          x = 5;
          obj = {..};
          b();
       }
       function b(){
          // access x or obj...
       }
    }
    
    container.a();
    
    Run Code Online (Sandbox Code Playgroud)

这些是你能够a直接使用变量b而没有一些额外代码来移动的唯一方法.如果您满足于一些"帮助"和/或间接,那么这里有一些想法.

间接访问

  1. 您可以将变量作为参数传递,但除了对象属性之外不会具有写访问权限:

    function a() {
       var x = 5,
          obj = {};
       b(x, obj);
    }
    
    function b(x, obj){
       // access x or obj...
       // changing x here won't change x in a, but you can modify properties of obj
    }
    
    a();
    
    Run Code Online (Sandbox Code Playgroud)

    作为对此的变体,您可以通过将更新的值传回到如下所示来获得写访问权限a:

    // in a:
    var ret = b(x, obj);
    x = ret.x;
    obj = ret.obj;
    
    // in b:
    return {x : x, obj : obj};
    
    Run Code Online (Sandbox Code Playgroud)
  2. 您可以b使用可以访问a私有变量的getter和setter 传递一个对象:

    function a(){
       var x = 5,
          obj = {..},
          translator = {
             getX : function() {return x;},
             setX : function(value) {x = value;},
             getObj : function() {return obj;},
             setObj : function(value) {obj = value;}
          };
       b(translator);
    }
    
    function b(t){
       var x = t.getX(),
          obj = t.getObj();
    
       // use x or obj...
       t.setX(x);
       t.setObj(obj);
    
       // or you can just directly modify obj's properties:
       obj.key = value;
    }
    
    a();
    
    Run Code Online (Sandbox Code Playgroud)

    getter和setter可以是公共的,分配给this对象a,但是这样只有从内部明确地给出它们才能访问它们a.

  3. 您可以将变量放在一个对象中并传递对象:

    function a(){
       var v = {
          x : 5,
          obj : {}
       };
       b(v);
    }
    
    function b(v){
       // access v.x or v.obj...
       // or set new local x and obj variables to these and use them.
    }
    
    a();
    
    Run Code Online (Sandbox Code Playgroud)

    作为变体,您可以在调用时构造对象:

    function a(){
       var x = 5,
          obj = {};
       b({x : x, obj: obj});
    }
    
    function b(v){
       // access v.x or v.obj...
       // or set new local x and obj variables to these and use them.
    }
    
    a();
    
    Run Code Online (Sandbox Code Playgroud)


use*_*716 8

范围是由函数创建的,并且范围与函数保持一致,因此与您要求的最接近的是将函数传递a()b(),并且该函数将继续访问范围变量a().

function a(){
   var x = 5;
   var obj = {..};
   b(function() { /* this can access var x and var obj */ });
}
function b( fn ){

    fn(); // the function passed still has access to the variables from a()

}
Run Code Online (Sandbox Code Playgroud)

虽然b()没有直接访问函数传递的变量,但是如果传递的函数返回该对象,则可以访问传递引用的数据类型,如Object .

function a(){
   var x = 5;
   var obj = {..};
   b(function() { x++; return obj; });
}
function b( fn ){

    var obj = fn();
    obj.some_prop = 'some value'; // This new property will be updated in the
                                  //    same obj referenced in a()

}
Run Code Online (Sandbox Code Playgroud)


Ray*_*nos 6

没有.

您正在访问本地范围对象.的[[Context]].

无法公开访问它.

现在,因为它是node.js,你应该能够编写一个C++插件,让你可以访问该[[Context]]对象.我强烈建议不要这样做,因为它带来了JavaScript语言的专有扩展.

  • downvote的任何理由?如果您可以访问`[[Context]],请_do_让我知道. (2认同)

vit*_*ore 6

怎么样使用 bind

function funcA(param) {     
    var bscoped = funcB.bind(this);     
    bscoped(param1,param2...)
}
Run Code Online (Sandbox Code Playgroud)