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

时间:2011-06-14 19:20:18

标签: javascript node.js closures scope serverside-javascript

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

例如,

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

function b(){
   //access x or obj....
}

我希望直接访问变量,即不使用this.athis.obj之类的内容,而只是直接使用xobj

12 个答案:

答案 0 :(得分:26)

真正访问函数a的私有范围的唯一方法是在b内声明a,以便形成一个允许隐式访问a的闭包变量。

以下是一些选项。

直接访问

  1. b内声明a

    function a() {
       var x = 5,
          obj = {};
       function b(){
          // access x or obj...
       }
       b();
    }
    
    a();
    
  2. 如果您不希望b位于a内,那么您可以将它们放在更大的容器范围内:

    function container() {
       var x, obj;
       function a(){
          x = 5;
          obj = {..};
          b();
       }
       function b(){
          // access x or obj...
       }
    }
    
    container.a();
    
  3. 这些是您可以直接在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();
      

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

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

      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();
      

      getter和setter可以是公开的,分配给this的{​​{1}}对象,但这样只有在a内明确发出时才能访问它们。

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

      a

      作为变体,您可以在呼叫时构建对象:

      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();
      

答案 1 :(得分: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()

}

虽然b()无法直接访问函数传递的变量,但是如果传递的函数返回那个对象。

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()

}

答案 2 :(得分:6)

没有

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

无法公开访问它。

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

答案 3 :(得分:6)

使用bind

怎么样?
function funcA(param) {     
    var bscoped = funcB.bind(this);     
    bscoped(param1,param2...)
}

答案 4 :(得分:2)

你不能“超越范围”......不是我所知道的。
您可以使用applycall传递函数所引用的对象,并将当前对象(this)作为第一个参数发送,而不是仅调用函数:

function b(){
    alert(this.x);
}
function a(){
    this.x = 2;
    b.call(this);
}

函数访问某个范围的唯一方法是在该范围内声明 有点棘手。
这将导致类似:

function a(){
    var x = 1;
    function b(){
        alert(x);
    }
}

但那会破坏目的。

答案 5 :(得分:2)

正如其他人所说,你无法通过这样的范围。但是,您可以使用自动执行匿名函数来正确调整变量范围(如果您是迂腐的话,可以立即执行):

(function(){
    var x = 5;
    var obj = {x:x};
    module.a = function(){
        module.b();
    };
    module.b = function(){
        alert(obj.x);    
    };
}());

a();

答案 6 :(得分:2)

我认为可以做的最简单的事情是变量从一个范围传递到该范围之外的函数。如果你通过引用传递(比如Objects),b '访问'它(参见下面的obj.someprop):

function a(){
   var x = 5;
   var obj = {someprop : 1};
   b(x, obj);
   alert(x); => 5
   alert(obj.someprop); //=> 'otherval'
}
function b(aa,obj){
   x += 1; //won't affect x in function a, because x is passed by value
   obj.someprop = 'otherval'; //change obj in function a, is passed by reference
}

答案 7 :(得分:1)

你真的只能用 eval 来做到这一点。下面将给出函数 b 函数 a 的作用域

  function a(){
     var x = 5;
     var obj = {x};
     eval('('+b.toString()+'())');
  }
  
  function b(){
     //access x or obj....
     console.log(x);
  }
  
  a();  //5

答案 8 :(得分:-1)

function a(){
   this.x = 5;
   this.obj = {..};
   var self = this;
   b(self);
}
function b(scope){
   //access x or obj....

}

答案 9 :(得分:-1)

function a(){
   var x = 5;
   var obj = {..};
   var b = function()
   {
        document.println(x);
   }
   b.call();
}

答案 10 :(得分:-2)

您可以在没有var关键字的情况下创建变量,它们将是全局的,但无法通过我所知道的范围......

答案 11 :(得分:-2)

你有没有试过这样的事情:

function a(){
   var x = 5;
   var obj = {..};
   b(this);
}
function b(fnA){
   //access x or obj....
   fnA.obj = 6;
}

如果您可以将功能B作为方法功能A,那么请执行以下操作:

function a(){
   var x = 5;
   var obj = {..};
   b(this);

   this.b = function (){
      // "this" keyword is still === function a
   }
}