JavaScript将作用域传递给另一个函数

问题描述 投票:34回答:12

是否可以以某种方式将一个函数的作用域传递给另一个函数?

例如:

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

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

我宁愿直接访问变量,也就是说,不使用任何类似于 this.athis.obj但只要用 xobj 直接使用。

javascript node.js closures scope serverside-javascript
12个回答
30
投票

真正获得功能的唯一途径 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();
    

这些都是你能够使用的唯一方法 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 的对象,该对象有获取器和设置器,可以访问 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();
    

    获取者和设置者可以是公共的,分配给了... 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();
    

    作为一种变化,你可以在调用时构造对象来代替:

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

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() 并不能直接访问所传递的函数所能访问的变量,而传递了引用的数据类型,比如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()

}

7
投票

那使用 bind

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

6
投票

不,你是在访问本地范围对象。

你正在访问本地范围对象。这个 [[Context]].

不能 公开访问它。

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


2
投票

正如其他人所说,你不能像这样传递作用域。然而你可以使用自执行的匿名函数(如果你很迂腐的话,也可以立即执行)正确地限定变量的范围。

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

a();

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
}

2
投票

你不能 "传递作用域"... 据我所知不是这样。你可以通过使用以下方法来传递函数所引用的对象 applycall 并将当前对象(this)作为第一个参数,而不是直接调用函数。

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

一个函数访问某个作用域的唯一方法 就是在该作用域中声明。这是一个棘手的问题。这将导致类似于.NET的东西。

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

但那会让我们的目的落空。


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

}

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

-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
   }
}

-3
投票

你可以创建你的变量而不需要 var 关键字,他们将是全局的,但没有办法传递我所知道的范围... ...

© www.soinside.com 2019 - 2024. All rights reserved.