38

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

例如,

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

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

我宁愿直接访问变量,即不使用this.aor之类的东西this.obj,而直接使用xor obj

4

11 回答 11

34

真正访问 functiona的私有作用域的唯一方法是在b内部声明,a这样它就形成了一个允许隐式访问a's 变量的闭包。

这里有一些选项供您选择。

直接访问

  1. b在里面声明a

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

    function container() {
       var x, obj;
       function a(){
          x = 5;
          obj = {..};
          b();
       }
       function b(){
          // access x or obj...
       }
    }
    
    container.a();
    

这些是您能够a直接使用 's 变量的唯一方法,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. 您可以使用可以访问私有变量的getter 和 setter传递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();
    

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

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

    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();
    
于 2011-06-14T19:48:01.513 回答
9

作用域是由函数创建的,作用域与函数一起存在,因此最接近您所要求的是将函数从 to 传递出去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()

}
于 2011-06-14T19:47:18.250 回答
8

怎么用bind

function funcA(param) {     
    var bscoped = funcB.bind(this);     
    bscoped(param1,param2...)
}
于 2011-06-14T21:37:55.413 回答
6

不。

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

不能公开访问它。

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

于 2011-06-14T19:33:35.877 回答
3

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

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

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

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

但这会破坏目的。

于 2011-06-14T19:31:09.257 回答
2

正如其他人所说,你不能像那样通过范围。但是,您可以使用自执行匿名函数正确地确定变量的范围(或者如果您是迂腐的,则立即执行):

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

a();
于 2011-06-14T19:40:39.547 回答
2

我认为您可以做的最简单的事情是变量从一个范围传递到该范围之外的函数。如果您通过引用传递(如对象),则 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
}
于 2011-06-14T19:53:16.987 回答
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
于 2021-04-22T19:42:08.770 回答
-2
function a(){
   this.x = 5;
   this.obj = {..};
   var self = this;
   b(self);
}
function b(scope){
   //access x or obj....

}
于 2011-06-14T19:25:31.037 回答
-2
function a(){
   var x = 5;
   var obj = {..};
   var b = function()
   {
        document.println(x);
   }
   b.call();
}
于 2011-06-14T19:26:56.373 回答
-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
   }
}
于 2011-06-14T19:44:08.210 回答